Annotation of lucent/sys/src/9/pc/devincon.c, revision 1.1

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: 
        !             9: #include       "io.h"
        !            10: 
        !            11: /* Centronix parallel (printer) port */
        !            12: 
        !            13: typedef struct Lptinfo Lptinfo;
        !            14: 
        !            15: struct Lptinfo
        !            16: {
        !            17:        int     base;           /* port number */
        !            18:        int     ivec;           /* interrupt number */
        !            19: };
        !            20: 
        !            21: static Lptinfo lptinfo[] = {
        !            22:        0x3bc,  Parallelvec,    /* lpt1 (safari) */
        !            23:        0x378,  Parallelvec,    /* lpt1 (`official') */
        !            24:        0x278,  Int0vec+5,      /* lpt2 (`official') */
        !            25: };
        !            26: #define NDEV   (sizeof lptinfo/sizeof lptinfo[0])
        !            27: 
        !            28: extern int     incondev;       /* from config */
        !            29: 
        !            30: /* offsets, and bits in the registers */
        !            31: enum
        !            32: {
        !            33:        /* data latch register */
        !            34:        Qdlr=           0x0,
        !            35:        /* printer status register */
        !            36:        Qpsr=           0x1,
        !            37:        Fbusy=          0x80,
        !            38:        Fintbar=        0x40,
        !            39:        /* printer control register */
        !            40:        Qpcr=           0x2,
        !            41:        Fie=            0x10,
        !            42:        Fsi=            0x08,
        !            43:        Finitbar=       0x04,
        !            44:        Faf=            0x02,
        !            45:        Fstrobe=        0x01,
        !            46: 
        !            47:        /* other `registers' */
        !            48:        Qstats=         0x03,
        !            49:        Qdebug=         0x04
        !            50: };
        !            51: 
        !            52: /*
        !            53:  *     af  si  dlr<7:0>
        !            54:  *      0   x  xxxxxxxx        wr ctl/data char (si is dcto)
        !            55:  *      1   0  xxxxxxxx        wr cmd
        !            56:  *      1   1  xxxxxx00        rd ctl/data char
        !            57:  *      1   1  xxxxxx01        rd status
        !            58:  *      1   1  xxxxxx11        nop (multiplexer to normal state)
        !            59:  *
        !            60:  *      psr<7:3> multiplexed as follows:
        !            61:  *
        !            62:  *                     bc7  bc6  bc5  bc4  bc3
        !            63:  *      rd, st- low    bsy   d8   d7   d6   d5
        !            64:  *      rd, st- high    d4   d3   d2   d1   d0
        !            65:  *      other          bsy  int-
        !            66:  */
        !            67: 
        !            68: typedef struct Incon   Incon;
        !            69: 
        !            70: #define NOW (MACHP(0)->ticks*MS2HZ)
        !            71: 
        !            72: #define DPRINT if(incondebug)kprint
        !            73: 
        !            74: static void    inconintr(Ureg *ur, void *a);
        !            75: 
        !            76: enum {
        !            77:        Minstation=     2,      /* lowest station # to poll */
        !            78:        Maxstation=     15,     /* highest station # to poll */
        !            79:        Nincon=         1,      /* number of incons */
        !            80:        Nin=            32,     /* Blocks in the input ring */
        !            81:        Bsize=          128,    /* size of an input ring block */
        !            82:        Mfifo=          0xff    /* a mask, must be 2^n-1, must be > Nin */
        !            83: };
        !            84: 
        !            85: struct Incon {
        !            86:        QLock;
        !            87: 
        !            88:        QLock   xmit;           /* transmit lock */
        !            89:        QLock   reslock;        /* reset lock */
        !            90:        int     dev;            /* base address of port */
        !            91:        int     station;        /* station number */
        !            92:        int     state;          /* chip state */
        !            93:        Rendez  r;              /* output process */
        !            94:        Rendez  kr;             /* input kernel process */
        !            95:        ushort  chan;           /* current input channel */
        !            96:        Queue   *rq;            /* read queue */
        !            97:        int     kstarted;       /* true if kernel process started */
        !            98: 
        !            99:        /*  input blocks */
        !           100: 
        !           101:        Block   *inb[Nin];
        !           102:        ushort  wi;             
        !           103:        ushort  ri;
        !           104: 
        !           105:        /* statistics */
        !           106: 
        !           107:        ulong   overflow;       /* overflow errors */
        !           108:        ulong   pack0;          /* channel 0 */
        !           109:        ulong   crc;            /* crc errors */
        !           110:        ulong   in;             /* bytes in */
        !           111:        ulong   out;            /* bytes out */
        !           112:        ulong   wait;           /* wait time in milliseconds */
        !           113: };
        !           114: 
        !           115: Incon incon[Nincon];
        !           116: 
        !           117: /*
        !           118:  *  chip state
        !           119:  */
        !           120: enum {
        !           121:        Selecting,
        !           122:        Selected,
        !           123:        Notliving,
        !           124: };
        !           125: 
        !           126: /*
        !           127:  *  internal chip registers
        !           128:  */
        !           129: #define        sel_polln       0
        !           130: #define        sel_station     1
        !           131: #define        sel_poll0       2
        !           132: #define sel_rcv_cnt    3
        !           133: #define sel_rcv_tim    4
        !           134: #define sel_tx_cnt     5
        !           135: 
        !           136: /*
        !           137:  *  CSR bits
        !           138:  */
        !           139: #define INCON_RUN      0x80
        !           140: #define INCON_STOP     0x00
        !           141: #define ENABLE_IRQ     0x40
        !           142: #define ENABLE_TX_IRQ  0x20
        !           143: #define INCON_ALIVE    0x80
        !           144: #define TX_FULL                0x10
        !           145: #define TX_EMPTY       0x08
        !           146: #define RCV_EMPTY      0x04
        !           147: #define OVERFLOW       0x02
        !           148: #define CRC_ERROR      0x01
        !           149: 
        !           150: /*
        !           151:  *  polling constants
        !           152:  */
        !           153: #define HT_GNOT        0x30
        !           154: #define HT_UNIX        0x31
        !           155: #define ST_UNIX 0x04
        !           156: #define NCHAN 64
        !           157: 
        !           158: static void inconkproc(void*);
        !           159: 
        !           160: /*
        !           161:  *  incon stream module definition
        !           162:  */
        !           163: static void inconoput(Queue*, Block*);
        !           164: static void inconstopen(Queue*, Stream*);
        !           165: static void inconstclose(Queue*);
        !           166: Qinfo inconinfo =
        !           167: {
        !           168:        nullput,
        !           169:        inconoput,
        !           170:        inconstopen,
        !           171:        inconstclose,
        !           172:        "incon"
        !           173: };
        !           174: 
        !           175: int incondebug = 0;
        !           176: 
        !           177: Dirtab incondir[]={
        !           178:        "dlr",          {Qdlr},         1,              0666,
        !           179:        "psr",          {Qpsr},         5,              0444,
        !           180:        "pcr",          {Qpcr},         0,              0666,
        !           181:        "stats",        {Qstats},       0,              0444,
        !           182:        "debug",        {Qdebug},       0,              0666,
        !           183: };
        !           184: #define NINCON (sizeof incondir/sizeof incondir[0])
        !           185: 
        !           186: static void
        !           187: nop(void)
        !           188: {
        !           189: }
        !           190: 
        !           191: static int
        !           192: slowinb(int x)
        !           193: {
        !           194:        nop();
        !           195:        nop();
        !           196:        return inb(x);
        !           197: }
        !           198: 
        !           199: static void
        !           200: reset(int dev)                         /* hardware reset */
        !           201: {
        !           202:        outb(dev+Qpcr, Finitbar);
        !           203:        outb(dev+Qpcr, 0);
        !           204:        outb(dev+Qpcr, Finitbar);
        !           205: }
        !           206: 
        !           207: static void
        !           208: wrctl(int dev, int data)               /* write control character */
        !           209: {
        !           210:        outb(dev+Qpcr, Finitbar);       /* no interrupts, please */
        !           211:        outb(dev+Qdlr, data);
        !           212:        outb(dev+Qpcr, Finitbar|Fstrobe);
        !           213:        outb(dev+Qpcr, Finitbar|Fie);
        !           214: }
        !           215: 
        !           216: static void
        !           217: wrdata(int dev, int data)              /* write data character */
        !           218: {
        !           219:        outb(dev+Qpcr, Finitbar|Fsi);
        !           220:        outb(dev+Qdlr, data);
        !           221:        outb(dev+Qpcr, Finitbar|Fsi|Fstrobe);
        !           222:        outb(dev+Qpcr, Finitbar|Fsi|Fie);
        !           223: }
        !           224: 
        !           225: static void
        !           226: wrcmd(int dev, int data)               /* write command */
        !           227: {
        !           228:        outb(dev+Qpcr, Finitbar|Faf);
        !           229:        outb(dev+Qdlr, data);
        !           230:        outb(dev+Qpcr, Finitbar|Faf|Fstrobe);
        !           231:        outb(dev+Qpcr, Finitbar|Faf|Fie);
        !           232: }
        !           233: 
        !           234: static int
        !           235: rdstatus(Incon *ip)                    /* read status */
        !           236: {
        !           237:        int dev, data;
        !           238: 
        !           239:        dev = ip->dev;
        !           240: 
        !           241:        outb(dev+Qpcr, Finitbar|Faf|Fsi);
        !           242:        outb(dev+Qdlr, 0x01);
        !           243:        outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
        !           244:        data = (inb(dev+Qpsr)&0xf8)<<2;
        !           245:        outb(dev+Qpcr, Finitbar|Faf|Fsi);
        !           246:        data |= inb(dev+Qpsr)>>3;
        !           247:        if(data&(OVERFLOW|CRC_ERROR)){
        !           248:                if(data&OVERFLOW)
        !           249:                        ip->overflow++;
        !           250:                if(data&CRC_ERROR)
        !           251:                        ip->crc++;
        !           252:        }
        !           253:        outb(dev+Qdlr, 0x03);
        !           254:        outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
        !           255:        outb(dev+Qpcr, Finitbar|Faf|Fsi|Fie);
        !           256: 
        !           257:        return data;
        !           258: }
        !           259: 
        !           260: static void
        !           261: iwrcmd(int dev, int data)              /* write command at interrupt level */
        !           262: {
        !           263:        outb(dev+Qdlr, data);
        !           264:        outb(dev+Qpcr, Finitbar|Faf|Fstrobe);
        !           265:        outb(dev+Qpcr, Finitbar|Faf);
        !           266: }
        !           267: 
        !           268: static int
        !           269: irdstatus(Incon *ip)                   /* read status at interrupt level */
        !           270: {
        !           271:        int dev, data;
        !           272: 
        !           273:        dev = ip->dev;
        !           274: 
        !           275:        outb(dev+Qdlr, 0x01);
        !           276:        outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
        !           277:        data = (slowinb(dev+Qpsr)&0xf8)<<2;
        !           278:        outb(dev+Qpcr, Finitbar|Faf|Fsi);
        !           279:        data |= slowinb(dev+Qpsr)>>3;
        !           280:        if(data&(OVERFLOW|CRC_ERROR)){
        !           281:                if(data&OVERFLOW)
        !           282:                        ip->overflow++;
        !           283:                if(data&CRC_ERROR)
        !           284:                        ip->crc++;
        !           285:        }
        !           286: 
        !           287:        return data;
        !           288: }
        !           289: 
        !           290: static int
        !           291: irddata(int dev)                       /* read data at interrupt level */
        !           292: {
        !           293:        int data;
        !           294: 
        !           295:        outb(dev+Qdlr, 0x00);
        !           296:        outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
        !           297:        data = (slowinb(dev+Qpsr)&0xf8)<<2;
        !           298:        outb(dev+Qpcr, Finitbar|Faf|Fsi);
        !           299:        data |= slowinb(dev+Qpsr)>>3;
        !           300: 
        !           301:        return data;
        !           302: }
        !           303: 
        !           304: static int
        !           305: irdnext(int dev)                       /* read next data at interrupt level */
        !           306: {
        !           307:        int data;
        !           308: 
        !           309:        outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
        !           310:        data = (inb(dev+Qpsr)&0xf8)<<2;
        !           311:        outb(dev+Qpcr, Finitbar|Faf|Fsi);
        !           312:        data |= inb(dev+Qpsr)>>3;
        !           313: 
        !           314:        return data;
        !           315: }
        !           316: 
        !           317: static void
        !           318: irdnop(int dev, int pcr)               /* read nop (mux reset) */
        !           319: {
        !           320:        outb(dev+Qdlr, 0x03);
        !           321:        outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
        !           322:        outb(dev+Qpcr, pcr);
        !           323: }
        !           324: 
        !           325: int            Irdnext(int);
        !           326: #define        irdnext Irdnext
        !           327: /**/
        !           328: 
        !           329: /*
        !           330:  *  set the incon parameters
        !           331:  */
        !           332: void
        !           333: inconset(Incon *ip, int cnt, int del)
        !           334: {
        !           335:        int dev;
        !           336: 
        !           337:        if (cnt<1 || cnt>14 || del<1 || del>15)
        !           338:                error(Ebadarg);
        !           339: 
        !           340:        dev = ip->dev;
        !           341:        wrcmd(dev, sel_rcv_cnt | INCON_RUN);
        !           342:        wrdata(dev, cnt);
        !           343:        wrcmd(dev, sel_rcv_tim | INCON_RUN);
        !           344:        wrdata(dev, del);
        !           345:        wrcmd(dev, INCON_RUN | ENABLE_IRQ);
        !           346: }
        !           347: 
        !           348: /*
        !           349:  *  parse a set request
        !           350:  */
        !           351: void
        !           352: inconsetctl(Incon *ip, Block *bp)
        !           353: {
        !           354:        char *field[3];
        !           355:        int n;
        !           356:        int del;
        !           357:        int cnt;
        !           358: 
        !           359:        del = 15;
        !           360:        n = getfields((char *)bp->rptr, field, 3, " ");
        !           361:        switch(n){
        !           362:        default:
        !           363:                freeb(bp);
        !           364:                error(Ebadarg);
        !           365:        case 2:
        !           366:                del = strtol(field[1], 0, 0);
        !           367:                if(del<0 || del>15){
        !           368:                        freeb(bp);
        !           369:                        error(Ebadarg);
        !           370:                }
        !           371:                /* fall through */
        !           372:        case 1:
        !           373:                cnt = strtol(field[0], 0, 0);
        !           374:                if(cnt<0 || cnt>15){
        !           375:                        freeb(bp);
        !           376:                        error(Ebadarg);
        !           377:                }
        !           378:        }
        !           379:        inconset(ip, cnt, del);
        !           380:        freeb(bp);
        !           381: }
        !           382: 
        !           383: /*
        !           384:  *  poll for a station number
        !           385:  */
        !           386: void 
        !           387: inconpoll(Incon *ip, int station)
        !           388: {
        !           389:        ulong timer;
        !           390:        int dev;
        !           391:        char *p;
        !           392: 
        !           393:        dev = ip->dev;
        !           394: 
        !           395:        /*
        !           396:         *  get us to a known state
        !           397:         */
        !           398:        ip->state = Notliving;
        !           399:        wrcmd(dev, INCON_STOP);
        !           400: 
        !           401:        /*
        !           402:         * try a station number
        !           403:         */
        !           404:        wrcmd(dev, sel_station);
        !           405:        wrdata(dev, station);
        !           406:        wrcmd(dev, sel_poll0);
        !           407:        wrdata(dev, HT_GNOT);
        !           408:        wrcmd(dev, sel_rcv_cnt);
        !           409:        wrdata(dev, 3);
        !           410:        wrcmd(dev, sel_rcv_tim);
        !           411:        wrdata(dev, 15);
        !           412:        wrcmd(dev, sel_tx_cnt);
        !           413:        wrdata(dev, 1);
        !           414:        wrcmd(dev, sel_polln);
        !           415:        wrdata(dev, 0x00);
        !           416:        wrdata(dev, ST_UNIX);
        !           417:        wrdata(dev, NCHAN);
        !           418:        for(p = "gnot"; *p; p++)
        !           419:                wrdata(dev, *p);
        !           420:        wrctl(dev, 0);
        !           421: 
        !           422:        /*
        !           423:         *  poll and wait for ready (or 1/4 second)
        !           424:         */
        !           425:        ip->state = Selecting;
        !           426:        wrcmd(dev, INCON_RUN | ENABLE_IRQ);
        !           427:        timer = NOW + 250;
        !           428:        while (NOW < timer) {
        !           429:                nop();
        !           430:                if(rdstatus(ip) & INCON_ALIVE){
        !           431:                        ip->station = station;
        !           432:                        ip->state = Selected;
        !           433:                        break;
        !           434:                }
        !           435:        }
        !           436: }
        !           437: 
        !           438: /*
        !           439:  *  reset the chip and find a new station number
        !           440:  */
        !           441: void
        !           442: inconrestart(Incon *ip)
        !           443: {
        !           444:        int i;
        !           445: 
        !           446:        if(!canqlock(&ip->reslock))
        !           447:                return;
        !           448: 
        !           449:        /*
        !           450:         *  poll for incon station numbers
        !           451:         */
        !           452:        DPRINT("inconrestart\n");
        !           453:        for(i = Minstation; i <= Maxstation; i++){
        !           454:                inconpoll(ip, i);
        !           455:                if(ip->state == Selected)
        !           456:                        break;
        !           457:        }
        !           458:        switch(ip->state) {
        !           459:        case Selecting:
        !           460:                DPRINT("incon[%d] not polled\n", ip-incon);
        !           461:                print("incon[%d] not polled\n", ip-incon);
        !           462:                break;
        !           463:        case Selected:
        !           464:                DPRINT("incon[%d] station %d\n", ip-incon, ip->station);
        !           465:                print("incon[%d] station %d\n", ip-incon, ip->station);
        !           466:                inconset(ip, 3, 15);
        !           467:                break;
        !           468:        default:
        !           469:                DPRINT("incon[%d] bollixed\n", ip-incon);
        !           470:                print("incon[%d] bollixed\n", ip-incon);
        !           471:                break;
        !           472:        }
        !           473:        qunlock(&ip->reslock);
        !           474: }
        !           475: 
        !           476: /*
        !           477:  *  reset all incon chips.
        !           478:  */
        !           479: 
        !           480: void
        !           481: inconreset(void)
        !           482: {
        !           483:        int i;
        !           484:        char *p;
        !           485: 
        !           486:        /*
        !           487:         *  get incondev from p9rc
        !           488:         */
        !           489:        p = getconf("incondev");
        !           490:        if(p)
        !           491:                incondev = atoi(p);
        !           492: 
        !           493:        /*
        !           494:         * state is Selected if we used incon as the boot device
        !           495:         * i.e. we've already got a station number.
        !           496:         * state is Selecting if this is a first-time open.
        !           497:         */
        !           498: /*     inconset(&incon[0], 3, 15); /**/
        !           499:        for(i=0; i<Nincon; i++){
        !           500:                incon[i].dev = lptinfo[incondev].base;
        !           501:                incon[i].state = Notliving;
        !           502:                reset(incon[i].dev);
        !           503:                incon[i].ri = incon[i].wi = 0;
        !           504:        }
        !           505:        incon[0].state = Selecting;
        !           506:        wrcmd(incon[0].dev, INCON_STOP);
        !           507: }
        !           508: 
        !           509: void
        !           510: inconinit(void)
        !           511: {
        !           512:        wrcmd(incon[0].dev, INCON_STOP);
        !           513: }
        !           514: 
        !           515: /*
        !           516:  *  enable the device for interrupts, spec is the device number
        !           517:  */
        !           518: Chan*
        !           519: inconattach(char *spec)
        !           520: {
        !           521:        Incon *ip;
        !           522:        int i;
        !           523:        Chan *c;
        !           524: 
        !           525:        setvec(lptinfo[incondev].ivec, inconintr, 0);
        !           526:        i = strtoul(spec, 0, 0);
        !           527:        if(i >= Nincon)
        !           528:                error(Ebadarg);
        !           529:        ip = &incon[i];
        !           530:        rdstatus(ip);
        !           531:        if(ip->state != Selected)
        !           532:                inconrestart(ip);
        !           533: 
        !           534:        c = devattach('i', spec);
        !           535:        c->dev = i;
        !           536:        c->qid.path = CHDIR;
        !           537:        c->qid.vers = 0;
        !           538:        return c;
        !           539: }
        !           540: 
        !           541: Chan*
        !           542: inconclone(Chan *c, Chan *nc)
        !           543: {
        !           544:        return devclone(c, nc);
        !           545: }
        !           546: 
        !           547: int     
        !           548: inconwalk(Chan *c, char *name)
        !           549: {
        !           550:        return devwalk(c, name, incondir, NINCON, streamgen);
        !           551: }
        !           552: 
        !           553: void    
        !           554: inconstat(Chan *c, char *dp)
        !           555: {
        !           556:        devstat(c, dp, incondir, NINCON, streamgen);
        !           557: }
        !           558: 
        !           559: Chan*
        !           560: inconopen(Chan *c, int omode)
        !           561: {
        !           562:        if(c->qid.path != CHDIR && c->qid.path >= Slowqid)
        !           563:                streamopen(c, &inconinfo);
        !           564:        c->mode = openmode(omode);
        !           565:        c->flag |= COPEN;
        !           566:        c->offset = 0;
        !           567:        return c;
        !           568: }
        !           569: 
        !           570: void    
        !           571: inconcreate(Chan *c, char *name, int omode, ulong perm)
        !           572: {
        !           573:        USED(c, name, omode, perm);
        !           574:        error(Eperm);
        !           575: }
        !           576: 
        !           577: void    
        !           578: inconclose(Chan *c)
        !           579: {
        !           580:        if(c->qid.path != CHDIR && c->qid.path >= Slowqid)
        !           581:                streamclose(c);
        !           582: }
        !           583: 
        !           584: long    
        !           585: inconread(Chan *c, void *buf, long n, ulong offset)
        !           586: {
        !           587:        char b[256];
        !           588:        Incon *ip;
        !           589: 
        !           590:        if(c->qid.path == CHDIR)
        !           591:                return devdirread(c, buf, n, incondir, NINCON, streamgen);
        !           592:        ip = &incon[c->dev];
        !           593:        switch(c->qid.path){
        !           594:        default:
        !           595:                return streamread(c, buf, n);
        !           596:        case Qdlr:
        !           597:        case Qpsr:
        !           598:        case Qpcr:
        !           599:                sprint(b, "0x%2.2ux\n", inb(ip->dev + c->qid.path));
        !           600:                break;
        !           601:        case Qstats:
        !           602:                sprint(b, "state: %d\nstation: %d\nin: %d\nout: %d\noverflow: %d\ncrc: %d\nwait: %d\n",
        !           603:                        ip->state, ip->station, ip->in, ip->out, ip->overflow, ip->crc, ip->wait);
        !           604:                break;
        !           605:        case Qdebug:
        !           606:                sprint(b, "%d\n", incondebug);
        !           607:                break;
        !           608:        }
        !           609:        return readstr(offset, buf, n, b);
        !           610: }
        !           611: 
        !           612: long    
        !           613: inconwrite(Chan *c, void *buf, long n, ulong offset)
        !           614: {
        !           615:        char b[8];
        !           616:        Incon *ip;
        !           617:        int data;
        !           618: 
        !           619:        USED(offset);
        !           620:        switch(c->qid.path){
        !           621:        default:
        !           622:                return streamwrite(c, buf, n, 0);
        !           623:        case Qdlr:
        !           624:        case Qpcr:
        !           625:        case Qdebug:
        !           626:                break;
        !           627:        }
        !           628:        if(n > sizeof b-1)
        !           629:                n = sizeof b-1;
        !           630:        memmove(b, buf, n);
        !           631:        b[n] = 0;
        !           632:        data = strtoul(b, 0, 0);
        !           633:        switch(c->qid.path){
        !           634:        default:
        !           635:                ip = &incon[c->dev];
        !           636:                outb(ip->dev + c->qid.path, data);
        !           637:                break;
        !           638:        case Qdebug:
        !           639:                incondebug = data;
        !           640:                break;
        !           641:        }
        !           642:        return n;
        !           643: }
        !           644: 
        !           645: void    
        !           646: inconremove(Chan *c)
        !           647: {
        !           648:        USED(c);
        !           649:        error(Eperm);
        !           650: }
        !           651: 
        !           652: void    
        !           653: inconwstat(Chan *c, char *dp)
        !           654: {
        !           655:        USED(c, dp);
        !           656:        error(Eperm);
        !           657: }
        !           658: 
        !           659: /*
        !           660:  *     the stream routines
        !           661:  */
        !           662: 
        !           663: /*
        !           664:  *  kill off the kernel process
        !           665:  */
        !           666: static int
        !           667: kNotliving(void *arg)
        !           668: {
        !           669:        Incon *ip;
        !           670: 
        !           671:        ip = (Incon *)arg;
        !           672:        return ip->kstarted == 0;
        !           673: }
        !           674: 
        !           675: static void
        !           676: inconstclose(Queue * q)
        !           677: {
        !           678:        Incon *ip;
        !           679: 
        !           680:        ip = (Incon *)q->ptr;
        !           681:        qlock(ip);
        !           682:        ip->rq = 0;
        !           683:        qunlock(ip);
        !           684:        wakeup(&ip->kr);
        !           685:        sleep(&ip->r, kNotliving, ip);
        !           686: }
        !           687: 
        !           688: /*
        !           689:  *  create the kernel process for input
        !           690:  *  first wait for any old ones to die
        !           691:  */
        !           692: static void
        !           693: inconstopen(Queue *q, Stream *s)
        !           694: {
        !           695:        Incon *ip;
        !           696:        char name[32];
        !           697: 
        !           698:        ip = &incon[s->dev];
        !           699:        sprint(name, "incon%d", s->dev);
        !           700:        q->ptr = q->other->ptr = ip;
        !           701:        wakeup(&ip->kr);
        !           702:        sleep(&ip->r, kNotliving, ip);
        !           703:        ip->rq = q;
        !           704:        kproc(name, inconkproc, ip);
        !           705: }
        !           706: 
        !           707: /*
        !           708:  *  free all blocks of a message in `q', `bp' is the first block
        !           709:  *  of the message
        !           710:  */
        !           711: static void
        !           712: freemsg(Queue *q, Block *bp)
        !           713: {
        !           714:        for(; bp; bp = getq(q)){
        !           715:                if(bp->flags & S_DELIM){
        !           716:                        freeb(bp);
        !           717:                        return;
        !           718:                }
        !           719:                freeb(bp);
        !           720:        }
        !           721: }
        !           722: 
        !           723: static void
        !           724: showpkt(char *str, int chan, int ctl, Block *bp, int i)
        !           725: {
        !           726:        int n;
        !           727: 
        !           728:        n = bp->wptr - bp->rptr;
        !           729:        kprint("%s(%d)%uo %d", str, chan, ctl, n);
        !           730:        if(n > 8)
        !           731:                n = 8;
        !           732:        for(; i<n; i++)
        !           733:                kprint(" %2.2ux", bp->rptr[i]);
        !           734:        kprint("\n");
        !           735: }
        !           736: 
        !           737: /*
        !           738:  *  output a block
        !           739:  *
        !           740:  *  the first 2 bytes of every message are the channel number,
        !           741:  *  low order byte first.  the third is a possible trailing control
        !           742:  *  character.
        !           743:  */
        !           744: void
        !           745: inconoput(Queue *q, Block *bp)
        !           746: {
        !           747:        int dev;
        !           748:        Incon *ip;
        !           749:        ulong end;
        !           750:        int status, chan, ctl;
        !           751:        int n, size;
        !           752: 
        !           753:        ip = (Incon *)q->ptr;
        !           754: 
        !           755:        if(bp->type != M_DATA){
        !           756:                if(streamparse("inconset", bp))
        !           757:                        inconsetctl(ip, bp);
        !           758:                else
        !           759:                        freeb(bp);
        !           760:                return;
        !           761:        }
        !           762:        if(BLEN(bp) < 3){
        !           763:                bp = pullup(bp, 3);
        !           764:                if(bp == 0){
        !           765:                        print("inconoput pullup failed\n");
        !           766:                        return;
        !           767:                }
        !           768:        }
        !           769: 
        !           770:        /*
        !           771:         *  get a whole message before handing bytes to the device
        !           772:         */
        !           773:        if(!putq(q, bp))
        !           774:                return;
        !           775: 
        !           776:        /*
        !           777:         *  one transmitter at a time
        !           778:         */
        !           779:        qlock(&ip->xmit);
        !           780:        dev = ip->dev;
        !           781: 
        !           782:        /*
        !           783:         *  parse message
        !           784:         */
        !           785:        bp = getq(q);
        !           786:        chan = bp->rptr[0] | (bp->rptr[1]<<8);
        !           787:        ctl = bp->rptr[2];
        !           788:        bp->rptr += 3;
        !           789:        if(chan<=0)
        !           790:                print("bad channel %d\n", chan);
        !           791: 
        !           792:        if(incondebug){
        !           793:                kprint("0x%.2ux ", rdstatus(ip));
        !           794:                showpkt("->", chan, ctl, bp, 0);
        !           795:        }
        !           796: 
        !           797:        /*
        !           798:         *  make sure there's an incon out there
        !           799:         */
        !           800:        if(!(rdstatus(ip)&INCON_ALIVE) || ip->state==Notliving){
        !           801:                DPRINT("inconoput: not ready");
        !           802:                inconrestart(ip);
        !           803:                freemsg(q, bp);
        !           804:                qunlock(&ip->xmit);
        !           805:                return;
        !           806:        }
        !           807: 
        !           808:        /*
        !           809:         *  send the 8 bit data
        !           810:         */
        !           811:        for(;;){
        !           812:                /*
        !           813:                 *  spin till there is room
        !           814:                 */
        !           815:                for(n=0, end = NOW+1000; (status=rdstatus(ip)) & TX_FULL; n++){
        !           816:                        nop();  /* make sure we don't optimize too much */
        !           817:                        if(NOW > end){
        !           818:                                print("incon output stuck 0 %.2ux\n", status);
        !           819:                                freemsg(q, bp);
        !           820:                                qunlock(&ip->xmit);
        !           821:                                return;
        !           822:                        }
        !           823:                }
        !           824:                ip->wait = (n + ip->wait)>>1;
        !           825: 
        !           826:                /*
        !           827:                 *  put in next packet
        !           828:                 */
        !           829:                n = bp->wptr - bp->rptr;
        !           830:                if(n > 16)
        !           831:                        n = 16;
        !           832:                size = n;
        !           833:                wrctl(dev, chan);
        !           834:                ip->out += n;
        !           835:                while(n--){
        !           836:                        wrdata(dev, *bp->rptr++);
        !           837:                }
        !           838: 
        !           839:                /*
        !           840:                 *  get next block 
        !           841:                 */
        !           842:                if(bp->rptr >= bp->wptr){
        !           843:                        if(bp->flags & S_DELIM){
        !           844:                                freeb(bp);
        !           845:                                break;
        !           846:                        }
        !           847:                        freeb(bp);
        !           848:                        bp = getq(q);
        !           849:                        if(bp==0)
        !           850:                                break;
        !           851:                }
        !           852: 
        !           853:                /*
        !           854:                 *  end packet
        !           855:                 */
        !           856:                wrctl(dev, 0);
        !           857:        }
        !           858: 
        !           859:        /*
        !           860:         *  send the control byte if there is one
        !           861:         */
        !           862:        if(ctl){
        !           863:                if(size >= 16){
        !           864:                        wrctl(dev, 0);
        !           865:                        for(end = NOW+1000; rdstatus(ip) & TX_FULL;){
        !           866:                                nop();  /* make sure we don't optimize too much */
        !           867:                                if(NOW > end){
        !           868:                                        print("incon output stuck 1\n");
        !           869:                                        freemsg(q, bp);
        !           870:                                        qunlock(&ip->xmit);
        !           871:                                        return;
        !           872:                                }
        !           873:                        }
        !           874:                        wrctl(dev, chan);
        !           875:                }
        !           876:                if(rdstatus(ip) & TX_FULL)
        !           877:                        print("inconfull\n");
        !           878:                ip->out += 1;
        !           879:                wrctl(dev, ctl);
        !           880:        }
        !           881:        wrctl(dev, 0);
        !           882: 
        !           883:        qunlock(&ip->xmit);
        !           884:        return;
        !           885: }
        !           886: 
        !           887: /*
        !           888:  *  return true if the raw fifo is non-empty
        !           889:  */
        !           890: static int
        !           891: notempty(void *arg)
        !           892: {
        !           893:        Incon *ip;
        !           894: 
        !           895:        ip = (Incon *)arg;
        !           896:        return ip->ri!=ip->wi;
        !           897: }
        !           898: 
        !           899: /*
        !           900:  *  Read bytes from the raw input circular buffer.
        !           901:  */
        !           902: static void
        !           903: inconkproc(void *arg)
        !           904: {
        !           905:        Incon *ip;
        !           906:        Block *bp;
        !           907:        int i;
        !           908:        int locked;
        !           909: 
        !           910:        ip = (Incon *)arg;
        !           911:        ip->kstarted = 1;
        !           912: 
        !           913:        /*
        !           914:         *  create a number of blocks for input
        !           915:         */
        !           916:        for(i = 0; i < Nin; i++){
        !           917:                bp = ip->inb[i] = allocb(Bsize);
        !           918:                bp->wptr += 3;
        !           919:        }
        !           920: 
        !           921:        locked = 0;
        !           922:        if(waserror()){
        !           923:                if(locked)
        !           924:                        qunlock(ip);
        !           925:                ip->kstarted = 0;
        !           926:                wakeup(&ip->r);
        !           927:                return;
        !           928:        }
        !           929: 
        !           930:        for(;;){
        !           931:                /*
        !           932:                 *  sleep if input fifo empty
        !           933:                 */
        !           934:                sleep(&ip->kr, notempty, ip);
        !           935: 
        !           936:                /*
        !           937:                 *  die if the device is closed
        !           938:                 */
        !           939:                USED(locked);
        !           940:                qlock(ip);
        !           941:                locked = 1;
        !           942:                if(ip->rq == 0){
        !           943:                        qunlock(ip);
        !           944:                        ip->kstarted = 0;
        !           945:                        wakeup(&ip->r);
        !           946:                        poperror();
        !           947:                        return;
        !           948:                }
        !           949: 
        !           950:                /*
        !           951:                 *  send blocks upstream and stage new blocks.
        !           952:                 */
        !           953:                while(ip->ri != ip->wi){
        !           954:                        bp = ip->inb[ip->ri];
        !           955:                        bp->flags |= S_DELIM;
        !           956:                        ip->in += BLEN(bp);
        !           957:                        PUTNEXT(ip->rq, bp);
        !           958:                        bp = ip->inb[ip->ri] = allocb(Bsize);
        !           959:                        bp->wptr += 3;
        !           960:                        ip->ri = (ip->ri+1)%Nin;
        !           961:                }
        !           962:                USED(locked);
        !           963:                qunlock(ip);
        !           964:                locked = 0;
        !           965:        }
        !           966: }
        !           967: 
        !           968: /*
        !           969:  *  drop a single packet
        !           970:  */
        !           971: static void
        !           972: droppacket(int dev)
        !           973: {
        !           974:        if(irddata(dev) == 0)
        !           975:                return;
        !           976:        while(irdnext(dev))
        !           977:                ;
        !           978: }
        !           979: 
        !           980: /*
        !           981:  *  flush the input fifo
        !           982:  */
        !           983: static void
        !           984: flushfifo(Incon *ip)
        !           985: {
        !           986:        while(!(irdstatus(ip) & RCV_EMPTY))
        !           987:                droppacket(ip->dev);
        !           988: }
        !           989: 
        !           990: /*
        !           991:  *  advance the queue. if we've run out of staged input blocks,
        !           992:  *  drop the packet and return 0.  otherwise return the next input
        !           993:  *  block to fill.
        !           994:  */
        !           995: static Block *
        !           996: nextin(Incon *ip, unsigned int c)
        !           997: {
        !           998:        Block *bp;
        !           999:        int next;
        !          1000: 
        !          1001:        bp = ip->inb[ip->wi];
        !          1002:        bp->rptr[0] = ip->chan;
        !          1003:        bp->rptr[1] = ip->chan>>8;
        !          1004:        bp->rptr[2] = c;
        !          1005:        if(incondebug)
        !          1006:                showpkt("<-", ip->chan, c, bp, 3);
        !          1007: 
        !          1008:        next = (ip->wi+1)%Nin;
        !          1009:        if(next == ip->ri){
        !          1010:                bp->wptr = bp->rptr+3;
        !          1011:                return bp;
        !          1012:        }
        !          1013:        ip->wi = next;
        !          1014: 
        !          1015:        return ip->inb[ip->wi];
        !          1016: }
        !          1017: 
        !          1018: /*
        !          1019:  *  read the packets from the device into the staged input blocks.
        !          1020:  *  we have to do this at interrupt tevel to turn off the interrupts.
        !          1021:  */
        !          1022: static void
        !          1023: rdpackets(Incon *ip)
        !          1024: {
        !          1025:        Block *bp;
        !          1026:        unsigned int c;
        !          1027:        int dev;
        !          1028:        uchar *p;
        !          1029:        int first = ip->wi;
        !          1030: 
        !          1031:        dev = ip->dev;
        !          1032:        bp = ip->inb[ip->wi];
        !          1033:        if(bp==0){
        !          1034:                flushfifo(ip);
        !          1035:                return;
        !          1036:        }
        !          1037:        p = bp->wptr;
        !          1038:        while(!(irdstatus(ip) & RCV_EMPTY)){
        !          1039:                /*
        !          1040:                 *  get channel number
        !          1041:                 */
        !          1042:                c = irddata(dev);
        !          1043:                if(c == 0){
        !          1044:                        droppacket(dev);
        !          1045:                        continue;
        !          1046:                }
        !          1047:                if(ip->chan != c){
        !          1048:                        if(p - bp->rptr > 3){
        !          1049:                                bp->wptr = p;
        !          1050:                                bp = nextin(ip, 0);
        !          1051:                                p = bp->wptr;
        !          1052:                        }
        !          1053:                        ip->chan = c;
        !          1054:                }
        !          1055: 
        !          1056:                /*
        !          1057:                 *  null byte marks end of packet
        !          1058:                 */
        !          1059:                while(c = irdnext(dev)){        /* assign = */
        !          1060:                        if((c & 0x100) == 0){
        !          1061:                                /*
        !          1062:                                 *  control byte ends block
        !          1063:                                 */
        !          1064:                                bp->wptr = p;
        !          1065:                                bp = nextin(ip, c);
        !          1066:                                p = bp->wptr;
        !          1067:                        }else{
        !          1068:                                /*
        !          1069:                                 *  data byte, put in local buffer
        !          1070:                                 */
        !          1071:                                *p++ = c;
        !          1072:                        }
        !          1073:                }
        !          1074: 
        !          1075:                /*
        !          1076:                 *  pass a block on if it doesn't have room for one more
        !          1077:                 *  packet.  this way we don't have to check per byte.
        !          1078:                 */
        !          1079:                if(p + 16 > bp->lim){
        !          1080:                        bp->wptr = p;
        !          1081:                        bp = nextin(ip, 0);
        !          1082:                        p = bp->wptr;
        !          1083:                }
        !          1084:        }       
        !          1085:        bp->wptr = p;
        !          1086:        if(bp->wptr != bp->rptr+3)
        !          1087:                nextin(ip, 0);
        !          1088: 
        !          1089:        if(first != ip->wi)/**/
        !          1090:                wakeup(&ip->kr);
        !          1091: }
        !          1092: 
        !          1093: /*
        !          1094:  *  Receive an incon interrupt.  One entry point
        !          1095:  *  for all types of interrupt.  Until we figure out
        !          1096:  *  how to use more than one incon, this routine only
        !          1097:  *  is for incon[0].
        !          1098:  */
        !          1099: static void
        !          1100: inconintr(Ureg *ur, void *a)
        !          1101: {
        !          1102:        uchar status;
        !          1103:        int pcr;
        !          1104:        Incon *ip;
        !          1105: 
        !          1106:        USED(ur, a);
        !          1107:        ip = &incon[0];
        !          1108:        pcr = inb(ip->dev+Qpcr);
        !          1109:        if(!(pcr & Fie))
        !          1110:                return;
        !          1111:        status = irdstatus(ip);
        !          1112:        if(incondebug){
        !          1113:                kprint("pcr=%2.2x status=%2.2x\n", pcr, status);
        !          1114:                if(pcr & Fstrobe)
        !          1115:                        kprint("YIKES!!\n");
        !          1116:        }
        !          1117:        if(!(status & RCV_EMPTY))
        !          1118:                rdpackets(ip);
        !          1119: 
        !          1120:        /* see if it died underneath us */
        !          1121:        if(!(status&INCON_ALIVE)){
        !          1122:                switch(ip->state){
        !          1123:                case Selected:
        !          1124:                        iwrcmd(ip->dev, INCON_STOP);
        !          1125:                        DPRINT("Incon died\n");
        !          1126:                        print("Incon died\n");
        !          1127:                        break;
        !          1128:                case Selecting:
        !          1129:                        DPRINT("rejected\n");
        !          1130:                        print("rejected\n");
        !          1131:                        break;
        !          1132:                default:
        !          1133:                        iwrcmd(ip->dev, INCON_STOP);
        !          1134:                        DPRINT("state was %d\n", ip->state);
        !          1135:                        break;
        !          1136:                }
        !          1137:                ip->state = Notliving;
        !          1138:        }
        !          1139:        irdnop(ip->dev, pcr);
        !          1140: }

unix.superglobalmegacorp.com

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