## diffname gnot/scsi.c 1992/0808 ## diff -e /dev/null /n/bootesdump/1992/0808/sys/src/9/gnot/scsi.c 0a #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; } } . ## diffname gnot/scsi.c 1993/0501 # deleted ## diff -e /n/bootesdump/1992/0808/sys/src/9/gnot/scsi.c /n/fornaxdump/1993/0501/sys/src/brazil/gnot/scsi.c 1,309d