|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "../port/error.h" ! 7: #include "devtab.h" ! 8: #include "io.h" ! 9: ! 10: int scsiintr(void); ! 11: ! 12: #define DPRINT if(debug)kprint ! 13: ! 14: int scsidebugs[8]; ! 15: int scsiownid = 0x08|7; /* enable advanced features */ ! 16: ! 17: Scsibuf * ! 18: scsialloc(ulong n) ! 19: { ! 20: Scsibuf *b; ! 21: ! 22: b = xalloc(sizeof(Scsibuf)); ! 23: b->virt = b->phys = xalloc(n); ! 24: return b; ! 25: } ! 26: ! 27: typedef struct Scsictl { ! 28: uchar asr; ! 29: uchar data; ! 30: uchar stat; ! 31: uchar dma; ! 32: } Scsictl; ! 33: ! 34: #define Scsiaddr 48 ! 35: #define DEV ((Scsictl *)&PORT[Scsiaddr]) ! 36: ! 37: static long poot; ! 38: #define WAIT (poot=0, poot==0?0:poot) ! 39: ! 40: #define PUT(a,d) (DEV->asr=(a), WAIT, DEV->data=(d)) ! 41: #define GET(a) (DEV->asr=(a), WAIT, DEV->data) ! 42: ! 43: enum Int_status { ! 44: Inten = 0x01, Scsirst = 0x02, ! 45: INTRQ = 0x01, DMA = 0x02, ! 46: }; ! 47: ! 48: enum SBIC_regs { ! 49: Own_id=0x00, Control=0x01, CDB=0x03, Target_LUN=0x0f, ! 50: Cmd_phase=0x10, Tc_hi=0x12, ! 51: Dest_id=0x15, Src_id=0x16, SCSI_Status=0x17, ! 52: Cmd=0x18, Data=0x19, ! 53: }; ! 54: ! 55: enum Commands { ! 56: Reset = 0x00, ! 57: Assert_ATN = 0x02, ! 58: Negate_ACK = 0x03, ! 59: Select_with_ATN = 0x06, ! 60: Select_with_ATN_and_Xfr = 0x08, ! 61: Select_and_Xfr = 0x09, ! 62: Transfer_Info = 0x20, ! 63: SBT = 0x80, /* modifier for single-byte transfer */ ! 64: }; ! 65: ! 66: enum Aux_status { ! 67: INT=0x80, LCI=0x40, BSY=0x20, CIP=0x10, ! 68: PE=0x02, DBR=0x01, ! 69: }; ! 70: ! 71: static int isscsi; ! 72: static QLock scsilock; ! 73: static Rendez scsirendez; ! 74: static uchar * datap; ! 75: static uchar * datalim; ! 76: static long debug, scsirflag, scsibusy, scsiinservice; ! 77: ! 78: static void ! 79: nop(void) ! 80: {} ! 81: ! 82: void ! 83: resetscsi(void) ! 84: { ! 85: static int inited; ! 86: ! 87: if(!inited) ! 88: addportintr(scsiintr); ! 89: inited = 1; ! 90: } ! 91: ! 92: void ! 93: initscsi(void) ! 94: { ! 95: isscsi = portprobe("scsi", -1, Scsiaddr, -1, 0L); ! 96: if (isscsi >= 0) { ! 97: DEV->stat = Scsirst; ! 98: delay(100); ! 99: DEV->stat = Inten; ! 100: while (DEV->stat & (INTRQ|DMA)) ! 101: nop(); ! 102: scsiownid &= 0x0f; /* possibly advanced features */ ! 103: scsiownid |= 0x80; /* 16MHz */ ! 104: PUT(Own_id, scsiownid); ! 105: PUT(Cmd, Reset); ! 106: } ! 107: } ! 108: ! 109: static int ! 110: scsidone(void *arg) ! 111: { ! 112: USED(arg); ! 113: return (scsibusy == 0); ! 114: } ! 115: ! 116: int ! 117: scsiexec(Scsi *p, int rflag) ! 118: { ! 119: long n; ! 120: ! 121: debug = scsidebugs[p->target&7]; ! 122: DPRINT("scsi %d.%d %2.2ux ", p->target, p->lun, *(p->cmd.ptr)); ! 123: qlock(&scsilock); ! 124: scsirflag = rflag; ! 125: p->rflag = rflag; ! 126: datap = p->data.base; ! 127: datalim = p->data.lim; ! 128: if ((scsiownid & 0x08) && rflag) ! 129: PUT(Dest_id, 0x40|p->target); ! 130: else ! 131: PUT(Dest_id, p->target); ! 132: PUT(Target_LUN, p->lun); ! 133: n = p->data.lim - p->data.base; ! 134: PUT(Tc_hi, n>>16); ! 135: DEV->data = n>>8; ! 136: DEV->data = n; ! 137: if (scsiownid & 0x08) { ! 138: n = p->cmd.lim - p->cmd.ptr; ! 139: DPRINT("len=%d ", n); ! 140: PUT(Own_id, n); ! 141: } ! 142: PUT(CDB, *(p->cmd.ptr)++); ! 143: while (p->cmd.ptr < p->cmd.lim) ! 144: DEV->data = *(p->cmd.ptr)++; ! 145: scsibusy = 1; ! 146: PUT(Cmd, Select_and_Xfr); ! 147: /*PUT(Cmd, Select_with_ATN_and_Xfr);*/ ! 148: while(waserror()) ! 149: ; ! 150: DPRINT("S<"); ! 151: sleep(&scsirendez, scsidone, 0); ! 152: DPRINT(">\n"); ! 153: p->data.ptr = datap; ! 154: p->status = GET(Target_LUN); ! 155: p->status |= DEV->data<<8; ! 156: poperror(); ! 157: qunlock(&scsilock); ! 158: debug = 0; ! 159: return p->status; ! 160: } ! 161: ! 162: void ! 163: scsirun(void) ! 164: { ! 165: wakeup(&scsirendez); ! 166: scsibusy = 0; ! 167: } ! 168: ! 169: void ! 170: scsireset0(void) ! 171: { ! 172: /* PUT(Control, 0x29); /* burst DMA, halt on parity error */ ! 173: PUT(Control, 0x28); /* burst DMA, allow parity errors */ ! 174: PUT(Control+1, 0xff); /* timeout */ ! 175: PUT(Src_id, 0x80); /* enable reselection */ ! 176: scsirun(); ! 177: /*qunlock(&scsilock);*/ ! 178: } ! 179: ! 180: int ! 181: scsiintr(void) ! 182: { ! 183: int status, s; ! 184: ! 185: if(isscsi < 0 || scsiinservice ! 186: || !((status = DEV->stat) & (DMA|INTRQ))) ! 187: return 0; ! 188: DEV->stat = 0; ! 189: scsiinservice = 1; ! 190: s = spl1(); ! 191: DPRINT("i%x ", status); ! 192: do{ ! 193: if (status & DMA) ! 194: scsidmaintr(); ! 195: if (status & INTRQ) ! 196: scsictrlintr(); ! 197: }while ((status = DEV->stat) & (DMA|INTRQ)); ! 198: splx(s); ! 199: scsiinservice = 0; ! 200: DEV->stat = Inten; ! 201: return 1; ! 202: } ! 203: ! 204: void ! 205: scsidmaintr(void) ! 206: { ! 207: uchar *p = 0; ! 208: /* ! 209: * if (scsirflag) { ! 210: * unsigned char *p; ! 211: * DPRINT("R", p=datap); ! 212: * do ! 213: * *datap++ = DEV->dma; ! 214: * while (DEV->stat & DMA); ! 215: * DPRINT("%d ", datap-p); ! 216: * } else { ! 217: * unsigned char *p; ! 218: * DPRINT("W", p=datap); ! 219: * do ! 220: * DEV->dma = *datap++; ! 221: * while (DEV->stat & DMA); ! 222: * DPRINT("%d ", datap-p); ! 223: * } ! 224: */ ! 225: if(scsirflag){ ! 226: DPRINT("R", p=datap); ! 227: datap = scsirecv(datap); ! 228: DPRINT("%d ", datap-p); ! 229: }else{ ! 230: DPRINT("X", p=datap); ! 231: datap = scsixmit(datap); ! 232: DPRINT("%d ", datap-p); ! 233: } ! 234: } ! 235: ! 236: void ! 237: scsictrlintr(void) ! 238: { ! 239: int status, phase; ! 240: long n; ! 241: ! 242: status = GET(SCSI_Status); ! 243: DPRINT("I%2.2x ", status); ! 244: switch(status){ ! 245: case 0x00: /* reset by command or power-up */ ! 246: case 0x01: /* reset by command or power-up */ ! 247: scsireset0(); ! 248: break; ! 249: case 0x21: /* Save Data Pointers message received */ ! 250: n = GET(Tc_hi); ! 251: n = (n<<8)|DEV->data; ! 252: n = (n<<8)|DEV->data; ! 253: datap = datalim - n; ! 254: PUT(Cmd_phase, 0x41); ! 255: PUT(Cmd, Select_and_Xfr); ! 256: break; ! 257: case 0x16: /* select-and-transfer completed */ ! 258: case 0x42: /* timeout during select */ ! 259: scsirun(); ! 260: break; ! 261: case 0x4b: /* unexpected status phase */ ! 262: DEV->asr = Target_LUN; ! 263: kprint("lun/status 0x%ux\n", DEV->data); ! 264: phase = DEV->data; ! 265: kprint("phase 0x%ux\n", phase); ! 266: PUT(Tc_hi, 0); ! 267: DEV->data = 0; ! 268: DEV->data = 0; ! 269: switch(phase){ ! 270: case 0x50: ! 271: case 0x60: ! 272: break; ! 273: default: ! 274: phase = 0x46; ! 275: break; ! 276: } ! 277: PUT(Cmd_phase, phase); ! 278: PUT(Cmd, Select_and_Xfr); ! 279: break; ! 280: default: ! 281: kprint("scsintr 0x%ux\n", status); ! 282: DEV->asr = Target_LUN; ! 283: kprint("lun/status 0x%ux\n", DEV->data); ! 284: kprint("phase 0x%ux\n", DEV->data); ! 285: switch (status&0xf0) { ! 286: case 0x00: ! 287: case 0x10: ! 288: case 0x20: ! 289: case 0x40: ! 290: case 0x80: ! 291: if(status & 0x08){ ! 292: kprint("count 0x%ux", GET(Tc_hi)); ! 293: kprint(" 0x%ux", DEV->data); ! 294: kprint(" 0x%ux\n", DEV->data); ! 295: } ! 296: scsirun(); ! 297: break; ! 298: default: ! 299: panic("scsi status 0x%2.2ux", status); ! 300: } ! 301: kprint("resetting..."); ! 302: PUT(Own_id, scsiownid); ! 303: PUT(Cmd, Reset); ! 304: break; ! 305: } ! 306: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.