From c25663f25265cbe3c0c7acf29156c7795cfd6549 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 8 Aug 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-08-08 --- boot/settime.c | 1 - gnot/dat.h | 7 - gnot/devport.c | 2 +- gnot/fns.h | 9 -- gnot/scsi.c | 309 ++++++++++++++++++++++++++++++++++++++++ pc/main.c | 2 +- port/devscsi.c | 380 ++++++++++--------------------------------------- port/devwren.c | 50 ++++--- port/portdat.h | 50 +++++++ port/portfns.h | 14 ++ ss/dat.h | 48 ------- ss/fns.h | 9 +- ss/l.s | 24 +++- ss/main.c | 156 +++++++++++++++----- ss/rom.h | 4 +- ss/scsi.c | 30 +++- 16 files changed, 640 insertions(+), 455 deletions(-) create mode 100644 gnot/scsi.c diff --git a/boot/settime.c b/boot/settime.c index dce47b90843fbfe718ec5f7353f5c18447ed425f..3792e0d05e35b6d1fb9a19f7f5ea237090d24405 100644 --- a/boot/settime.c +++ b/boot/settime.c @@ -12,7 +12,6 @@ settime(int islocal) int timeset; Dir dir; char dirbuf[DIRLEN]; - char *srvname; print("time..."); timeset = 0; diff --git a/gnot/dat.h b/gnot/dat.h index 70c46fff9d257d5a9203b63cb46befa6e3dcb25f..7dca97328d4ad5fba5fae13dc00cfbcaa79903ff 100644 --- a/gnot/dat.h +++ b/gnot/dat.h @@ -8,7 +8,6 @@ typedef struct MMU MMU; typedef struct Mach Mach; typedef struct PMMU PMMU; typedef struct Portpage Portpage; -typedef struct Scsibuf Scsibuf; typedef struct Ureg Ureg; typedef struct User User; @@ -139,12 +138,6 @@ struct Portpage extern int portispaged; -struct Scsibuf -{ - void *virt; - void *phys; -}; - #define NERR 25 #define NNOTE 5 struct User diff --git a/gnot/devport.c b/gnot/devport.c index 4bca3c3b7f099234a88ca6118dc3ba3ee8be7b9a..8f63547e27704c1f8ac618e96bb1813e57beeaa6 100644 --- a/gnot/devport.c +++ b/gnot/devport.c @@ -34,7 +34,7 @@ Dirtab portdir[]={ #define Nportservice 8 static int (*portservice[Nportservice])(void); -static Portpage portpage; + Portpage portpage; static Lock intrlock; int diff --git a/gnot/fns.h b/gnot/fns.h index 71dcae85b52537c51dd3720576ca96e39d1cd8ff..f3b4059a2439d2b61a25d03eeb94393c10ce5e0a 100644 --- a/gnot/fns.h +++ b/gnot/fns.h @@ -36,15 +36,6 @@ void restfpregs(FPsave*); 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*); -int scsiready(int); -int scsisense(int, void *); -int scsicap(int, uchar *); void scsictrlintr(void); void scsidmaintr(void); uchar* scsirecv(uchar *); diff --git a/gnot/scsi.c b/gnot/scsi.c new file mode 100644 index 0000000000000000000000000000000000000000..dc250e416a763656fe45fb5bacd2d1a0f3bd3e85 --- /dev/null +++ b/gnot/scsi.c @@ -0,0 +1,309 @@ +#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" + +int scsiintr(void); + +#define DPRINT if(debug)kprint + +int scsidebugs[8]; +int scsiownid = 0x08|7; /* enable advanced features */ + +Scsibuf * +scsialloc(ulong n) +{ + Scsibuf *b; + + b = xalloc(sizeof(Scsibuf)); + b->virt = b->phys = xalloc(n); + return b; +} + +typedef struct Scsictl { + uchar asr; + uchar data; + uchar stat; + uchar dma; +} Scsictl; + +#define Scsiaddr 48 +#define DEV ((Scsictl *)&PORT[Scsiaddr]) + +static long poot; +#define WAIT (poot=0, poot==0?0:poot) + +#define PUT(a,d) (DEV->asr=(a), WAIT, DEV->data=(d)) +#define GET(a) (DEV->asr=(a), WAIT, DEV->data) + +enum Int_status { + Inten = 0x01, Scsirst = 0x02, + INTRQ = 0x01, DMA = 0x02, +}; + +enum SBIC_regs { + Own_id=0x00, Control=0x01, CDB=0x03, Target_LUN=0x0f, + Cmd_phase=0x10, Tc_hi=0x12, + Dest_id=0x15, Src_id=0x16, SCSI_Status=0x17, + Cmd=0x18, Data=0x19, +}; + +enum Commands { + Reset = 0x00, + Assert_ATN = 0x02, + Negate_ACK = 0x03, + Select_with_ATN = 0x06, + Select_with_ATN_and_Xfr = 0x08, + Select_and_Xfr = 0x09, + Transfer_Info = 0x20, + SBT = 0x80, /* modifier for single-byte transfer */ +}; + +enum Aux_status { + INT=0x80, LCI=0x40, BSY=0x20, CIP=0x10, + PE=0x02, DBR=0x01, +}; + +static int isscsi; +static QLock scsilock; +static Rendez scsirendez; +static uchar * datap; +static uchar * datalim; +static long debug, scsirflag, scsibusy, scsiinservice; + +static void +nop(void) +{} + +void +resetscsi(void) +{ + static int inited; + + if(!inited) + addportintr(scsiintr); + inited = 1; +} + +void +initscsi(void) +{ + isscsi = portprobe("scsi", -1, Scsiaddr, -1, 0L); + if (isscsi >= 0) { + DEV->stat = Scsirst; + delay(100); + DEV->stat = Inten; + while (DEV->stat & (INTRQ|DMA)) + nop(); + scsiownid &= 0x0f; /* possibly advanced features */ + scsiownid |= 0x80; /* 16MHz */ + PUT(Own_id, scsiownid); + PUT(Cmd, Reset); + } +} + +static int +scsidone(void *arg) +{ + USED(arg); + return (scsibusy == 0); +} + +int +scsiexec(Scsi *p, int rflag) +{ + long n; + + debug = scsidebugs[p->target&7]; + DPRINT("scsi %d.%d %2.2ux ", p->target, p->lun, *(p->cmd.ptr)); + qlock(&scsilock); + if(waserror()){ + qunlock(&scsilock); + DPRINT(" error return\n"); + nexterror(); + } + scsirflag = rflag; + p->rflag = rflag; + datap = p->data.base; + datalim = p->data.lim; + if ((scsiownid & 0x08) && rflag) + PUT(Dest_id, 0x40|p->target); + else + PUT(Dest_id, p->target); + PUT(Target_LUN, p->lun); + n = p->data.lim - p->data.base; + PUT(Tc_hi, n>>16); + DEV->data = n>>8; + DEV->data = n; + if (scsiownid & 0x08) { + n = p->cmd.lim - p->cmd.ptr; + DPRINT("len=%d ", n); + PUT(Own_id, n); + } + PUT(CDB, *(p->cmd.ptr)++); + while (p->cmd.ptr < p->cmd.lim) + DEV->data = *(p->cmd.ptr)++; + scsibusy = 1; + PUT(Cmd, Select_and_Xfr); + /*PUT(Cmd, Select_with_ATN_and_Xfr);*/ + DPRINT("S<"); + sleep(&scsirendez, scsidone, 0); + DPRINT(">\n"); + p->data.ptr = datap; + p->status = GET(Target_LUN); + p->status |= DEV->data<<8; + poperror(); + qunlock(&scsilock); + debug = 0; + return p->status; +} + +void +scsirun(void) +{ + wakeup(&scsirendez); + scsibusy = 0; +} + +void +scsireset0(void) +{ +/* PUT(Control, 0x29); /* burst DMA, halt on parity error */ + PUT(Control, 0x28); /* burst DMA, allow parity errors */ + PUT(Control+1, 0xff); /* timeout */ + PUT(Src_id, 0x80); /* enable reselection */ + scsirun(); + /*qunlock(&scsilock);*/ +} + +int +scsiintr(void) +{ + int status, s; + + if(isscsi < 0 || scsiinservice + || !((status = DEV->stat) & (DMA|INTRQ))) + return 0; + DEV->stat = 0; + scsiinservice = 1; + s = spl1(); + DPRINT("i%x ", status); + do{ + if (status & DMA) + scsidmaintr(); + if (status & INTRQ) + scsictrlintr(); + }while ((status = DEV->stat) & (DMA|INTRQ)); + splx(s); + scsiinservice = 0; + DEV->stat = Inten; + return 1; +} + +void +scsidmaintr(void) +{ + uchar *p = 0; +/* + * if (scsirflag) { + * unsigned char *p; + * DPRINT("R", p=datap); + * do + * *datap++ = DEV->dma; + * while (DEV->stat & DMA); + * DPRINT("%d ", datap-p); + * } else { + * unsigned char *p; + * DPRINT("W", p=datap); + * do + * DEV->dma = *datap++; + * while (DEV->stat & DMA); + * DPRINT("%d ", datap-p); + * } + */ + if(scsirflag){ + DPRINT("R", p=datap); + datap = scsirecv(datap); + DPRINT("%d ", datap-p); + }else{ + DPRINT("X", p=datap); + datap = scsixmit(datap); + DPRINT("%d ", datap-p); + } +} + +void +scsictrlintr(void) +{ + int status, phase; + long n; + + status = GET(SCSI_Status); + DPRINT("I%2.2x ", status); + switch(status){ + case 0x00: /* reset by command or power-up */ + case 0x01: /* reset by command or power-up */ + scsireset0(); + break; + case 0x21: /* Save Data Pointers message received */ + n = GET(Tc_hi); + n = (n<<8)|DEV->data; + n = (n<<8)|DEV->data; + datap = datalim - n; + PUT(Cmd_phase, 0x41); + PUT(Cmd, Select_and_Xfr); + break; + case 0x16: /* select-and-transfer completed */ + case 0x42: /* timeout during select */ + scsirun(); + break; + case 0x4b: /* unexpected status phase */ + DEV->asr = Target_LUN; + kprint("lun/status 0x%ux\n", DEV->data); + phase = DEV->data; + kprint("phase 0x%ux\n", phase); + PUT(Tc_hi, 0); + DEV->data = 0; + DEV->data = 0; + switch(phase){ + case 0x50: + case 0x60: + break; + default: + phase = 0x46; + break; + } + PUT(Cmd_phase, phase); + PUT(Cmd, Select_and_Xfr); + break; + default: + kprint("scsintr 0x%ux\n", status); + DEV->asr = Target_LUN; + kprint("lun/status 0x%ux\n", DEV->data); + kprint("phase 0x%ux\n", DEV->data); + switch (status&0xf0) { + case 0x00: + case 0x10: + case 0x20: + case 0x40: + case 0x80: + if(status & 0x08){ + kprint("count 0x%ux", GET(Tc_hi)); + kprint(" 0x%ux", DEV->data); + kprint(" 0x%ux\n", DEV->data); + } + scsirun(); + break; + default: + panic("scsi status 0x%2.2ux", status); + } + kprint("resetting..."); + PUT(Own_id, scsiownid); + PUT(Cmd, Reset); + break; + } +} diff --git a/pc/main.c b/pc/main.c index f9d3c6ec249f6b40f80d919b5b5710bb6cbbdb93..075490a06384f883539d8ed91f28986e8b79821e 100644 --- a/pc/main.c +++ b/pc/main.c @@ -7,7 +7,7 @@ #include "ureg.h" #include "init.h" -int machtype; +int machtype; /* machine type, mostly for power management */ uchar *sp; /* stack pointer for /boot */ void diff --git a/port/devscsi.c b/port/devscsi.c index e2ce5c5907b21633f8c822a7425fc4faff333496..c359bdbde2d47962b6eaac8f1360daf5f079e504 100644 --- a/port/devscsi.c +++ b/port/devscsi.c @@ -5,51 +5,16 @@ #include "fns.h" #include "../port/error.h" #include "devtab.h" -#include "io.h" #define DPRINT if(debug)kprint -typedef struct Scsi Scsi; -typedef struct Scsidata Scsidata; +#define Nbuf 2 +#define DATASIZE (32*512) -#define Nbuf 4 -#define DATASIZE (8*1024) -enum -{ - ScsiTestunit = 0x00, - ScsiExtsens = 0x03, - ScsiGetcap = 0x25, - ScsiRead = 0x08, - ScsiWrite = 0x0a, - - /* - * data direction - */ - ScsiIn = 1, - ScsiOut = 0, -}; - -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]; -}; +struct{ + Lock; + Scsibuf *free; +}scsibufalloc; static Scsi staticcmd; /* BUG: should be one per scsi device */ @@ -68,12 +33,8 @@ static Dirtab scsidir[]={ }; #define NSCSI (sizeof scsidir/sizeof(Dirtab)) -static int debugs[8]; -static int ownid = 0x08|7; /* enable advanced features */ - -int scsiexec(Scsi*, int); -int scsiintr(void); -void scsireset(void); +extern int scsidebugs[]; +extern int scsiownid; static int scsigen1(Chan *c, long qid, Dir *dp) @@ -117,6 +78,24 @@ scsigen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp) return scsigen1(c, (c->qid.path&~CHDIR)+s+1, dp); } +void +scsireset(void) +{ + int i; + + for(i = 0; i < Nbuf; i++) + scsifree(scsialloc(DATASIZE)); + lock(&scsibufalloc); + unlock(&scsibufalloc); + resetscsi(); +} + +void +scsiinit(void) +{ + initscsi(); +} + Chan * scsiattach(char *param) { @@ -181,7 +160,7 @@ scsiread(Chan *c, char *a, long n, ulong offset) if(c->qid.path==1){ if(offset == 0){ /*void scsidump(void); scsidump();*/ - *a = ownid; + *a = scsiownid; n = 1; }else n = 0; @@ -230,7 +209,7 @@ scsiread(Chan *c, char *a, long n, ulong offset) case Qdebug: if(offset == 0){ n=1; - *a="01"[debugs[(c->qid.path>>4)&7]!=0]; + *a="01"[scsidebugs[(c->qid.path>>4)&7]!=0]; }else n = 0; break; @@ -248,7 +227,7 @@ scsiwrite(Chan *c, char *a, long n, ulong offset) if(c->qid.path==1 && n>0){ if(offset == 0){ n = 1; - ownid=*a; + scsiownid=*a; scsireset(); }else n = 0; @@ -292,7 +271,7 @@ scsiwrite(Chan *c, char *a, long n, ulong offset) break; case Qdebug: if(offset == 0){ - debugs[(c->qid.path>>4)&7] = (*a=='1'); + scsidebugs[(c->qid.path>>4)&7] = (*a=='1'); n = 1; }else n = 0; @@ -343,6 +322,9 @@ scsicmd(int dev, int cmdbyte, Scsibuf *b, long size) switch(cmdbyte){ case ScsiTestunit: break; + case ScsiModesense: + cmd->cmdblk[2] = 1; + /* fall through */ case ScsiExtsens: cmd->cmdblk[4] = size; break; @@ -419,9 +401,33 @@ scsicap(int dev, void *p) qunlock(cmd); if((status&0xff00) != 0x6000) error(Eio); + if(status & 0xFF) + scsisense(dev, p); return status&0xff; } +int +scsiwp(int dev) +{ + Scsi *cmd; + int r, status; + + cmd = scsicmd(dev, ScsiModesense, scsibuf(), 12); + if(waserror()){ + scsifree(cmd->b); + qunlock(cmd); + nexterror(); + } + status = scsiexec(cmd, ScsiIn); + r = cmd->data.base[2] & 0x80; + poperror(); + scsifree(cmd->b); + qunlock(cmd); + if ((status&0xffff) != 0x6000) + error(Eio); + return r; +} + int scsibread(int dev, Scsibuf *b, long n, long blocksize, long blockno) { @@ -472,267 +478,25 @@ scsibuf(void) { Scsibuf *b; - b = smalloc(sizeof(Scsibuf)+DATASIZE); - b->phys = (void*)(b + 1); - b->virt = b->phys; - return b; -} - -void -scsifree(Scsibuf *b) -{ - free(b); -} - -typedef struct Scsictl { - uchar asr; - uchar data; - uchar stat; - uchar dma; -} Scsictl; - -#define Scsiaddr 48 -#define DEV ((Scsictl *)&PORT[Scsiaddr]) - -static long poot; -#define WAIT (poot=0, poot==0?0:poot) - -#define PUT(a,d) (DEV->asr=(a), WAIT, DEV->data=(d)) -#define GET(a) (DEV->asr=(a), WAIT, DEV->data) - -enum Int_status { - Inten = 0x01, Scsirst = 0x02, - INTRQ = 0x01, DMA = 0x02, -}; - -enum SBIC_regs { - Own_id=0x00, Control=0x01, CDB=0x03, Target_LUN=0x0f, - Cmd_phase=0x10, Tc_hi=0x12, - Dest_id=0x15, Src_id=0x16, SCSI_Status=0x17, - Cmd=0x18, Data=0x19, -}; - -enum Commands { - Reset = 0x00, - Assert_ATN = 0x02, - Negate_ACK = 0x03, - Select_with_ATN = 0x06, - Select_with_ATN_and_Xfr = 0x08, - Select_and_Xfr = 0x09, - Transfer_Info = 0x20, - SBT = 0x80, /* modifier for single-byte transfer */ -}; - -enum Aux_status { - INT=0x80, LCI=0x40, BSY=0x20, CIP=0x10, - PE=0x02, DBR=0x01, -}; - -static int isscsi; -static QLock scsilock; -static Rendez scsirendez; -static uchar *datap; -static long debug, scsirflag, scsibusy, scsiinservice; - -static void -nop(void) -{} - -void -scsireset(void) -{ - addportintr(scsiintr); -} - -void -scsiinit(void) -{ - isscsi = portprobe("scsi", -1, Scsiaddr, -1, 0L); - if (isscsi >= 0) { - DEV->stat = Scsirst; - WAIT; nop(); WAIT; - DEV->stat = Inten; - while (DEV->stat & (INTRQ|DMA)) - nop(); - ownid &= 0x0f; /* possibly advanced features */ - ownid |= 0x80; /* 16MHz */ - PUT(Own_id, ownid); - PUT(Cmd, Reset); - } -} - -static int -scsidone(void *arg) -{ - USED(arg); - return (scsibusy == 0); -} - -int -scsiexec(Scsi *p, int rflag) -{ - long n; - debug = debugs[p->target&7]; - DPRINT("scsi %d.%d ", p->target, p->lun); - qlock(&scsilock); - if(waserror()){ - qunlock(&scsilock); - nexterror(); - } - scsirflag = rflag; - p->rflag = rflag; - datap = p->data.base; - if ((ownid & 0x08) && rflag) - PUT(Dest_id, 0x40|p->target); - else - PUT(Dest_id, p->target); - PUT(Target_LUN, p->lun); - n = p->data.lim - p->data.base; - PUT(Tc_hi, n>>16); - DEV->data = n>>8; - DEV->data = n; - if (ownid & 0x08) { - n = p->cmd.lim - p->cmd.ptr; - DPRINT("len=%d ", n); - PUT(Own_id, n); - } - PUT(CDB, *(p->cmd.ptr)++); - while (p->cmd.ptr < p->cmd.lim) - DEV->data = *(p->cmd.ptr)++; - scsibusy = 1; - PUT(Cmd, Select_and_Xfr); - DPRINT("S<"); - sleep(&scsirendez, scsidone, 0); - DPRINT(">"); - p->data.ptr = datap; - p->status = GET(Target_LUN); - p->status |= DEV->data<<8; - poperror(); - qunlock(&scsilock); - debug = 0; - return p->status; -} - -void -scsirun(void) -{ - wakeup(&scsirendez); - scsibusy = 0; -} - -void -scsireset0(void) -{ - PUT(Control, 0x29); /* burst DMA, halt on parity error */ - PUT(Control+1, 0xff); /* timeout */ - PUT(Src_id, 0x80); /* enable reselection */ - scsirun(); - /*qunlock(&scsilock);*/ -} - -int -scsiintr(void) -{ - int status, s; - if (isscsi < 0 || scsiinservice - || !((status = DEV->stat) & (DMA|INTRQ))) - return 0; - DEV->stat = 0; - scsiinservice = 1; - s = spl1(); - DPRINT("i%x ", status); - do { - if (status & DMA) - scsidmaintr(); - if (status & INTRQ) - scsictrlintr(); - } while ((status = DEV->stat) & (DMA|INTRQ)); - splx(s); - scsiinservice = 0; - DEV->stat = Inten; - return 1; -} + for(;;) { + lock(&scsibufalloc); + if(b = scsibufalloc.free) { + scsibufalloc.free = b->next; + unlock(&scsibufalloc); + return b; + } -void -scsidmaintr(void) -{ - uchar *p = 0; -/* - * if (scsirflag) { - * unsigned char *p; - * DPRINT("R", p=datap); - * do - * *datap++ = DEV->dma; - * while (DEV->stat & DMA); - * DPRINT("%d ", datap-p); - * } else { - * unsigned char *p; - * DPRINT("W", p=datap); - * do - * DEV->dma = *datap++; - * while (DEV->stat & DMA); - * DPRINT("%d ", datap-p); - * } - */ - if (scsirflag) { - DPRINT("R", p=datap); - datap = scsirecv(datap); - DPRINT("%d ", datap-p); - } else { - DPRINT("X", p=datap); - datap = scsixmit(datap); - DPRINT("%d ", datap-p); + unlock(&scsibufalloc); + resrcwait("no scsi buffers"); } + return 0; /* not reached */ } void -scsictrlintr(void) +scsifree(Scsibuf *b) { - int status; - status = GET(SCSI_Status); - DPRINT("I%2.2x ", status); - switch(status){ - case 0x00: /* reset by command or power-up */ - case 0x01: /* reset by command or power-up */ - scsireset0(); - break; - case 0x21: /* Save Data Pointers message received */ - break; - case 0x16: /* select-and-transfer completed */ - case 0x42: /* timeout during select */ - scsirun(); - break; - case 0x4b: /* unexpected status phase */ - PUT(Tc_hi, 0); - DEV->data = 0; - DEV->data = 0; - PUT(Cmd_phase, 0x46); - PUT(Cmd, Select_and_Xfr); - break; - default: - kprint("scsintr 0x%ux\n", status); - DEV->asr = Target_LUN; - kprint("lun/status 0x%ux\n", DEV->data); - kprint("phase 0x%ux\n", DEV->data); - switch (status&0xf0) { - case 0x00: - case 0x10: - case 0x20: - case 0x40: - case 0x80: - if (status & 0x08) { - kprint("count 0x%ux", GET(Tc_hi)); - kprint(" 0x%ux", DEV->data); - kprint(" 0x%ux\n", DEV->data); - } - scsirun(); - break; - default: - panic("scsi status 0x%2.2ux", status); - } - kprint("resetting..."); - PUT(Own_id, ownid); - PUT(Cmd, Reset); - break; - } + lock(&scsibufalloc); + b->next = scsibufalloc.free; + scsibufalloc.free = b; + unlock(&scsibufalloc); } diff --git a/port/devwren.c b/port/devwren.c index f036e3b3cf7f7c145b9870cef4ac829bbb5a91c8..f822f81cc7d9000d9ad74b5021cfc59f1b12092b 100644 --- a/port/devwren.c +++ b/port/devwren.c @@ -37,7 +37,7 @@ struct Drive ulong bytes; /* bytes per block */ int npart; /* actual number of partitions */ int drive; - int ready; /* true if ever ready */ + int readonly; Partition p[Npart]; }; @@ -96,7 +96,7 @@ wrengen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp) name[NAMELEN] = 0; qid.path = MKQID(drive, s); l = (pp->end - pp->start) * dp->bytes; - devdir(c, qid, name, l, eve, 0666, dirp); + devdir(c, qid, name, l, eve, dp->readonly ? 0444 : 0666, dirp); return 1; } @@ -111,7 +111,7 @@ wreninit(void) } /* - * param is #r. + * param is #w. */ Chan * wrenattach(char *param) @@ -273,28 +273,26 @@ wrenpart(int dev) nexterror(); } qlock(dp); - if(!dp->ready){ - scsiready(dev); - scsisense(dev, buf); - if (scsicap(dev, buf)) - error(Eio); - dp->drive = dev; - dp->ready = 1; - - /* - * we always have a partition for the whole disk - * and one for the partition table - */ - dp->bytes = (buf[4]<<24)+(buf[5]<<16)+(buf[6]<<8)+(buf[7]); - pp = &dp->p[0]; - strcpy(pp->name, "disk"); - pp->start = 0; - pp->end = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]) + 1; - pp++; - strcpy(pp->name, "partition"); - pp->start = dp->p[0].end - 1; - pp->end = dp->p[0].end; - } + scsiready(dev); + scsisense(dev, buf); + if(scsicap(dev, buf)) + error(Eio); + dp->drive = dev; + dp->readonly = scsiwp(dev); + + /* + * we always have a partition for the whole disk + * and one for the partition table + */ + dp->bytes = (buf[4]<<24)+(buf[5]<<16)+(buf[6]<<8)+(buf[7]); + pp = &dp->p[0]; + strcpy(pp->name, "disk"); + pp->start = 0; + pp->end = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]) + 1; + pp++; + strcpy(pp->name, "partition"); + pp->start = dp->p[0].end - 1; + pp->end = dp->p[0].end; /* * read partition table from disk, null terminate @@ -313,7 +311,7 @@ wrenpart(int dev) */ pp = &dp->p[2]; n = getfields(rawpart, line, Npart+1, '\n'); - if(strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){ + if(n > 0 && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){ for(i = 1; i < n; i++){ if(getfields(line[i], field, 3, ' ') != 3) break; diff --git a/port/portdat.h b/port/portdat.h index 645be390e8322725dfc9cc6b5342263df8118162..6e8b186f4b6002c3373f4cff8b2ffb346a375f7d 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -33,6 +33,9 @@ typedef struct Ref Ref; typedef struct Rendez Rendez; typedef struct RWlock RWlock; typedef struct Sargs Sargs; +typedef struct Scsi Scsi; +typedef struct Scsibuf Scsibuf; +typedef struct Scsidata Scsidata; typedef struct Segment Segment; typedef struct Stream Stream; typedef struct Talarm Talarm; @@ -217,6 +220,53 @@ struct Etherpkt #define ETHERMAXTU 1514 /* maximum transmit size */ #define ETHERHDRSIZE 14 /* size of an ethernet header */ +/* + * SCSI devices. + */ +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]; +}; /* * character based IO (mouse, keyboard, console screen) */ diff --git a/port/portfns.h b/port/portfns.h index 46d9fe94199b9fa2df05317c60dc04df724a5fc6..aec3ecad5460e976bf84ef5ebea6a8c23ace26b0 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -26,6 +26,7 @@ void closemount(Mount*); void closepgrp(Pgrp*); long clrfpintr(void); void confinit(void); +void confinit1(int); int consactive(void); void consdebug(void); Block* copyb(Block*, int); @@ -82,6 +83,7 @@ int hwcursset(uchar*, uchar*, int, int); long ibrk(ulong, int); int incref(Ref*); void initq(IOQ*); +void initscsi(void); void initseg(void); void invalidateu(void); void isdir(Chan*); @@ -181,6 +183,7 @@ int readstr(ulong, char*, ulong, char*); void ready(Proc*); void relocateseg(Segment*, ulong); void resched(char*); +void resetscsi(void); void resrcwait(char*); int return0(void*); void rlock(RWlock*); @@ -194,6 +197,17 @@ void sccspecial(int, IOQ*, IOQ*, int); void sched(void); void schedinit(void); int screenbits(void); +Scsibuf* scsialloc(ulong); +int scsibread(int, Scsibuf*, long, long, long); +Scsibuf* scsibuf(void); +int scsibwrite(int, Scsibuf*, long, long, long); +int scsicap(int, void*); +Scsi* scsicmd(int, int, Scsibuf*, long); +int scsiexec(Scsi*, int); +void scsifree(Scsibuf*); +int scsiready(int); +int scsisense(int, void*); +int scsiwp(int); long seconds(void); ulong segattach(Proc*, ulong, char *, ulong, ulong); void segpage(Segment*, Page*); diff --git a/ss/dat.h b/ss/dat.h index 2120661d60550d06cfdcebecff30d14c5000e116..4273f117c46c1e81ef70daed8ed2271c0fa83546 100644 --- a/ss/dat.h +++ b/ss/dat.h @@ -7,9 +7,6 @@ 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; @@ -214,48 +211,3 @@ 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/fns.h b/ss/fns.h index b934b28cf441c321f2ff24953f2a5da33fab9545..f70973854c7158b4ad8dbc5b4752163b743b52ca 100644 --- a/ss/fns.h +++ b/ss/fns.h @@ -1,6 +1,7 @@ #include "../port/portfns.h" void cacheinit(void); +ulong call(void*, ...); void clearftt(ulong); #define clearmmucache() void clockinit(void); @@ -56,15 +57,7 @@ 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); diff --git a/ss/l.s b/ss/l.s index 6f5acb20ca02b455e6958dc2a4015a340d79a37d..049aaaa8169f3cd576c80797c1619c764dfd3957 100644 --- a/ss/l.s +++ b/ss/l.s @@ -22,7 +22,7 @@ TEXT start(SB), $-4 TEXT startvirt(SB), $-4 - MOVW $romvec(SB), R7 + MOVW $rom(SB), R7 MOVW R8, (R7) /* romvec passed in %i0==R8 */ MOVW $BOOTSTACK, R1 @@ -453,3 +453,25 @@ TEXT clearftt(SB), $0 GLOBL mach0+0(SB), $MACHSIZE GLOBL fsr+0(SB), $BY2WD + +/* + * Interface to ROM. Must save and restore state because + * of different calling conventions. + */ + +TEXT call(SB), $16 + MOVW R1, R14 /* save my SP in their SP */ + MOVW R2, sb-4(SP) + MOVW R(MACH), mach-8(SP) + MOVW R(USER), user-12(SP) + MOVW param1+4(FP), R8 + MOVW param2+8(FP), R9 + MOVW param3+12(FP), R10 + MOVW param4+16(FP), R11 + JMPL (R7) + MOVW R14, R1 /* restore my SP */ + MOVW user-12(SP), R(USER) + MOVW mach-8(SP), R(MACH) + MOVW sb-4(SP), R2 + MOVW R8, R7 /* move their return value into mine */ + RETURN diff --git a/ss/main.c b/ss/main.c index 2969bbaf5c2c316d4b123a2017832407777537ad..7800c89f75f02fc40cfcee6e997a75b359a68aba 100644 --- a/ss/main.c +++ b/ss/main.c @@ -5,6 +5,7 @@ #include "fns.h" #include "io.h" #include "init.h" +#include "rom.h" #include #include @@ -12,10 +13,12 @@ uchar *intrreg; int model; uchar idprom[32]; -ulong romvec; /* open boot rom vector */ +ROM *rom; /* open boot rom vector */ int cpuserver; -ulong romputcxsegm; +void (*romputcxsegm)(int, ulong, int); ulong bank[2]; +char rombuf[20000]; +char mempres[256]; void main(void) @@ -114,6 +117,7 @@ init0(void) kproc("alarm", alarmkproc, 0); chandevinit(); + if(!waserror()){ ksetterm("sun %s"); ksetenv("cputype", "sparc"); @@ -204,34 +208,86 @@ exit(void) systemreset(); } -int -banksize(ulong addr, ulong nbytes) +void +scanmem(char *mempres, int n) { int i; - ulong min, max, t; - ulong va, pa; - ulong nmeg; + ulong va, addr; - nmeg = nbytes/MB; va = 1*MB-2*BY2PG; - for(i=0; i t) - min = t; - if(max < t) - max = t; + for(i=0; iconf->getproplen, d, p); + if(n>=0 && nconf->getprop, d, p, buf); + if(strcmp((char*)p, "name")==0){ + strcpy(namep, (char*)buf); + romp += sprint(rombuf+romp, "`%s'\n", name); + }else{ + romp += sprint(rombuf+romp, "%lux: %s: ", d, p); + for(i=0; iconf->nextprop, d, p); + } +} + +void +romwalk(ulong d, char* namep) +{ + char *endp; + + *namep++ = '/'; + *namep = 0; + while(d){ + romprops(d, namep, call(rom->conf->nextprop, d, 0)); + endp = namep+strlen(namep); + romwalk(call(rom->conf->child, d), endp); + *endp = 0; + d = call(rom->conf->next, d); } - putw4(va, INVALIDPTE); - return (max-min)/MB+1; +} + +void +fuck(void) +{ + name[0] = 0; + romwalk(call(rom->conf->next, 0), name); } Conf conf; @@ -240,8 +296,8 @@ void confinit(void) { int mul; - ulong i; - ulong ktop, va, mbytes; + ulong i, j; + ulong ktop, va, mbytes, nmeg, npg, v; conf.nmach = 1; if(conf.nmach > MAXMACH) @@ -256,8 +312,14 @@ confinit(void) putw4(va, INVALIDPTE); switch(idprom[1]){ - case 0x51: /* sparcstation 1 */ - case 0x54: /* slc */ + + /* sparcstation 1+ BUG: unknown! */ + case 0x52: /* IPC 4/40 */ + case 0x53: /* sparcstation 1+ 4/65 */ + /* fall through */ + /* sparcstation 1 */ + case 0x51: /* sparcstation 1 4/60 */ + case 0x54: /* slc 4/20 */ default: conf.ss2 = 0; conf.vacsize = 65536; @@ -266,11 +328,13 @@ confinit(void) conf.npmeg = 128; conf.ss2cachebug = 0; conf.monitor = 1; /* BUG */ - conf.base0 = 0; - conf.base1 = 32*MB; + nmeg = 64; break; - case 0x55: /* sparcstation 2 */ + /* sparcstation 2 */ + case 0x55: /* sparcstation 2 4/75 */ + case 0x56: /* ELC 4/25 */ + case 0x57: /* IPX 4/50 */ conf.ss2 = 1; conf.vacsize = 65536; conf.vaclinesize = 32; @@ -278,18 +342,30 @@ confinit(void) conf.npmeg = 256; conf.ss2cachebug = 1; conf.monitor = 0; /* BUG */ - conf.base0 = 0; - conf.base1 = 16*MB; + nmeg = 64; 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; - - romputcxsegm = *(ulong*)(romvec+260); + scanmem(mempres, nmeg); + for(i=0; iv; j++) + v = mempres[j]; + npg = ((v+1)-mempres[i])*MB/BY2PG; + if(conf.npage0 == 0){ + conf.base0 = i*MB; + conf.npage0 = npg; + }else if(conf.npage1 < npg){ + conf.base1 = i*MB; + conf.npage1 = npg; + } + i = v-'0'; + } + bank[0] = conf.npage0*BY2PG/MB; + bank[1] = conf.npage1*BY2PG/MB; + conf.npage = conf.npage0+conf.npage1; conf.upages = (conf.npage*70)/100; if(cpuserver){ @@ -298,6 +374,8 @@ confinit(void) conf.upages += i - ((6*MB)/BY2PG); } + romputcxsegm = rom->putcxsegm; + ktop = PGROUND((ulong)end); ktop = PADDR(ktop); conf.npage0 -= ktop/BY2PG; diff --git a/ss/rom.h b/ss/rom.h index 25cf88d2893da1169f86f9cf558fcc2d640e27c8..ed4ee2cbe95ee8b4ceffafa04ff0e11e755893aa 100644 --- a/ss/rom.h +++ b/ss/rom.h @@ -34,7 +34,8 @@ struct ROM uint (*seek)(uint, uint, uint); void (*chain)(void*, uint, void*, void*, uint); void (*release)(void*, uint); - uint pad5[16]; + uint pad4[15]; + void (*putcxsegm)(int, ulong, int); int (*startcpu)(uint, uint, uint, uint); int (*stopcpu)(uint); int (*idlecpu)(uint); @@ -47,6 +48,7 @@ struct ROMconf uint (*child)(uint); int (*getproplen)(uint, void*); int (*getprop)(uint, void*, void*); + int (*setprop)(uint, void*, void*); void* (*nextprop)(uint, void*); }; diff --git a/ss/scsi.c b/ss/scsi.c index 6fb5230a89ad0fdb29361962f149be3d479ec71f..e1963ef07f0653b3b5148ce16fa432c51da668ed 100644 --- a/ss/scsi.c +++ b/ss/scsi.c @@ -7,7 +7,10 @@ #include "devtab.h" #include "io.h" -static int ownid = 7; +int scsiownid = 7; +int scsidebugs[8]; + +static int dmatype; Scsibuf * scsialloc(ulong n) @@ -92,7 +95,7 @@ resetscsi(void) dev->timeout = 146; dev->syncperiod = 0; dev->syncoffset = 0; - dev->config = 0x10|(ownid&7); + dev->config = 0x10|(scsiownid&7); dev->cmd = Dma|Nop; dma->csr = Dma_Reset; @@ -100,6 +103,8 @@ resetscsi(void) dma->csr = Int_en; dma->count = 0; + dmatype = (dma->csr>>28) & 0xF; + putenab(getenab()|ENABDMA); /**/ } @@ -251,9 +256,23 @@ scsiintr(void) goto Done; } - if(p->rflag) - while(dma->csr & Pack_cnt) - ; + if(p->rflag){ + switch(dmatype){ + + case 8: + dma->csr = Drain|Int_en; + /*FALLTHROUGH*/ + + case 9: + while(dma->csr & Pack_cnt) + ; + break; + + default: + break; + } + } + dev->cmd = Cmdcomplete; return; @@ -261,6 +280,7 @@ scsiintr(void) case 0x46: /* Cmdcomplete was issued */ p->status = 0x6000|dev->fifo; m = dev->fifo; + USED(m); dev->cmd = Msgaccept; return;