M boot/settime.c => boot/settime.c +0 -1
@@ 12,7 12,6 @@ settime(int islocal)
int timeset;
Dir dir;
char dirbuf[DIRLEN];
- char *srvname;
print("time...");
timeset = 0;
M gnot/dat.h => gnot/dat.h +0 -7
@@ 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
M gnot/devport.c => gnot/devport.c +1 -1
@@ 34,7 34,7 @@ Dirtab portdir[]={
#define Nportservice 8
static int (*portservice[Nportservice])(void);
-static Portpage portpage;
+ Portpage portpage;
static Lock intrlock;
int
M gnot/fns.h => gnot/fns.h +0 -9
@@ 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 *);
A gnot/scsi.c => gnot/scsi.c +309 -0
@@ 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;
+ }
+}
M pc/main.c => pc/main.c +1 -1
@@ 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
M port/devscsi.c => port/devscsi.c +72 -308
@@ 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,10 401,34 @@ 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)
{
Scsi *cmd;
@@ 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);
}
M port/devwren.c => port/devwren.c +24 -26
@@ 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<target>.<lun>
+ * param is #w<target>.<lun>
*/
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;
M port/portdat.h => port/portdat.h +50 -0
@@ 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;
@@ 218,6 221,53 @@ struct Etherpkt
#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)
*/
#define NQ 4096
M port/portfns.h => port/portfns.h +14 -0
@@ 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*);
M ss/dat.h => ss/dat.h +0 -48
@@ 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];
-};
M ss/fns.h => ss/fns.h +1 -8
@@ 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);
M ss/l.s => ss/l.s +23 -1
@@ 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
M ss/main.c => ss/main.c +117 -39
@@ 5,6 5,7 @@
#include "fns.h"
#include "io.h"
#include "init.h"
+#include "rom.h"
#include <libg.h>
#include <gnot.h>
@@ 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<nmeg; i++){
- pa = addr+i*MB;
- putw4(va, PPN(pa)|PTEVALID|PTEKERNEL|PTENOCACHE|PTEWRITE|PTEMAINMEM);
- *(ulong*)va = pa;
+ for(i=0; i<n; i++){
+ mempres[i] = 0;
+ addr = i*MB;
+ putw4(va, PPN(addr)|PTEVALID|PTEKERNEL|PTENOCACHE|PTEWRITE|PTEMAINMEM);
+ *(ulong*)va = addr;
+ if(*(ulong*)va == addr){
+ addr = ~addr;
+ *(ulong*)va = addr;
+ if(*(ulong*)va == addr){
+ mempres[i] = 1;
+ *(ulong*)va = i + '0';
+ }
+ }
}
- 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;
+ for(i=0; i<n; i++)
+ if(mempres[i]){
+ addr = i*MB;
+ putw4(va, PPN(addr)|PTEVALID|PTEKERNEL|PTENOCACHE|PTEWRITE|PTEMAINMEM);
+ mempres[i] = *(ulong*)va;
+ }else
+ mempres[i] = 0;
+}
+
+char name[1024];
+
+void
+romprops(ulong d, char *namep, ulong p)
+{
+ static ulong romp;
+ uchar buf[128];
+ int i, n;
+
+ romp += sprint(rombuf+romp, "romprops %lux %lux\n", d, p);
+ while(p && *(char*)p){
+ n = call(rom->conf->getproplen, d, p);
+ if(n>=0 && n<sizeof buf){
+ call(rom->conf->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; i<n; i++)
+ romp += sprint(rombuf+romp, "%.2ux ", buf[i]);
+ romp += sprint(rombuf+romp, "\n");
+ }
+ }else
+ romp += sprint(rombuf+romp, "%lux: %s(%d)\n", d, p, n);
+ p = call(rom->conf->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; i<nmeg; i++)
+ if(mempres[i]){
+ v = mempres[i];
+ for(j=i+1; j<nmeg && mempres[j]>v; 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;
M ss/rom.h => ss/rom.h +3 -1
@@ 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*);
};
M ss/scsi.c => ss/scsi.c +25 -5
@@ 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;