From 1efdb88a07a90b8d224da51a6422ea3bac8a7fa0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 7 Aug 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-08-07 --- gnot/dat.h | 1 + gnot/main.c | 1 + pc/dat.h | 1 + pc/main.c | 1 + port/devbit.c | 26 ++++ port/tcpinput.c | 9 +- port/tcptimer.c | 5 +- ss/clock.c | 2 + ss/dat.h | 56 +++++++- ss/devrtc.c | 369 ++++++++++++++++++++++++++++++++++++++++++++++++ ss/fns.h | 25 +++- ss/io.h | 106 ++++++++++++++ ss/l.s | 11 +- ss/main.c | 119 ++++++++++++++-- ss/mem.h | 22 +-- ss/mmu.c | 29 ++-- ss/rom.h | 55 ++++++++ ss/screen.c | 6 + ss/scsi.c | 297 ++++++++++++++++++++++++++++++++++++++ ss/trap.c | 9 +- 20 files changed, 1089 insertions(+), 61 deletions(-) create mode 100644 ss/devrtc.c create mode 100644 ss/rom.h create mode 100644 ss/scsi.c diff --git a/gnot/dat.h b/gnot/dat.h index 2bb64b796610e7203a3097e87ef684cb5b8aba44..70c46fff9d257d5a9203b63cb46befa6e3dcb25f 100644 --- a/gnot/dat.h +++ b/gnot/dat.h @@ -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; diff --git a/gnot/main.c b/gnot/main.c index 28f5d20041dc6f4ab5e3fc08cc57eb43517b63ec..90f5f3c765f1a8b5fc59678f94cdb3e2d6a9476a 100644 --- a/gnot/main.c +++ b/gnot/main.c @@ -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; diff --git a/pc/dat.h b/pc/dat.h index 2c3a00a154cc0cc1a52de8a0da5420d52b12b554..55e188491d5de3dea58aee66dcaa55bc98e8c674 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -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 */ diff --git a/pc/main.c b/pc/main.c index 02e8a16126d7b10917d82ed9b9b18710f013eed3..f9d3c6ec249f6b40f80d919b5b5710bb6cbbdb93 100644 --- a/pc/main.c +++ b/pc/main.c @@ -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; diff --git a/port/devbit.c b/port/devbit.c index 5fd69178c61ac9abdaf22b1d4ba8eaa819befe6d..2948a08ce351f4197086e229f7d55487b60fe771 100644 --- a/port/devbit.c +++ b/port/devbit.c @@ -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) diff --git a/port/tcpinput.c b/port/tcpinput.c index 087446c42b223e0e6218d4a36785274999e70455..aa2d1d7066ca59ffd80ebd62355934bf1ee4f6b6 100644 --- a/port/tcpinput.c +++ b/port/tcpinput.c @@ -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 */ diff --git a/port/tcptimer.c b/port/tcptimer.c index b829400a27144ce77650036debb96aa12ae98063..93da25b3c6a1548a093d137df93a111039099b13 100644 --- a/port/tcptimer.c +++ b/port/tcptimer.c @@ -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); } diff --git a/ss/clock.c b/ss/clock.c index ebd65caa20fd1fd328392006e0857ce4f0116b86..427b48418e1c64d6aab715cb6e8f9ef94d974558 100644 --- a/ss/clock.c +++ b/ss/clock.c @@ -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) diff --git a/ss/dat.h b/ss/dat.h index 389a54b79ce603c72d14a12e5258442d879c5a6f..2120661d60550d06cfdcebecff30d14c5000e116 100644 --- a/ss/dat.h +++ b/ss/dat.h @@ -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]; +}; diff --git a/ss/devrtc.c b/ss/devrtc.c new file mode 100644 index 0000000000000000000000000000000000000000..8dfb9aeb713b747a4b8c29ad21eadd3b94ff9524 --- /dev/null +++ b/ss/devrtc.c @@ -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; +} diff --git a/ss/fns.h b/ss/fns.h index 3ad4a0812a1ff1be4f0389a6b47529f24a239549..b934b28cf441c321f2ff24953f2a5da33fab9545 100644 --- a/ss/fns.h +++ b/ss/fns.h @@ -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); diff --git a/ss/io.h b/ss/io.h index 6ea3105eb2bdd6cd7de08727144ffd8e084f156b..1a9575185ef6821e71e36aa66fe7fd8cb73eb320 100644 --- a/ss/io.h +++ b/ss/io.h @@ -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]; + }; + }; +}; diff --git a/ss/l.s b/ss/l.s index b082594332f9cb5e875ed0885b3629be501caf15..6f5acb20ca02b455e6958dc2a4015a340d79a37d 100644 --- a/ss/l.s +++ b/ss/l.s @@ -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 diff --git a/ss/main.c b/ss/main.c index 9a18c2541092bb75c47bd1ecb5a58fcf50926096..2969bbaf5c2c316d4b123a2017832407777537ad 100644 --- a/ss/main.c +++ b/ss/main.c @@ -9,7 +9,13 @@ #include #include -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 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; } /* diff --git a/ss/mem.h b/ss/mem.h index 310fb692859d9a8290f07699885b573f31bd57bb..ff6becc38174dd2c25f88bf07caa26661a345927 100644 --- a/ss/mem.h +++ b/ss/mem.h @@ -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 @@ -121,15 +119,9 @@ #define VTAG(va) ((va>>22)&0x03F) #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) diff --git a/ss/mmu.c b/ss/mmu.c index 8a34d8ae61f474d0d486097bb7c2a60fc70efd83..a8df18488cbf78356ee7aed34b98e0c849550af2 100644 --- a/ss/mmu.c +++ b/ss/mmu.c @@ -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 && jticks)&(nc-1)); /* random guess */ + nc++; + for(j=1; t && j 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); diff --git a/ss/scsi.c b/ss/scsi.c new file mode 100644 index 0000000000000000000000000000000000000000..6fb5230a89ad0fdb29361962f149be3d479ec71f --- /dev/null +++ b/ss/scsi.c @@ -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 diff --git a/ss/trap.c b/ss/trap.c index 08395dbda239ceaf5bf757a9ac77f6de1d627b99..dc9eb02846b1a4f2c265fb65f402d445737c194f 100644 --- a/ss/trap.c +++ b/ss/trap.c @@ -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();