|
|
1.1 ! root 1: /* ! 2: Imagitek Scanner -- Andrew Hume ! 3: 1100 (?), on DR-11/W ! 4: Ninth Edition Unix (related to BSD 4.1c) ! 5: */ ! 6: ! 7: int imdebug = 0; ! 8: int imdebug1 = 0; ! 9: int imdebug2 = 0; ! 10: #define IMKEEPINT 100/**/ ! 11: ! 12: enum states { ! 13: IDLE, /*0 idle or finishing off read */ ! 14: WRITEPROBE, /*1 waiting for scanner ack */ ! 15: WRITE, /*2 started dma to scanner */ ! 16: WRITEDMA, /*3 got dma after WRITE */ ! 17: WRITEATTN, /*4 got attn after WRITE */ ! 18: READPROBE, /*5 waiting for ATTN from scanner */ ! 19: READ, /*6 ready to start dma from scanner */ ! 20: RESETTING /*7 imreset(dev) */ ! 21: }; ! 22: #include "sys/param.h" ! 23: #include "sys/conf.h" ! 24: #include "sys/user.h" ! 25: #include "sys/buf.h" ! 26: #include "sys/ubaddr.h" ! 27: #include "sys/systm.h" ! 28: ! 29: #include "sys/im.h" ! 30: ! 31: struct imdevice { ! 32: short wcr; /* Unibus word count reg */ ! 33: u_short bar; /* Unibus address register */ ! 34: u_short csr; /* Unibus status/command reg */ ! 35: u_short idr; /* Input Data Register */ ! 36: }; ! 37: #define eir csr /* Error and Information Register */ ! 38: #define odr idr /* Output Data Register */ ! 39: ! 40: /* ! 41: * Unibus status/command register bits ! 42: */ ! 43: #define GO 0x0001 ! 44: #define HSTRB 0x0002 /* host strobe fn1 */ ! 45: #define HINTR 0x0004 /* host interrupt fn2 */ ! 46: #define HRESET 0x0008 /* host reset fn3 */ ! 47: #define XMEM 0x0030 ! 48: #define xmem(a) (((a) >> 12)&XMEM) ! 49: #define IENABLE 0x0040 ! 50: #define READY 0x0080 ! 51: #define SSTRB 0x0200 /* scanner strobe statc */ ! 52: #define SINTR 0x0400 /* scanner interrupt statb */ ! 53: #define SRESET 0x0800 /* scanner interface reset stata */ ! 54: #define MAINT 0x1000 ! 55: #define ATTN 0x2000 /* attention */ ! 56: #define NEX 0x4000 ! 57: #define ERROR 0x8000 ! 58: ! 59: /* ! 60: * config glue ! 61: */ ! 62: int imopen(), imclose(), imread(), imwrite(), imioctl(); ! 63: ! 64: extern struct im im[]; ! 65: extern struct ubaddr imaddr[]; ! 66: extern int imcnt; ! 67: struct cdevsw imcdev = cdinit(imopen, imclose, imread, imwrite, imioctl); ! 68: ! 69: /* ! 70: * IOCTL ! 71: */ ! 72: #define IMRESET (('i'<<8)|1) ! 73: #define IMWAIT (('i'<<8)|2) ! 74: ! 75: #define DMAPRI (PZERO-1) ! 76: #define WAITPRI (PZERO+1) ! 77: #define FUNCMASK (HSTRB|HINTR|HRESET) ! 78: ! 79: /* ! 80: this is a finite state automata driven by the interrupt routine ! 81: */ ! 82: ! 83: ! 84: #ifdef IMKEEPINT ! 85: typedef struct iminterrupt ! 86: { ! 87: short csr, ostate, nstate, attn; ! 88: long time; ! 89: } iminterrupt; ! 90: iminterrupt imi[IMKEEPINT], *nimi; ! 91: #endif ! 92: #define IMN 1000 ! 93: static short wcnt[IMN], rcnt[IMN], rscnt[IMN], wi, ri; ! 94: ! 95: imopen(d, f) ! 96: { ! 97: register struct im *imp; ! 98: register int dev; ! 99: ! 100: if((dev = minor(d)) >= imcnt) { ! 101: u.u_error = ENODEV; ! 102: return; ! 103: } ! 104: if((imp = &im[dev])->open) { ! 105: u.u_error = EBUSY; ! 106: return; ! 107: } ! 108: if((imp->addr = (struct imdevice *)ubaddr(&imaddr[dev])) == 0 ! 109: || ubbadaddr(imaddr[dev].ubno, (caddr_t)imp->addr, sizeof(u_short))) { ! 110: printf("im%d absent\n", dev); ! 111: u.u_error = ENODEV; ! 112: return; ! 113: } ! 114: imp->addr->csr = 0; ! 115: imp->open = 1; ! 116: imp->state = IDLE; ! 117: #ifdef IMKEEPINT ! 118: nimi = imi; ! 119: #endif ! 120: wi = ri = 0; ! 121: } ! 122: ! 123: imclose(dev) ! 124: { ! 125: register struct im *imp = &im[minor(dev)]; ! 126: ! 127: if(imp->state != IDLE) ! 128: imreset(imp); ! 129: imp->open = 0; ! 130: #ifdef IMKEEPINT ! 131: if(imdebug1){ ! 132: iminterrupt *i; ! 133: ! 134: for(i = imi; i < nimi; i++) ! 135: printf("%d: csr=0x%x attn=%d ostate=%d nstate=%d\n", ! 136: i->time, i->csr&0xFFFF, i->attn, i->ostate, i->nstate); ! 137: } ! 138: #endif ! 139: if(imdebug2){ ! 140: register i; ! 141: ! 142: printf("read: "); ! 143: for(i = 0; i < ri; i++) ! 144: printf("%d:%d[%d] ", i, rcnt[i], rscnt[i]); ! 145: printf("\nwrite: "); ! 146: for(i = 0; i < wi; i++) ! 147: if(wcnt[i]) printf("%d:%d ", i, wcnt[i]); ! 148: printf("\n"); ! 149: } ! 150: } ! 151: ! 152: u_int ! 153: imminphys(bp) ! 154: register struct buf *bp; ! 155: { ! 156: ! 157: if(bp->b_bcount > 65536) /* may be able to do twice as much */ ! 158: bp->b_bcount = 65536; ! 159: } ! 160: ! 161: imstrategy(bp) ! 162: register struct buf *bp; ! 163: { ! 164: register struct im *imp = &im[minor(bp->b_dev)]; ! 165: register int s; ! 166: uaddr_t uaddr; ! 167: u_short csr; ! 168: ! 169: if(bp->b_bcount<=0 || (bp->b_bcount&1) || ((int)bp->b_un.b_addr&1)){ ! 170: bp->b_flags |= B_ERROR; ! 171: iodone(bp); ! 172: return; ! 173: } ! 174: imp->ubm = ubmbuf(imaddr[minor(bp->b_dev)].ubno, bp, UBDP|USLP); ! 175: uaddr = ubadbuf(imaddr[minor(bp->b_dev)].ubno, bp, imp->ubm); ! 176: s = spl5(); ! 177: csr = IENABLE| xmem(uaddr) | ((bp->b_flags&B_READ) ? 0: HINTR); ! 178: imp->addr->wcr = -(bp->b_bcount>>1); /* it's a word count */; ! 179: imp->addr->bar = uaddr; ! 180: imp->addr->csr = csr; /* No GO bit; let function codes settle */ ! 181: imp->addr->csr = csr|GO; ! 182: if(tsleep((caddr_t)imp, DMAPRI+1, 15) != TS_OK){ ! 183: printf("im dma timeout: csr=0x%x wcr=%d\n", ! 184: imp->addr->csr, imp->addr->wcr); ! 185: /* stop the dma */ ! 186: imslam(imp->addr); ! 187: imp->addr->wcr = 0xFFFF; /* gently; -1 first... */ ! 188: imp->addr->wcr = 0x0000; /* then zero */ ! 189: /* reset device */ ! 190: imreset(imp); ! 191: bp->b_flags |= B_ERROR; ! 192: } ! 193: splx(s); ! 194: ubmfree(imaddr[minor(bp->b_dev)].ubno, imp->ubm); ! 195: bp->b_resid = -(imp->addr->wcr<<1); ! 196: iodone(bp); ! 197: } ! 198: ! 199: imread(dev) ! 200: { ! 201: register struct im *imp = &im[minor(dev)]; ! 202: int start; ! 203: ! 204: start = time*HZ+lbolt; ! 205: if(imdebug) ! 206: printf("read: "); ! 207: while((imp->state == WRITEDMA) || (imp->state == WRITEATTN) || ! 208: (imp->state == READPROBE)){ ! 209: if(tsleep((caddr_t)imp, DMAPRI+1, 15) != TS_OK){ ! 210: imreset(imp); ! 211: return; ! 212: } ! 213: } ! 214: rscnt[ri] = time*HZ+lbolt-start; ! 215: if(imp->state != READ){ ! 216: u.u_error = EGREG; ! 217: return; ! 218: } ! 219: u.u_count += 2; ! 220: imp->addr->csr = IENABLE; /* HSTRB ??*/ ! 221: physio(imstrategy, &imp->buf, dev, B_READ, imminphys); ! 222: u.u_count -= 2; ! 223: imp->addr->csr = IENABLE; ! 224: rcnt[ri++] = time*HZ+lbolt-start; ! 225: } ! 226: ! 227: imwrite(dev) ! 228: { ! 229: register struct im *imp = &im[minor(dev)]; ! 230: register int start, s, x; ! 231: ! 232: start = time*HZ+lbolt; ! 233: if(imp->state != IDLE){ ! 234: u.u_error = EGREG; ! 235: return; ! 236: } ! 237: if(imp->addr->csr&(SINTR|SRESET)){ /* is it offline ? */ ! 238: printf("im: offline csr=0x%x\n", imp->addr->csr); ! 239: u.u_error = ENXIO; ! 240: return; ! 241: } ! 242: s = spl5(); ! 243: imp->state = WRITEPROBE; ! 244: imp->addr->csr = IENABLE | HINTR | HSTRB; /* poke scanner */ ! 245: if(((x = tsleep((caddr_t)imp, DMAPRI+1, 15)) != TS_OK) || ! 246: (imp->state != WRITE)){ ! 247: printf("im%d: wtimo - type %d, state %d\n", x, imp->state); ! 248: imreset(imp); ! 249: return; ! 250: } ! 251: imp->addr->csr = HINTR; ! 252: splx(s); ! 253: physio(imstrategy, &imp->buf, dev, B_WRITE, imminphys); ! 254: /* ! 255: the write is done although we may not have both interrupts ! 256: */ ! 257: wcnt[wi++] = time*HZ+lbolt-start; ! 258: } ! 259: ! 260: imslam(addr) ! 261: register struct imdevice *addr; ! 262: { ! 263: register i; ! 264: ! 265: addr->csr = MAINT; ! 266: for(i = 0; i < 10; i++) ! 267: ; ! 268: addr->csr = 0; ! 269: for(i = 0; i < 10; i++) ! 270: ; ! 271: } ! 272: ! 273: /*ARGSUSED*/ ! 274: imioctl(dev, cmd, addr, flag) ! 275: caddr_t addr; ! 276: { ! 277: register struct im *imp = &im[minor(dev)]; ! 278: ! 279: switch(cmd) { ! 280: ! 281: case IMRESET: ! 282: spl5(); ! 283: imreset(imp); ! 284: if((tsleep((caddr_t)imp, WAITPRI, 15) != TS_OK) || (imp->state != IDLE)){ ! 285: spl0(); ! 286: u.u_error = EIO; ! 287: imp->state = IDLE; ! 288: return; ! 289: } ! 290: u.u_error = 0; ! 291: spl0(); ! 292: break; ! 293: ! 294: case IMWAIT: ! 295: if(imp->state != READPROBE){ ! 296: if(imdebug) ! 297: printf("im: wait state=%d\n", imp->state); ! 298: return; ! 299: } ! 300: if((tsleep((caddr_t)imp, WAITPRI, 150) != TS_OK) || (imp->state != READ)){ ! 301: u.u_error = EIO; ! 302: return; ! 303: } ! 304: u.u_error = 0; ! 305: break; ! 306: ! 307: default: ! 308: u.u_error = ENOTTY; ! 309: break; ! 310: } ! 311: } ! 312: ! 313: im0int(dev) ! 314: { ! 315: register struct im *imp = &im[dev]; ! 316: u_short csr; ! 317: int attn = 0; ! 318: int ostate = imp->state; ! 319: int dma; ! 320: ! 321: if((csr = imp->addr->csr) & ATTN) ! 322: attn = 1; ! 323: else if(csr&ERROR) { ! 324: imp->addr->eir |= ERROR; ! 325: printf("im: read goo CSR %x EIR %x BAR %x WCR %x\n", ! 326: csr, imp->addr->eir, imp->addr->bar, imp->addr->wcr); ! 327: imp->addr->csr = csr&~FUNCMASK; ! 328: imreset(imp); ! 329: } ! 330: #ifdef IMKEEPINT ! 331: nimi->time = time*HZ+lbolt; ! 332: nimi->csr = csr; ! 333: nimi->attn = attn; ! 334: nimi->ostate = ostate; ! 335: nimi->nstate = -1; ! 336: if(++nimi >= &imi[IMKEEPINT]) ! 337: nimi--; ! 338: #endif ! 339: if(imdebug) ! 340: printf("imintr: csr=0x%x ostate=%d attn=%d ", csr, ostate, attn); ! 341: if(!(csr&READY)) ! 342: return; ! 343: switch(imp->state) { ! 344: ! 345: case IDLE: ! 346: break; ! 347: ! 348: case WRITEPROBE: ! 349: if(attn) ! 350: imp->state = WRITE; ! 351: else ! 352: imreset(imp); ! 353: break; ! 354: ! 355: case WRITE: ! 356: dma = (csr&READY) && (imp->addr->wcr == 0); ! 357: if(attn){ ! 358: if(dma){ ! 359: imp->addr->csr = IENABLE; ! 360: imp->state = READPROBE; ! 361: } else ! 362: imp->state = WRITEATTN; ! 363: } else { ! 364: if(!dma) ! 365: printf("im: phooey! wcr=%d\n", imp->addr->wcr); ! 366: /* bad value: imp->state = WRITEDMA;*/ ! 367: imp->addr->csr = IENABLE; ! 368: imp->state = READPROBE; ! 369: } ! 370: break; ! 371: ! 372: case WRITEDMA: ! 373: if(!attn) ! 374: printf("im: scrunt\n"); ! 375: imp->addr->csr = IENABLE; ! 376: imp->state = READPROBE; ! 377: break; ! 378: ! 379: case WRITEATTN: ! 380: if(attn) ! 381: printf("im: poot\n"); ! 382: imp->addr->csr = IENABLE; ! 383: imp->state = READPROBE; ! 384: break; ! 385: ! 386: case READPROBE: ! 387: if(attn) ! 388: imp->state = READ; ! 389: else ! 390: imreset(imp); ! 391: break; ! 392: ! 393: case READ: ! 394: /* ! 395: because we may not get both an attn and a dma done ! 396: drop into idle. if we get neither, something will screw ! 397: up; that's ok because the user is in trouble anyway. ! 398: */ ! 399: dma = (csr&READY) && (imp->addr->wcr == 0); ! 400: if(imdebug) ! 401: printf("DMA=%d: ", dma); ! 402: if((csr & (SRESET|SINTR|SSTRB)) != SSTRB) ! 403: imreset(imp); ! 404: else ! 405: imp->state = IDLE; ! 406: break; ! 407: ! 408: case RESETTING: ! 409: if(!attn || (csr & SSTRB)){ ! 410: printf("im: bad reset\n"); ! 411: } ! 412: imp->addr->csr &= ~FUNCMASK; ! 413: imp->state = IDLE; ! 414: break; ! 415: ! 416: default: ! 417: printf("im0int: unknown state %d\n", imp->state); ! 418: imreset(imp); ! 419: } ! 420: if(imdebug) ! 421: printf("new state=%d\n", imp->state); ! 422: #ifdef IMKEEPINT ! 423: nimi[-1].nstate = imp->state; ! 424: #endif ! 425: wakeup((caddr_t)imp); ! 426: } ! 427: ! 428: imreset(imp) ! 429: register struct im *imp; ! 430: { ! 431: register int s; ! 432: u_short csr; ! 433: ! 434: s = spl5(); ! 435: if(imdebug) ! 436: printf("imreset: state=%d\n", imp->state); ! 437: if(imp->addr->csr&SRESET) ! 438: return; ! 439: imp->state = RESETTING; ! 440: csr = IENABLE | HINTR | HRESET | HSTRB; ! 441: imp->addr->csr = csr; ! 442: splx(s); ! 443: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.