M gnot/dat.h => gnot/dat.h +1 -0
@@ 68,6 68,7 @@ struct Conf
{
int nmach; /* processors */
int nproc; /* processes */
+ int monitor; /* has display */
ulong npage0; /* total physical pages of memory, bank 0 */
ulong npage1; /* total physical pages of memory, bank 1 */
ulong npage;
M gnot/main.c => gnot/main.c +1 -0
@@ 308,6 308,7 @@ confinit(void)
conf.nmach = 1;
if(conf.nmach > MAXMACH)
panic("confinit");
+ conf.monitor = 1;
bank[0] = banksize(0);
bank[1] = banksize(16);
conf.npage0 = (bank[0]*MB)/BY2PG;
M pc/dat.h => pc/dat.h +1 -0
@@ 64,6 64,7 @@ struct Conf
{
ulong nmach; /* processors */
ulong nproc; /* processes */
+ ulong monitor; /* has monitor? */
ulong npage0; /* total physical pages of memory */
ulong npage1; /* total physical pages of memory */
ulong topofmem; /* highest physical address + 1 */
M pc/main.c => pc/main.c +1 -0
@@ 246,6 246,7 @@ confinit(void)
/* for meminit() */
conf.topofmem = i*MB;
+ conf.monitor = 1;
conf.nproc = 30 + i*5;
conf.nswap = conf.nproc*80;
conf.nimage = 50;
M port/devbit.c => port/devbit.c +26 -0
@@ 247,6 247,8 @@ bitreset(void)
ulong r;
Arena *a;
+ if(!conf.monitor)
+ return;
bit.map = smalloc(DMAP*sizeof(GBitmap*));
bit.nmap = DMAP;
getcolor(0, &r, &r, &r);
@@ 286,6 288,8 @@ bitreset(void)
void
bitinit(void)
{
+ if(!conf.monitor)
+ return;
if(gscreen.ldepth > 3)
cursorback.ldepth = 0;
else{
@@ 298,12 302,16 @@ bitinit(void)
Chan*
bitattach(char *spec)
{
+ if(!conf.monitor)
+ error(Egreg);
return devattach('b', spec);
}
Chan*
bitclone(Chan *c, Chan *nc)
{
+ if(!conf.monitor)
+ error(Egreg);
nc = devclone(c, nc);
if(c->qid.path != CHDIR)
incref(&bit);
@@ 313,12 321,16 @@ bitclone(Chan *c, Chan *nc)
int
bitwalk(Chan *c, char *name)
{
+ if(!conf.monitor)
+ error(Egreg);
return devwalk(c, name, bitdir, NBIT, devgen);
}
void
bitstat(Chan *c, char *db)
{
+ if(!conf.monitor)
+ error(Egreg);
devstat(c, db, bitdir, NBIT, devgen);
}
@@ 327,6 339,8 @@ bitopen(Chan *c, int omode)
{
GBitmap *b;
+ if(!conf.monitor)
+ error(Egreg);
switch(c->qid.path){
case CHDIR:
if(omode != OREAD)
@@ 378,6 392,8 @@ bitopen(Chan *c, int omode)
void
bitcreate(Chan *c, char *name, int omode, ulong perm)
{
+ if(!conf.monitor)
+ error(Egreg);
USED(c, name, omode, perm);
error(Eperm);
}
@@ 385,6 401,8 @@ bitcreate(Chan *c, char *name, int omode, ulong perm)
void
bitremove(Chan *c)
{
+ if(!conf.monitor)
+ error(Egreg);
USED(c);
error(Eperm);
}
@@ 392,6 410,8 @@ bitremove(Chan *c)
void
bitwstat(Chan *c, char *db)
{
+ if(!conf.monitor)
+ error(Egreg);
USED(c, db);
error(Eperm);
}
@@ 403,6 423,8 @@ bitclose(Chan *c)
BSubfont *s, **sp, **esp;
GFont *f, **fp, **efp;
+ if(!conf.monitor)
+ error(Egreg);
if(c->qid.path!=CHDIR && (c->flag&COPEN)){
lock(&bit);
if(c->qid.path == Qmouse)
@@ 447,6 469,8 @@ bitread(Chan *c, void *va, long n, ulong offset)
GBitmap *src;
BSubfont *s;
+ if(!conf.monitor)
+ error(Egreg);
if(c->qid.path & CHDIR)
return devdirread(c, va, n, bitdir, NBIT, devgen);
@@ 729,6 753,8 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
GFont *ff, **ffp;
GCacheinfo *gc;
+ if(!conf.monitor)
+ error(Egreg);
USED(offset);
if(c->qid.path == CHDIR)
M port/tcpinput.c => port/tcpinput.c +6 -3
@@ 11,10 11,12 @@ int tcpdbg = 0;
#define DPRINT if(tcpdbg) print
#define LPRINT if(tcpdbg) print
-char *tcpstate[] = {
+char *tcpstate[] =
+{
"Closed", "Listen", "Syn_sent", "Syn_received",
"Established", "Finwait1", "Finwait2", "Close_wait",
- "Closing", "Last_ack", "Time_wait" };
+ "Closing", "Last_ack", "Time_wait"
+};
void
reset(Ipaddr source, Ipaddr dest, char tos, ushort length, Tcp *seg)
@@ 379,7 381,8 @@ tcp_input(Ipifc *ifc, Block *bp)
if(length == 0){
if(bp)
freeb(bp);
- } else {
+ }
+ else {
switch(tcb->state){
default:
/* Ignore segment text */
M port/tcptimer.c => port/tcptimer.c +2 -3
@@ 115,6 115,7 @@ tcpflow(void *x)
ifc = x;
etab = &ifc->conv[Nipconv];
+
for(;;) {
sleep(&tcpflowr, return0, 0);
@@ 122,9 123,7 @@ tcpflow(void *x)
cp = *p;
if(cp == 0)
break;
- if(cp->readq)
- if(cp->ref != 0)
- if(!QFULL(cp->readq->next)) {
+ if(cp->readq && cp->ref != 0 && !QFULL(cp->readq->next)) {
tcprcvwin(cp);
tcp_acktimer(cp);
}
M ss/clock.c => ss/clock.c +2 -0
@@ 61,6 61,8 @@ clock(Ureg *ur)
mouseclock();
sccclock();
kproftimer(ur->pc);
+ if(m->fpunsafe)
+ return;
if((ur->psr&SPL(0xF))==0 && p && p->state==Running){
if(anyready()){
if(p->hasspin)
M ss/dat.h => ss/dat.h +55 -1
@@ 7,6 7,9 @@ typedef struct Lancemem Lancemem;
typedef struct Label Label;
typedef struct Lock Lock;
typedef struct PMMU PMMU;
+typedef struct Scsi Scsi;
+typedef struct Scsibuf Scsibuf;
+typedef struct Scsidata Scsidata;
typedef struct Mach Mach;
typedef struct Ureg Ureg;
typedef struct User User;
@@ 65,7 68,13 @@ struct Conf
{
int nmach; /* processors */
int nproc; /* processes */
- int ss2; /* is a sparcstation 2 */
+ char ss2; /* is a sparcstation 2 */
+ char ss2cachebug; /* has sparcstation2 cache bug */
+ char monitor; /* has graphics monitor */
+ int ncontext; /* in mmu */
+ int npmeg;
+ int vacsize; /* size of virtual address cache, in bytes */
+ int vaclinesize; /* size of cache line */
ulong npage0; /* total physical pages of memory, bank 0 */
ulong npage1; /* total physical pages of memory, bank 1 */
ulong base0; /* base of bank 0 */
@@ 205,3 214,48 @@ struct
short machs;
short exiting;
}active;
+
+enum
+{
+ ScsiTestunit = 0x00,
+ ScsiExtsens = 0x03,
+ ScsiModesense = 0x1a,
+ ScsiGetcap = 0x25,
+ ScsiRead = 0x08,
+ ScsiWrite = 0x0a,
+
+ /*
+ * data direction
+ */
+ ScsiIn = 1,
+ ScsiOut = 0,
+};
+
+struct Scsibuf
+{
+ void *virt;
+ void *phys;
+ Scsibuf *next;
+};
+
+struct Scsidata
+{
+ uchar *base;
+ uchar *lim;
+ uchar *ptr;
+};
+
+struct Scsi
+{
+ QLock;
+ ulong pid;
+ ushort target;
+ ushort lun;
+ ushort rflag;
+ ushort status;
+ Scsidata cmd;
+ Scsidata data;
+ Scsibuf *b;
+ uchar *save;
+ uchar cmdblk[16];
+};
A ss/devrtc.c => ss/devrtc.c +369 -0
@@ 0,0 1,369 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "devtab.h"
+
+#include "io.h"
+
+/*
+ * Mostek MK48T12-15 Zeropower/Timekeeper
+ * This driver is actually portable.
+ */
+typedef struct Rtc Rtc;
+struct Rtc
+{
+ int sec;
+ int min;
+ int hour;
+ int wday;
+ int mday;
+ int mon;
+ int year;
+};
+ulong rtc2sec(Rtc *);
+void sec2rtc(ulong, Rtc *);
+
+static struct
+{
+ uchar *ram;
+ RTCdev *rtc;
+}nvr;
+
+
+enum{
+ Qrtc = 1,
+ Qnvram,
+};
+
+QLock rtclock; /* mutex on clock operations */
+
+static Dirtab rtcdir[]={
+ "rtc", {Qrtc, 0}, 0, 0666,
+ "nvram", {Qnvram, 0}, 0, 0666,
+};
+#define NRTC (sizeof(rtcdir)/sizeof(rtcdir[0]))
+void setrtc(Rtc*);
+long rtctime(void);
+
+void
+rtcreset(void)
+{
+}
+
+void
+rtcinit(void)
+{
+ KMap *k;
+
+ k = kmappa(NVRAM, PTENOCACHE|PTEIO);
+ nvr.ram = (uchar*)k->va;
+ nvr.rtc = (RTCdev*)(k->va+RTCOFF);
+}
+
+Chan*
+rtcattach(char *spec)
+{
+ return devattach('r', spec);
+}
+
+Chan*
+rtcclone(Chan *c, Chan *nc)
+{
+ return devclone(c, nc);
+}
+
+int
+rtcwalk(Chan *c, char *name)
+{
+ return devwalk(c, name, rtcdir, NRTC, devgen);
+}
+
+void
+rtcstat(Chan *c, char *dp)
+{
+ devstat(c, dp, rtcdir, NRTC, devgen);
+}
+
+Chan*
+rtcopen(Chan *c, int omode)
+{
+ return devopen(c, omode, rtcdir, NRTC, devgen);
+}
+
+void
+rtccreate(Chan *c, char *name, int omode, ulong perm)
+{
+ USED(c, name, omode, perm);
+ error(Eperm);
+}
+
+void
+rtcclose(Chan *c)
+{
+ USED(c);
+}
+
+long
+rtcread(Chan *c, void *buf, long n, ulong offset)
+{
+ ulong t, ot;
+
+ if(c->qid.path & CHDIR)
+ return devdirread(c, buf, n, rtcdir, NRTC, devgen);
+
+ switch(c->qid.path){
+ case Qrtc:
+ qlock(&rtclock);
+ t = rtctime();
+ do{
+ ot = t;
+ t = rtctime(); /* make sure there's no skew */
+ }while(t != ot);
+ qunlock(&rtclock);
+ n = readnum(offset, buf, n, t, 12);
+ return n;
+ case Qnvram:
+ if(offset > NVREAD)
+ return 0;
+ if(n > NVREAD - offset)
+ n = NVREAD - offset;
+ qlock(&rtclock);
+ memmove(buf, nvr.ram+offset, n);
+ qunlock(&rtclock);
+ return n;
+ }
+ error(Egreg);
+ return 0; /* not reached */
+}
+
+long
+rtcwrite(Chan *c, void *buf, long n, ulong offset)
+{
+ Rtc rtc;
+ ulong secs;
+ char *cp, *ep;
+
+ switch(c->qid.path){
+ case Qrtc:
+ if(offset!=0)
+ error(Ebadarg);
+ /*
+ * read the time
+ */
+ cp = ep = buf;
+ ep += n;
+ while(cp < ep){
+ if(*cp>='0' && *cp<='9')
+ break;
+ cp++;
+ }
+ secs = strtoul(cp, 0, 0);
+ /*
+ * convert to bcd
+ */
+ sec2rtc(secs, &rtc);
+ /*
+ * write it
+ */
+ qlock(&rtclock);
+ setrtc(&rtc);
+ qunlock(&rtclock);
+ return n;
+ case Qnvram:
+ if(offset > NVWRITE)
+ return 0;
+ if(n > NVWRITE - offset)
+ n = NVWRITE - offset;
+ qlock(&rtclock);
+ memmove(nvr.ram+offset, buf, n);
+ qunlock(&rtclock);
+ return n;
+ }
+ error(Egreg);
+ return 0; /* not reached */
+}
+
+void
+rtcremove(Chan *c)
+{
+ USED(c);
+ error(Eperm);
+}
+
+void
+rtcwstat(Chan *c, char *dp)
+{
+ USED(c, dp);
+ error(Eperm);
+}
+
+#define bcd2dec(bcd) (((((bcd)>>4) & 0x0F) * 10) + ((bcd) & 0x0F))
+#define dec2bcd(dec) ((((dec)/10)<<4)|((dec)%10))
+
+void
+setrtc(Rtc *rtc)
+{
+ struct RTCdev *dev;
+
+ dev = nvr.rtc;
+ dev->control |= RTCWRITE;
+ wbflush();
+ dev->year = dec2bcd(rtc->year % 100);
+ dev->mon = dec2bcd(rtc->mon);
+ dev->mday = dec2bcd(rtc->mday);
+ dev->hour = dec2bcd(rtc->hour);
+ dev->min = dec2bcd(rtc->min);
+ dev->sec = dec2bcd(rtc->sec);
+ wbflush();
+ dev->control &= ~RTCWRITE;
+ wbflush();
+}
+
+long
+rtctime(void)
+{
+ struct RTCdev *dev;
+ Rtc rtc;
+
+ dev = nvr.rtc;
+ dev->control |= RTCREAD;
+ wbflush();
+ rtc.sec = bcd2dec(dev->sec) & 0x7F;
+ rtc.min = bcd2dec(dev->min & 0x7F);
+ rtc.hour = bcd2dec(dev->hour & 0x3F);
+ rtc.mday = bcd2dec(dev->mday & 0x3F);
+ rtc.mon = bcd2dec(dev->mon & 0x3F);
+ rtc.year = bcd2dec(dev->year);
+ dev->control &= ~RTCREAD;
+ wbflush();
+
+ if (rtc.mon < 1 || rtc.mon > 12)
+ return 0;
+ /*
+ * the world starts Jan 1 1970
+ */
+ if(rtc.year < 70)
+ rtc.year += 2000;
+ else
+ rtc.year += 1900;
+
+ return rtc2sec(&rtc);
+}
+
+#define SEC2MIN 60L
+#define SEC2HOUR (60L*SEC2MIN)
+#define SEC2DAY (24L*SEC2HOUR)
+
+/*
+ * days per month plus days/year
+ */
+static int dmsize[] =
+{
+ 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+static int ldmsize[] =
+{
+ 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * return the days/month for the given year
+ */
+int *
+yrsize(int yr)
+{
+ if((yr % 4) == 0)
+ return ldmsize;
+ else
+ return dmsize;
+}
+
+/*
+ * compute seconds since Jan 1 1970
+ */
+ulong
+rtc2sec(Rtc *rtc)
+{
+ ulong secs;
+ int i;
+ int *d2m;
+
+ secs = 0;
+
+ /*
+ * seconds per year
+ */
+ for(i = 1970; i < rtc->year; i++){
+ d2m = yrsize(i);
+ secs += d2m[0] * SEC2DAY;
+ }
+
+ /*
+ * seconds per month
+ */
+ d2m = yrsize(rtc->year);
+ for(i = 1; i < rtc->mon; i++)
+ secs += d2m[i] * SEC2DAY;
+
+ secs += (rtc->mday-1) * SEC2DAY;
+ secs += rtc->hour * SEC2HOUR;
+ secs += rtc->min * SEC2MIN;
+ secs += rtc->sec;
+
+ return secs;
+}
+
+/*
+ * compute rtc from seconds since Jan 1 1970
+ */
+void
+sec2rtc(ulong secs, Rtc *rtc)
+{
+ int d;
+ long hms, day;
+ int *d2m;
+
+ /*
+ * break initial number into days
+ */
+ hms = secs % SEC2DAY;
+ day = secs / SEC2DAY;
+ if(hms < 0) {
+ hms += SEC2DAY;
+ day -= 1;
+ }
+
+ /*
+ * generate hours:minutes:seconds
+ */
+ rtc->sec = hms % 60;
+ d = hms / 60;
+ rtc->min = d % 60;
+ d /= 60;
+ rtc->hour = d;
+
+ /*
+ * year number
+ */
+ if(day >= 0)
+ for(d = 1970; day >= *yrsize(d); d++)
+ day -= *yrsize(d);
+ else
+ for (d = 1970; day < 0; d--)
+ day += *yrsize(d-1);
+ rtc->year = d;
+
+ /*
+ * generate month
+ */
+ d2m = yrsize(rtc->year);
+ for(d = 1; day >= d2m[d]; d++)
+ day -= d2m[d];
+ rtc->mday = day + 1;
+ rtc->mon = d;
+
+ return;
+}
M ss/fns.h => ss/fns.h +22 -3
@@ 21,7 21,6 @@ void fpsave(FPsave*);
int fptrap(void);
int getfpq(ulong*);
ulong getfsr(void);
-ulong (*getsysspace)(ulong);
void intrinit(void);
void ioinit(void);
int kbdstate(IOQ*, int);
@@ 46,18 45,26 @@ void printinit(void);
#define procsave(p)
#define procsetup(x) ((p)->fpstate = FPinit)
void putcxsegm(int, ulong, int);
-void (*putenab)(ulong);
void putpmeg(ulong, ulong);
void putsegm(ulong, int);
-void (*putsysspace)(ulong, ulong);
void putstr(char*);
void putstrn(char*, long);
void puttbr(ulong);
+void putw4(ulong, ulong); /* needed only at boot time */
void systemreset(void);
void restfpregs(FPsave*, ulong);
void screeninit(void);
void screenputc(int);
void screenputs(char*, int);
+Scsibuf *scsialloc(ulong);
+int scsibread(int, Scsibuf*, long, long, long);
+int scsibwrite(int, Scsibuf*, long, long, long);
+Scsibuf *scsibuf(void);
+int scsicap(int, void*);
+void scsifree(Scsibuf*);
+void scsiintr(void);
+int scsiready(int);
+int scsisense(int, void *);
void spldone(void);
ulong tas(ulong*);
void touser(ulong);
@@ 66,3 73,15 @@ void trapinit(void);
#define wbflush() /* mips compatibility */
#define waserror() (u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))
#define getcallerpc(x) (*(ulong*)(x))
+
+/*
+ * compiled entry points
+ */
+extern void (*putcontext)(ulong);
+extern void (*putenab)(ulong);
+extern ulong (*getenab)(void);
+extern void (*putpmegspace)(ulong, ulong);
+extern void (*putsysspace)(ulong, ulong);
+extern ulong (*getsysspace)(ulong);
+extern ulong (*flushcx)(ulong);
+extern ulong (*flushpg)(ulong);
M ss/io.h => ss/io.h +106 -0
@@ 4,6 4,9 @@
#define CLOCKFREQ 1000000 /* one microsecond increments */
#define KMDUART 0xF0000000 /* keyboard A, mouse B */
#define EIADUART 0xF1000000 /* serial ports */
+#define NVRAM 0xF2000000 /* non-volatile RAM */
+#define DMA 0xF8400000 /* DMA registers */
+#define SCSI 0xF8800000 /* NCR53C90 registers */
#define ETHER 0xF8C00000 /* RDP, RAP */
#define EEPROM 0xF2000000
#define INTRREG 0xF5000000 /* interrupt register, IO space */
@@ 23,3 26,106 @@ struct SCCdev
#define KMFREQ 10000000 /* crystal frequency for kbd/mouse 8530 */
#define EIAFREQ 5000000 /* crystal frequency for serial port 8530 */
+
+/*
+ * non-volatile ram
+ */
+#define NVREAD (2048-8) /* minus RTC */
+#define NVWRITE (2048-8-32) /* minus RTC, minus ID prom */
+
+/*
+ * real-time clock (every 4th location)
+ */
+typedef struct RTCdev RTCdev;
+struct RTCdev
+{
+ uchar control; /* read or write the device */
+ uchar sec;
+ uchar min;
+ uchar hour;
+ uchar wday;
+ uchar mday;
+ uchar mon;
+ uchar year;
+};
+#define RTCOFF 0x7F8
+#define RTCREAD (0x40)
+#define RTCWRITE (0x80)
+
+/*
+ * dma
+ */
+typedef struct DMAdev DMAdev;
+struct DMAdev {
+ ulong csr; /* Control/Status */
+ ulong addr; /* address in 16Mb segment */
+ ulong count; /* transfer byte count */
+ ulong diag;
+};
+
+enum {
+ Int_pend = 0x00000001, /* interrupt pending */
+ Err_pend = 0x00000002, /* error pending */
+ Pack_cnt = 0x0000000C, /* pack count (mask) */
+ Int_en = 0x00000010, /* interrupt enable */
+ Dma_Flush = 0x00000020, /* flush pack end error */
+ Drain = 0x00000040, /* drain pack to memory */
+ Dma_Reset = 0x00000080, /* hardware reset (sticky) */
+ Write = 0x00000100, /* set for device to memory (!) */
+ En_dma = 0x00000200, /* enable DMA */
+ Req_pend = 0x00000400, /* request pending */
+ Byte_addr = 0x00001800, /* next byte addr (mask) */
+ En_cnt = 0x00002000, /* enable count */
+ Tc = 0x00004000, /* terminal count */
+ Ilacc = 0x00008000, /* which ether chip */
+ Dev_id = 0xF0000000, /* device ID */
+};
+
+/*
+ * NCR53C90 SCSI controller (every 4th location)
+ */
+typedef struct SCSIdev SCSIdev;
+struct SCSIdev {
+ uchar countlo; /* byte count, low bits */
+ uchar pad1[3];
+ uchar counthi; /* byte count, hi bits */
+ uchar pad2[3];
+ uchar fifo; /* data fifo */
+ uchar pad3[3];
+ uchar cmd; /* command byte */
+ uchar pad4[3];
+ union {
+ struct { /* read only... */
+ uchar status; /* status */
+ uchar pad05[3];
+ uchar intr; /* interrupt status */
+ uchar pad06[3];
+ uchar step; /* sequence step */
+ uchar pad07[3];
+ uchar fflags; /* fifo flags */
+ uchar pad08[3];
+ uchar config; /* configuration */
+ uchar pad09[3];
+ uchar Reserved1;
+ uchar pad0A[3];
+ uchar Reserved2;
+ uchar pad0B[3];
+ };
+ struct { /* write only... */
+ uchar destid; /* destination id */
+ uchar pad15[3];
+ uchar timeout; /* during selection */
+ uchar pad16[3];
+ uchar syncperiod; /* synchronous xfr period */
+ uchar pad17[3];
+ uchar syncoffset; /* synchronous xfr offset */
+ uchar pad18[3];
+ uchar XXX;
+ uchar pad19[3];
+ uchar clkconf;
+ uchar pad1A[3];
+ uchar test;
+ uchar pad1B[3];
+ };
+ };
+};
M ss/l.s => ss/l.s +10 -1
@@ 22,6 22,9 @@ TEXT start(SB), $-4
TEXT startvirt(SB), $-4
+ MOVW $romvec(SB), R7
+ MOVW R8, (R7) /* romvec passed in %i0==R8 */
+
MOVW $BOOTSTACK, R1
MOVW $(SPL(0xF)|PSREF|PSRSUPER), R7
@@ 324,10 327,16 @@ TEXT putcxsegm(SB), $0
MOVW R7, R8 /* context */
MOVW 4(FP), R9 /* segment addr */
MOVW 8(FP), R10 /* segment value */
- MOVW $PUTCXSEGM, R7
+ MOVW $romputcxsegm(SB), R7
+ MOVW (R7), R7
JMPL (R7)
RETURN
+TEXT putw4(SB), $0
+ MOVW 4(FP), R8
+ MOVW R8, (R7, 4)
+ RETURN
+
TEXT getpsr(SB), $0
MOVW PSR, R7
M ss/main.c => ss/main.c +105 -14
@@ 9,7 9,13 @@
#include <libg.h>
#include <gnot.h>
-uchar *intrreg;
+uchar *intrreg;
+int model;
+uchar idprom[32];
+ulong romvec; /* open boot rom vector */
+int cpuserver;
+ulong romputcxsegm;
+ulong bank[2];
void
main(void)
@@ 23,12 29,15 @@ main(void)
confinit();
xinit();
mmuinit();
- screeninit();
+ if(conf.monitor)
+ screeninit();
printinit();
- pageinit();
trapinit();
kmapinit();
ioinit();
+ if(!conf.monitor)
+ sccspecial(2, &printq, &kbdq, 9600);
+ pageinit();
cacheinit();
intrinit();
procinit0();
@@ 54,7 63,7 @@ void
systemreset(void)
{
delay(100);
- putb2(ENAB, ENABRESET);
+ putenab(ENABRESET);
}
@@ 98,6 107,7 @@ init0(void)
u->p->mach = m;
spllo();
+ print("bank 0: %dM 1: %dM\n", bank[0], bank[1]);
u->slash = (*devtab[0].attach)(0);
u->dot = clone(u->slash, 0);
@@ 194,42 204,123 @@ exit(void)
systemreset();
}
+int
+banksize(ulong addr, ulong nbytes)
+{
+ int i;
+ ulong min, max, t;
+ ulong va, pa;
+ ulong nmeg;
+
+ nmeg = nbytes/MB;
+ va = 1*MB-2*BY2PG;
+ for(i=0; i<nmeg; i++){
+ pa = addr+i*MB;
+ putw4(va, PPN(pa)|PTEVALID|PTEKERNEL|PTENOCACHE|PTEWRITE|PTEMAINMEM);
+ *(ulong*)va = pa;
+ }
+ min = ~0;
+ max = 0;
+ for(i=0; i<nmeg; i++){
+ pa = addr+i*MB;
+ putw4(va, PPN(pa)|PTEVALID|PTEKERNEL|PTENOCACHE|PTEWRITE|PTEMAINMEM);
+ t = *(ulong*)va;
+ if(min > t)
+ min = t;
+ if(max < t)
+ max = t;
+ }
+ putw4(va, INVALIDPTE);
+ return (max-min)/MB+1;
+}
+
Conf conf;
void
confinit(void)
{
int mul;
- ulong ktop;
+ ulong i;
+ ulong ktop, va, mbytes;
conf.nmach = 1;
if(conf.nmach > MAXMACH)
panic("confinit");
- conf.ss2 = 0;
- conf.npage0 = (4*1024*1024)/BY2PG; /* BUG */
- conf.npage1 = (4*1024*1024)/BY2PG; /* BUG */
- conf.base0 = 0;
- conf.base1 = 32*1024*1024;
- conf.npage = conf.npage0+conf.npage1;
+ /* map id prom */
+ va = 1*MB-BY2PG;
+ putw4(va, PPN(EEPROM)|PTEVALID|PTEKERNEL|PTENOCACHE|PTEIO);
+ memmove(idprom, (char*)(va+0x7d8), 32);
+ if(idprom[0]!=1 || (idprom[1]&0xF0)!=0x50)
+ *(ulong*)va = 0;
+ putw4(va, INVALIDPTE);
+
+ switch(idprom[1]){
+ case 0x51: /* sparcstation 1 */
+ case 0x54: /* slc */
+ default:
+ conf.ss2 = 0;
+ conf.vacsize = 65536;
+ conf.vaclinesize = 16;
+ conf.ncontext = 8;
+ conf.npmeg = 128;
+ conf.ss2cachebug = 0;
+ conf.monitor = 1; /* BUG */
+ conf.base0 = 0;
+ conf.base1 = 32*MB;
+ break;
+
+ case 0x55: /* sparcstation 2 */
+ conf.ss2 = 1;
+ conf.vacsize = 65536;
+ conf.vaclinesize = 32;
+ conf.ncontext = 16;
+ conf.npmeg = 256;
+ conf.ss2cachebug = 1;
+ conf.monitor = 0; /* BUG */
+ conf.base0 = 0;
+ conf.base1 = 16*MB;
+ break;
+ }
+
+ bank[0] = banksize(conf.base0, 16*MB);
+ bank[1] = banksize(conf.base1, 16*MB);
+ conf.npage0 = (bank[0]*MB)/BY2PG;
+ conf.npage1 = (bank[1]*MB)/BY2PG;
- conf.upages = 1400;
+ romputcxsegm = *(ulong*)(romvec+260);
+
+ conf.npage = conf.npage0+conf.npage1;
+ conf.upages = (conf.npage*70)/100;
+ if(cpuserver){
+ i = conf.npage-conf.upages;
+ if(i > (6*MB)/BY2PG)
+ conf.upages += i - ((6*MB)/BY2PG);
+ }
ktop = PGROUND((ulong)end);
ktop = PADDR(ktop);
conf.npage0 -= ktop/BY2PG;
conf.base0 += ktop;
- mul = conf.upages/700;
+ mbytes = (conf.npage*BY2PG)>>20;
+ mul = 1 + (mbytes+11)/12;
+ if(mul > 2)
+ mul = 2;
conf.nproc = 50*mul;
- conf.nswap = 4096;
+ if(cpuserver)
+ conf.nswap = conf.npage*2;
+ else
+ conf.nswap = 4096;
conf.nimage = 50;
conf.copymode = 0; /* copy on write */
conf.ipif = 8;
conf.ip = 64;
conf.arp = 32;
conf.frag = 32;
+ if(cpuserver)
+ conf.nproc = 500;
}
/*
M ss/mem.h => ss/mem.h +6 -16
@@ 56,20 56,19 @@
*/
#define VAMASK 0x3FFFFFFF
-#define NPMEG (1<<12)
#define BY2SEGM (1<<18)
#define PG2SEGM (1<<6)
-#define NTLBPID (1+NCONTEXT) /* TLBPID 0 is unallocated */
-#define NCONTEXT 8
+#define NTLBPID (1+MAXCONTEXT) /* TLBPID 0 is unallocated */
+#define MAXCONTEXT 16
#define CONTEXT 0x30000000 /* in ASI 2 */
/*
* MMU regions
*/
#define INVALIDSEGM 0xFFFC0000 /* highest seg of VA reserved as invalid */
-#define INVALIDPMEG 0x7F
+#define INVALIDPMEG (conf.npmeg-1)
#define SCREENSEGM 0xFFF80000
-#define SCREENPMEG 0x7E
+#define SCREENPMEG (conf.npmeg-2)
#define ROMSEGM 0xFFE80000
#define ROMEND 0xFFEC0000
#define PG2ROM ((ROMEND-ROMSEGM)/BY2PG)
@@ 110,10 109,9 @@
#define ASER 0x60000008 /* ASI 2 */
#define ASEVAR 0x6000000C /* ASI 2 */
#define ENAB 0x40000000 /* ASI 2 */
-#define ENABCACHE 0x10
#define ENABRESET 0x04
-#define VACLINESZ 16 /* cache line size */
-#define VACSIZE (1<<16) /* total cache size */
+#define ENABCACHE 0x10
+#define ENABDMA 0x20
/*
* Virtual addresses
@@ 122,14 120,8 @@
#define VPN(va) ((va>>13)&0x1FF)
/*
- * Rom addresses
- */
-#define PUTCXSEGM 0xFFE80118
-
-/*
* Address spaces
*/
-
#define UZERO 0x00000000 /* base of user address space */
#define UTZERO (UZERO+BY2PG) /* first address in user text */
#define TSTKTOP 0x10000000 /* end of new stack in sysexec */
@@ 140,5 132,3 @@
#define USTKSIZE (4*1024*1024) /* size of user stack */
#define MACHSIZE 4096
-
-#define isphys(x) (((ulong)(x)&0xF0000000) == KZERO)
M ss/mmu.c => ss/mmu.c +12 -17
@@ 89,13 89,15 @@ mmurelease(Proc *p)
int
newpid(Proc *p)
{
- int i, j;
+ int i, j, nc;
ulong t;
Proc *sp;
t = ~0;
- i = 1+((m->ticks)&(NCONTEXT-1)); /* random guess */
- for(j=1; t && j<NTLBPID; j++)
+ nc = conf.ncontext;
+ i = 1+((m->ticks)&(nc-1)); /* random guess */
+ nc++;
+ for(j=1; t && j<nc; j++)
if(pidtime[j] < t){
i = j;
t = pidtime[j];
@@ 132,7 134,7 @@ flushcontext(void)
a = 0;
do
a = flushcx(a);
- while(a < VACSIZE);
+ while(a < conf.vacsize);
}
void
@@ 156,7 158,7 @@ mmuinit(void)
* First map lots of memory as kernel addressable in all contexts
*/
i = 0; /* used */
- for(c=0; c<NCONTEXT; c++)
+ for(c=0; c<conf.ncontext; c++)
for(i=0; i < ktop/BY2SEGM; i++)
putcxsegm(c, KZERO+i*BY2SEGM, i);
@@ 177,7 179,7 @@ mmuinit(void)
for(i=0; i<PG2SEGM; i++)
putpmeg(INVALIDSEGM+i*BY2PG, INVALIDPTE);
- for(c=0; c<NCONTEXT; c++){
+ for(c=0; c<conf.ncontext; c++){
putcontext(c);
putsegm(INVALIDSEGM, INVALIDPMEG);
/*
@@ 274,13 276,6 @@ putpmeg(ulong virt, ulong phys)
virt &= VAMASK;
virt &= ~(BY2PG-1);
-#ifdef asdf
- if(conf.ss2)
- putw6(virt, 0);
- else
- for(i=0; i<BY2PG; i+=16*VACLINESZ)
- putwD16(virt+i, 0);
-#endif
/*
* Flush old entries from cache
*/
@@ 319,7 314,7 @@ cacheinit(void)
* Initialize cache by clearing the valid bit
* (along with the others) in all cache entries
*/
- for(i=0; i<VACSIZE; i+=VACLINESZ)
+ for(i=0; i<conf.vacsize; i+=conf.vaclinesize)
putsysspace(CACHETAGS+i, 0);
/*
@@ 438,10 433,10 @@ compile(void)
getsysspace = compileldaddr(LDA, 2);
if(conf.ss2){
flushpg = compile1(BY2PG, 6);
- flushcx = compile16(VACLINESZ, 7);
+ flushcx = compile16(conf.vaclinesize, 7);
}else{
- flushpg = compile16(VACLINESZ, 0xD);
- flushcx = compile16(VACLINESZ, 0xE);
+ flushpg = compile16(conf.vaclinesize, 0xD);
+ flushcx = compile16(conf.vaclinesize, 0xE);
}
}
A ss/rom.h => ss/rom.h +55 -0
@@ 0,0 1,55 @@
+typedef struct ROM ROM;
+typedef struct ROMconf ROMconf;
+
+struct ROM
+{
+ uint magic;
+ uint version;
+ uint plugversion;
+ uint monid;
+ uint pad1[3];
+ ROMconf *conf;
+ uint pad2[17];
+ void (*boot)(void*);
+ uint pad3[1];
+ void (*enter)(void);
+ int *msec;
+ void (*exit)(void);
+ void (**callback)(void);
+ uint (*interpret)(void*);
+ uint pad4[2];
+ char **bootpath;
+ char **bootargs;
+ uint *stdin;
+ uint *stdout;
+ uint (*phandle)(uint);
+ uint (*alloc)(void*, uint);
+ void (*free)(void*);
+ uint (*map)(void*, uint, uint, uint);
+ void (*unmap)(void*, uint);
+ uint (*open)(char*);
+ uint (*close)(uint);
+ uint (*read)(uint, void*, int);
+ uint (*write)(uint, void*, int);
+ uint (*seek)(uint, uint, uint);
+ void (*chain)(void*, uint, void*, void*, uint);
+ void (*release)(void*, uint);
+ uint pad5[16];
+ int (*startcpu)(uint, uint, uint, uint);
+ int (*stopcpu)(uint);
+ int (*idlecpu)(uint);
+ int (*resumecpu)(uint);
+};
+
+struct ROMconf
+{
+ uint (*next)(uint);
+ uint (*child)(uint);
+ int (*getproplen)(uint, void*);
+ int (*getprop)(uint, void*, void*);
+ void* (*nextprop)(uint, void*);
+};
+
+#define ROMMAGIC 0x10010407
+
+extern ROM *rom;
M ss/screen.c => ss/screen.c +6 -0
@@ 38,6 38,8 @@ Lock screenlock;
void
screeninit(void)
{
+ if(!conf.monitor)
+ return;
defont = &defont0;
gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, 0);
out.pos.x = MINX;
@@ 48,6 50,8 @@ screeninit(void)
void
screenputnl(void)
{
+ if(!conf.monitor)
+ return;
out.pos.x = MINX;
out.pos.y += defont0.height;
if(out.pos.y > gscreen.r.max.y-defont0.height)
@@ 63,6 67,8 @@ screenputs(char *s, int n)
int i;
char buf[4];
+ if(!conf.monitor)
+ return;
lock(&screenlock);
while(n > 0){
i = chartorune(&r, s);
A ss/scsi.c => ss/scsi.c +297 -0
@@ 0,0 1,297 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "devtab.h"
+#include "io.h"
+
+static int ownid = 7;
+
+Scsibuf *
+scsialloc(ulong n)
+{
+ Scsibuf *b;
+ KMap *k;
+ ulong pa, va;
+ int i, j;
+
+ b = xalloc(sizeof(Scsibuf));
+
+ /*
+ * Allocate space in host memory for the io buffer.
+ * Allocate a block and kmap it page by page. kmap's are initially
+ * in reverse order so rearrange them.
+ * NOTE: dma mustn't cross a 16Mb boundary.
+ */
+ i = (n+(BY2PG-1))/BY2PG;
+ pa = (ulong)xspanalloc(i*BY2PG, BY2PG, 16*1024*1024) & ~KZERO;
+ va = 0;
+ k = 0;
+ for(j=i-1; j>=0; j--){
+ k = kmappa(pa+j*BY2PG, PTEMAINMEM|PTENOCACHE);
+ if(va && va != k->va+BY2PG)
+ panic("scsialloc va unordered\n");
+ va = k->va;
+ }
+ /*
+ * k->va is the base of the region
+ */
+ b->virt = (void*)k->va;
+ b->phys = (void*)k->pa;
+
+ return b;
+}
+
+/*
+ * NCR 53C90 commands
+ */
+
+enum
+{
+ Dma = 0x80,
+ Nop = 0x00,
+ Flush = 0x01,
+ Reset = 0x02,
+ Busreset = 0x03,
+ Select = 0x41,
+ Transfer = 0x10,
+ Cmdcomplete = 0x11,
+ Msgaccept = 0x12
+};
+
+static QLock scsilock; /* access to device */
+static Rendez scsirendez; /* sleep/wakeup for requesting process */
+static Scsi * curcmd; /* currently executing command */
+
+struct {
+ DMAdev *dma;
+ SCSIdev *scsi;
+} ioaddr;
+
+void
+resetscsi(void)
+{
+ SCSIdev *dev;
+ DMAdev *dma;
+ KMap *k;
+
+ k = kmappa(DMA, PTENOCACHE|PTEIO);
+ ioaddr.dma = (DMAdev*)k->va;
+ k = kmappa(SCSI, PTENOCACHE|PTEIO);
+ ioaddr.scsi = (SCSIdev*)k->va;
+
+ dev = ioaddr.scsi;
+ dma = ioaddr.dma;
+
+ dev->cmd = Reset;
+ dev->cmd = Nop;
+ dev->countlo = 0;
+ dev->counthi = 0;
+ dev->timeout = 146;
+ dev->syncperiod = 0;
+ dev->syncoffset = 0;
+ dev->config = 0x10|(ownid&7);
+ dev->cmd = Dma|Nop;
+
+ dma->csr = Dma_Reset;
+ delay(1);
+ dma->csr = Int_en;
+ dma->count = 0;
+
+ putenab(getenab()|ENABDMA); /**/
+}
+
+void
+initscsi(void)
+{
+}
+
+static int
+scsidone(void *arg)
+{
+ USED(arg);
+ return (curcmd == 0);
+}
+
+int
+scsiexec(Scsi *p, int rflag)
+{
+ SCSIdev *dev = ioaddr.scsi;
+ DMAdev *dma = ioaddr.dma;
+ long n;
+
+ qlock(&scsilock);
+
+ if(waserror()){
+ qunlock(&scsilock);
+ nexterror();
+ }
+ p->rflag = rflag;
+ p->status = 0;
+
+ dma->csr = Dma_Flush|Int_en;
+ dma->addr = (ulong)p->data.ptr;
+
+ dev->counthi = 0;
+ dev->countlo = 0;
+ dev->cmd = Dma|Nop;
+ dev->cmd = Flush; /* clear scsi fifo */
+
+ while (p->cmd.ptr < p->cmd.lim)
+ dev->fifo = *(p->cmd.ptr)++;
+
+ dev->destid = p->target&7;
+ n = p->data.lim - p->data.ptr;
+ dev->counthi = n>>8;
+ dev->countlo = n;
+ dev->cmd = Dma|Nop;
+
+ dma->csr = Int_en;
+
+ curcmd = p;
+ dev->cmd = Select;
+
+ sleep(&scsirendez, scsidone, 0);
+ poperror();
+ qunlock(&scsilock);
+ return p->status;
+}
+
+
+void
+scsibusreset(void)
+{
+ SCSIdev *dev = ioaddr.scsi;
+ int s;
+
+ s = splhi();
+ dev->cmd = Nop;
+ dev->cmd = Busreset;
+ dev->cmd = Nop;
+ splx(s);
+}
+
+static void
+scsimoan(char *msg, int status, int intr, int dmastat)
+{
+ print("scsiintr: %s:", msg);
+ print(" status=%2.2ux step/intr=%3.3ux", status, intr);
+ print(" dma=%8.8ux cmd status=%4.4ux\n",
+ dmastat, curcmd ? curcmd->status : 0xffff);
+}
+
+void
+scsiintr(void)
+{
+ SCSIdev *dev = ioaddr.scsi;
+ DMAdev *dma = ioaddr.dma;
+ Scsi *p = curcmd;
+ int status, step, intr, n;
+ ulong m, csr;
+
+ csr = dma->csr;
+
+ status = dev->status;
+ step = dev->step;
+ intr = dev->intr;
+
+ intr |= ((step&7)<<8);
+
+ if(p == 0 || (intr & 0x80)) { /* SCSI bus reset */
+ dev->cmd = Nop;
+ goto Done;
+ }
+
+ switch(p->status>>8){
+ case 0x00: /* Select was issued */
+ switch(intr){
+ default:
+ scsimoan("bad case", status, intr, csr);
+ print("cmd = #%2.2ux\n", dev->cmd);
+ resetscsi();
+ scsibusreset();
+ goto Done;
+ case 0x020: /* arbitration complete, selection timed out */
+ goto Done;
+ case 0x218: /* selection complete, no command phase */
+ p->status = 0x1000;
+ scsimoan("no cmd phase", status, intr, csr);
+ resetscsi();
+ scsibusreset();
+ goto Done;
+ case 0x318: /* command phase ended prematurely */
+ n = (p->cmd.lim - p->cmd.base) - (dev->fflags & 0x1f);
+ p->status = (0x30+n)<<8;
+ scsimoan("short cmd phase", status, intr, csr);
+ resetscsi();
+ scsibusreset();
+ goto Done;
+ case 0x418: /* select sequence complete */
+ p->status = 0x4100;
+ if((status & 0x07) == p->rflag){
+ dma->csr = p->rflag ? En_dma|Write|Int_en : En_dma|Int_en;
+ dev->cmd = Dma|Transfer;
+ return;
+ }else if((status & 0x07) != 3){
+ scsimoan("weird phase after cmd",
+ status, intr, csr);
+ goto Done;
+ }
+ /* else fall through */
+ }
+
+ case 0x41: /* data transfer, if any, is finished */
+ p->status = 0x4600;
+ p->data.ptr = p->data.lim - ((dev->counthi<<8)|dev->countlo);
+ if((status & 0x07) != 3){
+ scsimoan("weird phase after xfr",
+ status, intr, csr);
+ goto Done;
+ }
+
+ if(p->rflag)
+ while(dma->csr & Pack_cnt)
+ ;
+
+ dev->cmd = Cmdcomplete;
+ return;
+
+ case 0x46: /* Cmdcomplete was issued */
+ p->status = 0x6000|dev->fifo;
+ m = dev->fifo;
+ dev->cmd = Msgaccept;
+ return;
+
+ case 0x60: /* Msgaccept was issued */
+ goto Done;
+ }
+Done:
+ curcmd = 0;
+ wakeup(&scsirendez);
+}
+
+#ifdef notdef
+void
+scsidump(void)
+{
+ SCSIdev *dev = ioaddr.scsi;
+ DMAdev *dma = ioaddr.dma;
+
+ print("\nscsi:\n");
+ print(" countlo=0x%2.2ux\n", dev->countlo);
+ print(" counthi=0x%2.2ux\n", dev->counthi);
+ print(" cmd =0x%2.2ux\n", dev->cmd);
+ print(" status =0x%2.2ux\n", dev->status);
+ print(" intr =0x%2.2ux\n", dev->intr);
+ print(" step =0x%2.2ux\n", dev->step);
+ print(" fflags =0x%2.2ux\n", dev->countlo);
+ print(" config =0x%2.2ux\n", dev->config);
+ print("dma:\n");
+ print(" csr =0x%8.8ux\n", dma->csr);
+ print(" addr =0x%8.8ux\n", dma->addr);
+ print(" count =0x%4.4ux\n", dma->count);
+ print(" diag =0x%8.8ux\n", dma->diag);
+}
+#endif
M ss/trap.c => ss/trap.c +6 -3
@@ 109,8 109,8 @@ trap(Ureg *ur)
user = !(ur->psr&PSRPSUPER);
tbr = (ur->tbr&0xFFF)>>4;
/* SS2 bug: flush cache line holding trap entry in table */
- if(conf.ss2)
- putsysspace(CACHETAGS+((TRAPS+16*tbr)&(VACSIZE-1)), 0);
+ if(conf.ss2cachebug)
+ putsysspace(CACHETAGS+((TRAPS+16*tbr)&(conf.vacsize-1)), 0);
if(tbr > 16){ /* interrupt */
if(u && u->p->state==Running){
/* if active, FPop at head of Q is probably an excep */
@@ 133,6 133,9 @@ trap(Ureg *ur)
case 5: /* lance */
lanceintr();
break;
+ case 3: /* lance */
+ scsiintr();
+ break;
default:
goto Error;
}
@@ 521,7 524,7 @@ syscall(Ureg *aur)
/* SS2 bug: flush cache line holding trap entry in table */
if(conf.ss2)
- putsysspace(CACHETAGS+((TRAPS+16*128)&(VACSIZE-1)), 0);
+ putsysspace(CACHETAGS+((TRAPS+16*128)&(conf.vacsize-1)), 0);
if(u->p->fpstate == FPactive) {
fpquiet();