|
|
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: #define DPRINT if(debug)print ! 11: ! 12: int scsiownid = 7; ! 13: int scsidebugs[8]; ! 14: ! 15: typedef struct SCSIdma SCSIdma; ! 16: typedef struct SCSIdev SCSIdev; ! 17: ! 18: void crankfifo(int); ! 19: void Xdelay(int); ! 20: ! 21: enum ! 22: { ! 23: DmaFifoOvflw = 16, /* Amount of extra buffer for crankfifo overflow */ ! 24: ! 25: Dma = 0x80, ! 26: Nop = 0x00, ! 27: Flush = 0x01, ! 28: Reset = 0x02, ! 29: Select = 0x41, ! 30: Transfer = 0x10, ! 31: Cmdcomplete = 0x11, ! 32: Msgaccept = 0x12 ! 33: }; ! 34: ! 35: static QLock scsilock; /* access to device */ ! 36: static Rendez scsirendez; /* sleep/wakeup for requesting process */ ! 37: static Scsi * curcmd; /* currently executing command */ ! 38: static int debug; ! 39: ! 40: /* NCR 53C90 device registers */ ! 41: struct SCSIdev ! 42: { ! 43: uchar countlo; ! 44: uchar counthi; ! 45: uchar fifo; ! 46: uchar cmd; ! 47: union { ! 48: struct { /* Registers when READ */ ! 49: uchar status; ! 50: uchar intr; ! 51: uchar step; ! 52: uchar fflags; ! 53: uchar config; ! 54: uchar Reserved1; ! 55: uchar Reserved2; ! 56: }; ! 57: struct { /* Registers when WRITTEN */ ! 58: uchar destid; ! 59: uchar timeout; ! 60: uchar syncperiod; ! 61: uchar syncoffset; ! 62: uchar XXX; ! 63: uchar clkconf; ! 64: uchar test; ! 65: }; ! 66: }; ! 67: }; ! 68: ! 69: /* ! 70: * allocate a scsi buf of any length ! 71: * must be called at ialloc time and never freed ! 72: */ ! 73: Scsibuf * ! 74: scsialloc(ulong n) ! 75: { ! 76: Scsibuf *b; ! 77: ulong l, p; ! 78: ! 79: b = xalloc(sizeof(Scsibuf)); ! 80: p = (ulong)xspanalloc(n + 2*DmaFifoOvflw, BY2PG, 0); ! 81: b->virt = (uchar *)kmappa(p); ! 82: for(l = BY2PG; l < n + 2*DmaFifoOvflw + BY2PG; l += BY2PG) ! 83: kmappa(p+l); ! 84: b->phys = (uchar*)p; ! 85: return b; ! 86: } ! 87: ! 88: void ! 89: initscsi(void) ! 90: { ! 91: } ! 92: ! 93: void ! 94: resetscsi(void) ! 95: { ! 96: SCSIdev *dev = (SCSIdev *)SCSI; ! 97: ! 98: INITCTL(0x80); ! 99: SETCTL(Int_mask); ! 100: CLRCTL(Cpu_dma); ! 101: ! 102: dev->cmd = Reset; ! 103: dev->cmd = Nop; ! 104: dev->countlo = 0; ! 105: dev->counthi = 0; ! 106: dev->timeout = 146; ! 107: dev->syncperiod = 0; ! 108: dev->syncoffset = 0; ! 109: dev->config = 0x10|(scsiownid&7); /* Parity on | Bus id */ ! 110: dev->cmd = Dma|Nop; ! 111: } ! 112: ! 113: static int ! 114: scsidone(void *arg) ! 115: { ! 116: USED(arg); ! 117: return (curcmd == 0); ! 118: } ! 119: ! 120: int ! 121: scsiexec(Scsi *p, int rflag) ! 122: { ! 123: SCSIdev *dev = (SCSIdev *)SCSI; ! 124: SCSIdma *dma = (SCSIdma *)SCSIDMA; ! 125: ulong n, up; ! 126: ! 127: debug = scsidebugs[p->target&7]; ! 128: DPRINT("scsi %d.%d cmd=0x%2.2ux ", p->target, p->lun, *(p->cmd.ptr)); ! 129: qlock(&scsilock); ! 130: qlock(&dmalock); ! 131: ! 132: p->rflag = rflag; ! 133: p->status = 0; ! 134: ! 135: CLRCTL(Cpu_dma); ! 136: ! 137: dma->chainbase = 0; ! 138: dma->chainlimit = 0; ! 139: dma->csr = Dinit | Dcreset | Dclrcint; ! 140: ! 141: dev->counthi = 0; ! 142: dev->countlo = 0; ! 143: dev->cmd = Dma|Nop; ! 144: dev->cmd = Flush; /* clear scsi fifo */ ! 145: ! 146: while(p->cmd.ptr < p->cmd.lim) ! 147: dev->fifo = *(p->cmd.ptr)++; ! 148: ! 149: dev->destid = p->target&7; ! 150: n = p->data.lim - p->data.ptr; ! 151: dev->counthi = n>>8; ! 152: dev->countlo = n; ! 153: dev->cmd = Dma|Nop; ! 154: if(n) { ! 155: up = (ulong)p->b->phys; ! 156: dma->base = up; ! 157: dma->limit = up + ((n + 0xf)&~0xf); ! 158: if(!rflag) ! 159: dma->limit += DmaFifoOvflw; /* NeXT brain damage */ ! 160: } ! 161: ! 162: curcmd = p; ! 163: dev->cmd = Select; ! 164: ! 165: while(waserror()) ! 166: ; ! 167: DPRINT("S<"); ! 168: sleep(&scsirendez, scsidone, 0); ! 169: poperror(); ! 170: qunlock(&dmalock); ! 171: qunlock(&scsilock); ! 172: debug = 0; ! 173: return p->status; ! 174: } ! 175: ! 176: void ! 177: scsiintr(int type) ! 178: { ! 179: SCSIdev *dev = (SCSIdev *)SCSI; ! 180: SCSIdma *dma = (SCSIdma *)SCSIDMA; ! 181: Scsi *p = curcmd; ! 182: int status, step, intr, n; ! 183: ulong m, csr; ! 184: ! 185: USED(type); ! 186: csr = dma->csr; ! 187: ! 188: CLRCTL(Cpu_dma); /* Access the registers */ ! 189: ! 190: /* Read cause */ ! 191: status = dev->status; ! 192: step = dev->step; ! 193: intr = dev->intr; ! 194: ! 195: intr |= ((step&7)<<8); ! 196: ! 197: DPRINT("\n\t[ status=%2.2ux step/intr=%3.3ux", status, intr); ! 198: DPRINT(" dma=%8.8ux cmd status=%4.4ux ]", csr, p ? p->status : 0xffff); ! 199: ! 200: if(p == 0 || (intr & 0x80)) { /* SCSI bus reset */ ! 201: dev->cmd = Nop; ! 202: goto Done; ! 203: } ! 204: ! 205: switch(p->status>>8){ ! 206: case 0x00: /* Select was issued */ ! 207: switch(intr){ ! 208: default: ! 209: print("devscsi: bad case\n"); ! 210: goto Done; ! 211: case 0x020: /* arbitration complete, selection timed out */ ! 212: goto Done; ! 213: case 0x218: /* selection complete, no command phase */ ! 214: p->status = 0x1000; ! 215: goto Done; ! 216: case 0x318: /* command phase ended prematurely */ ! 217: n = (p->cmd.lim - p->cmd.base) - (dev->fflags & 0x1f); ! 218: p->status = (0x30+n)<<8; ! 219: goto Done; ! 220: case 0x418: /* select sequence complete */ ! 221: p->status = 0x4100; ! 222: if((status & 0x07) == p->rflag){ ! 223: DPRINT(" Dma|Transfer "); ! 224: dma->csr = Dcreset|Dinit; ! 225: dma->csr = 0; ! 226: if(p->rflag) { ! 227: SETCTL(Dmadir); ! 228: dma->csr = Dseten|Dsetread|Dinit; ! 229: } ! 230: else { ! 231: CLRCTL(Dmadir); ! 232: dma->csr = Dseten|Dinit; ! 233: } ! 234: dev->cmd = Dma|Transfer; ! 235: SETCTL(Cpu_dma); ! 236: return; ! 237: } ! 238: else if((status & 0x07) != 3) ! 239: goto Done; ! 240: /* else fall through */ ! 241: } ! 242: ! 243: case 0x41: /* data transfer, if any, is finished */ ! 244: p->status = 0x4600; ! 245: p->data.ptr = p->data.lim - ((dev->counthi<<8)|dev->countlo); ! 246: if((status & 0x07) != 3) ! 247: goto Done; ! 248: crankfifo(dma->limit - dma->base); ! 249: dma->csr = Dcreset; ! 250: DPRINT(" Cmdcomplete"); ! 251: dev->cmd = Cmdcomplete; ! 252: return; ! 253: ! 254: case 0x46: /* Cmdcomplete was issued */ ! 255: p->status = 0x6000|dev->fifo; ! 256: m = dev->fifo; ! 257: DPRINT(" end status=0x%2.2ux msg=0x%2.2ux", p->status, m); ! 258: DPRINT(" Msgaccept"); ! 259: dev->cmd = Msgaccept; ! 260: return; ! 261: ! 262: case 0x60: /* Msgaccept was issued */ ! 263: goto Done; ! 264: } ! 265: Done: ! 266: DPRINT(" Done"); ! 267: curcmd = 0; ! 268: wakeup(&scsirendez); ! 269: } ! 270: ! 271: void ! 272: crankfifo(int n) ! 273: { ! 274: if(n <= 0) ! 275: return; ! 276: ! 277: n = n>>2; ! 278: SETCTL(Cpu_dma); ! 279: while(n--) { ! 280: CLRCTL(Fifofl); ! 281: SETCTL(Fifofl); ! 282: CLRCTL(Fifofl); ! 283: } ! 284: CLRCTL(Cpu_dma); ! 285: } ! 286: ! 287: void ! 288: Xdelay(int time) ! 289: { ! 290: time *= 100; ! 291: while(time--) ! 292: ; ! 293: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.