Annotation of researchv10no/sys/io/im.c, revision 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.