Annotation of researchv10no/sys/io/im.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.