Annotation of researchv9/sys/sundev/ie.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Copyright (c) 1985 by Sun Microsystems, Inc.
                      3:  */
                      4: 
                      5: #include "ie.h"
                      6: #if NIE > 0
                      7: /*
                      8:  * Sun Intel Ethernet Controller interface
                      9:  */
                     10: 
                     11: #include "../h/param.h"
                     12: #include "../h/systm.h"
                     13: #include "../machine/pte.h"
                     14: #include "../h/map.h"
                     15: #include "../h/buf.h"
                     16: #include "../h/vmmac.h"
                     17: #include "../h/conf.h"
                     18: #include "../h/ttyio.h"
                     19: #include "../h/enio.h"
                     20: #include "../h/ttyld.h"
                     21: #include "../h/stream.h"
                     22: #include "../h/ethernet.h"
                     23: 
                     24: #include "../sundev/mbvar.h"
                     25: #include "../sundev/iereg.h"
                     26: #include "../sundev/iem.h"
                     27: #include "../sundev/ieob.h"
                     28: 
                     29: /* controller types */
                     30: #define IE_MB  1       /* Multibus */
                     31: #define IE_OB  2       /* Onboard I/O */
                     32:  
                     33: #define        IEOBMEMDFT      (40*1024)       /* default memory allocated for obie */
                     34: #define CBCACHESIZ     (80)            /* size of control block cache */
                     35: #define OVFLWARNMASK   (3)             /* overflow count mask before warning */
                     36: #define NPOOL_RBD      50
                     37: #define        NTRANSBUF       4               /* NUmber of transmit buffers */
                     38: 
                     39: int    ieprobe(), ieattach(), iepoll();
                     40: struct mb_device *ieinfo[NIE];
                     41: struct mb_driver iedriver = {
                     42:        ieprobe, 0, ieattach, 0, 0, iepoll,
                     43:        /* take the larger of the two devices */
                     44:        sizeof (struct mie_device), "ie", ieinfo,
                     45: };
                     46: 
                     47: caddr_t from_ieaddr();
                     48: ieoff_t to_ieoff();
                     49: caddr_t from_ieoff();
                     50: ieaddr_t to_ieaddr();
                     51: long  escbget(), escbput();
                     52: ieint_t to_ieint();
                     53: #define        from_ieint      to_ieint
                     54: 
                     55: #define iepages(x)     (((x) + IEPAGSIZ-1)>>IEPAGSHIFT)
                     56: 
                     57: int iecbcsmall;
                     58: int iecbclarge;
                     59: 
                     60: /*
                     61:  * Ethernet software status per interface.
                     62:  */
                     63: struct ie_softc {
                     64: /* Added by D.A.K for version 9 compatability */
                     65:        char myetheradr[6];
                     66:        char    attached;       /* Non zero when ie has been attached */
                     67:        int     state;
                     68:        int     collisions;
                     69:        int     ierrors, oerrors;
                     70:        int     ipackets, opackets;
                     71:        struct ietfd *es_tfd[NTRANSBUF];        /* transmit TFD */
                     72:        struct ietbd *es_tbd[NTRANSBUF];        /* transmit TBD */
                     73:        caddr_t es_tbuffer[NTRANSBUF];          /* transmit buffer */
                     74:        int     es_tfree;                       /* transmitter bit map */
                     75: /* Supplied by SUN */
                     76:        struct mie_device *es_mie;      /* Multibus board registers */
                     77:        struct obie_device *es_obie;    /* On-board registers */
                     78:        caddr_t es_memspace;            /* + chip addr = kernel addr */
                     79:        int     es_paddr;               /* starting page number for board */
                     80:        int     es_vmemsize;            /* size of multibus mem port */
                     81:        caddr_t es_base;                /* our addr of control block base */
                     82:        struct map *es_cbmap;           /* rmap for control blocks */
                     83:        struct map *es_memmap;          /* rmap for memory */
                     84:        struct map *es_pgmap;           /* rmap for 1K page (ND) memory
                     85:                                           accessed thru if_memmap */
                     86:        struct iescb *es_scb;           /* SCB ptr */
                     87:        struct iescp *es_scp;           /* SCP ptr */
                     88:        struct iecb *es_cbhead;         /* CBL head */
                     89:        struct iecb *es_cbtail;         /* CBL tail */
                     90:        struct ierfd *es_rfdhead;       /* head of RFD list */
                     91:        struct ierfd *es_rfdtail;       /* tail of RFD list */
                     92:        struct ierbd *es_rbdhead;       /* head of RBD list */
                     93:        struct ierbd *es_rbdtail;       /* tail of RBD list */
                     94:        struct ieipack *es_iepavail;    /* standby input packets */
                     95:        int     es_obmem;               /* total IE_OB main memory */
                     96:        char    es_type;                /* type of controller */
                     97:        char    es_simple;              /* doing simple flag */
                     98:        u_int   es_runotready;          /* RU was not ready counter */
                     99:        u_int   es_xmiturun;            /* xmit DMA underrun counter */
                    100:        u_int   es_ieheart;             /* heartbeat counter */
                    101:        u_int   es_iedefer;             /* deferred transmission counter */
                    102:        struct ieierr {
                    103:                u_int   crc;
                    104:                u_int   aln;
                    105:                u_int   rsc;
                    106:                u_int   ovr;
                    107:        }        es_ierr;               /* input error counters */
                    108:        int     es_cbsize;              /* control block area size */
                    109:        int     es_cbc_lo;              /* small block cache pointer */
                    110:        int     es_cbc_hi;              /* large block cache pointer */
                    111:        u_int   es_cbc_ovfl;            /* overflow counter */
                    112:        int     es_cbcbusy;             /* cache is loaded */
                    113:        long    es_cbcache[CBCACHESIZ]; /* control block cache */
                    114: } ie_softc[NIE];
                    115: 
                    116: #define        NIECHAN (CHANS_PER_UNIT * NIE)
                    117: struct iechan {
                    118:        int     unit;
                    119:        int     packets;
                    120:        struct  queue *ieq;
                    121:        int     type;
                    122: } iechan[NIECHAN];
                    123: 
                    124: int    nodev(), ieopen(), ieclose(), ieput(), iesrv();
                    125: static struct qinit ierinit = { nodev, NULL, ieopen, ieclose, 0, 0 };
                    126: static struct qinit iewinit = { ieput, NULL, ieopen, ieclose, 1514, 0 };
                    127:        /* 1514 bytes is minimum highwater mark to send 1514 byte packets */
                    128: struct streamtab iesinfo = { &ierinit, &iewinit };
                    129: 
                    130: #define IEMAPSIZ       100
                    131: struct map iecbmap[NIE][IEMAPSIZ];
                    132: struct map iememmap[NIE][IEMAPSIZ];
                    133: struct map iepgmap[NIE][IEMAPSIZ];
                    134: #define        escballoc(es, type, cached) (type *)escbget(es, sizeof(type), cached)
                    135: #define        escbfree(es, ptr)       escbput(es, sizeof(*ptr), (long)ptr);
                    136: #define escbpin(es, len, addr) rmget(es->es_cbmap, (int)len, (int)addr)
                    137: #define esmemalloc(es, len)    rmalloc(es->es_memmap, (long)len)
                    138: #define esmemfree(es, len, ptr)        rmfree(es->es_memmap, (long)len, (long)ptr)
                    139: #define esmempin(es, len, addr) rmget(es->es_memmap, (int)len, (int)addr)
                    140: 
                    141: /*
                    142:  * fixed header size for page alignment of received data buffers
                    143:  * this is sizeof(struct ndpack) for ND.  (doesn't include ether header)
                    144:  */
                    145: #define        OPTHDRSIZ       48
                    146: #define        IPACKOVH        8       /* struct ieipack header overhead */
                    147: struct ieipack {
                    148:        struct ieipack  *iep_next;      /* next in list; MUST BE FIRST FIELD */
                    149:        struct ie_softc *iep_es;        /* assoc ie_softc */
                    150:        char    iep_data[1500];         /* the packet */
                    151: };
                    152: 
                    153: #define IEDELAY        400000          /* delay period (in ms) before giving up */
                    154: #define IEKLUDGE 20            /* delay period (in ms) to make chip work */
                    155: 
                    156: /*
                    157:  * Probe for device.
                    158:  */
                    159: ieprobe(reg, unit)
                    160:        caddr_t reg;
                    161: {
                    162:        register short *sp;
                    163:        struct ie_softc *es = &ie_softc[unit];
                    164: 
                    165:        if ((getkpgmap(reg) & PGT_MASK) == PGT_OBIO) {
                    166:                register struct obie_device *obie = (struct obie_device *)reg;
                    167: 
                    168:                /* onboard Ethernet */
                    169:                if (pokec(reg, 0))
                    170:                        return (0);
                    171:                if (peekc(reg) == -1)
                    172:                        return (0);
                    173:                if (obie->obie_noreset)
                    174:                        return (0);
                    175:                es->es_type = IE_OB;
                    176:        } else {
                    177:                register struct mie_device *mie = (struct mie_device *)reg;
                    178: 
                    179:                /* Multibus Ethernet */
                    180:                sp = (short *)mie;
                    181:                if (poke(sp, 0))
                    182:                        return (0);
                    183:                sp = &mie->mie_prom[0];
                    184:                if (poke(sp, 0x6789))
                    185:                        return (0);
                    186:                if (peek(sp) == 0x6789)
                    187:                        return (0);
                    188:                es->es_type = IE_MB;
                    189:        } 
                    190:        return (1);
                    191: }
                    192: 
                    193: /*
                    194:  * Interface exists; make available by filling in network interface
                    195:  * record.  System will initialize the interface when it is ready
                    196:  * to accept packets.
                    197:  */
                    198: ieattach(md)
                    199:        struct mb_device *md;
                    200: {
                    201:        struct ie_softc *es = &ie_softc[md->md_unit];
                    202: 
                    203:        if (md->md_intr)        /* set up vectored interrupts */
                    204:                *(md->md_intr->v_vptr) = (int)es;
                    205: 
                    206:        if (es->es_type == IE_OB) {
                    207:                es->es_obie = (struct obie_device *)md->md_addr;
                    208:                es->es_obmem = IEOBMEMDFT;
                    209:        } else {
                    210:                es->es_mie = (struct mie_device *)md->md_addr;
                    211:                /*
                    212:                 * magic thru config used to artificially restrict
                    213:                 * the amount of MBMEM used, as there is only 1 Mb
                    214:                 * available, making it a scarce resource.
                    215:                 */
                    216:                switch (md->md_flags) {
                    217:                case 0:
                    218:                default:
                    219:                        es->es_vmemsize = 256*1024;
                    220:                        break;
                    221:                case 1:
                    222:                        es->es_vmemsize = 128*1024;
                    223:                        break;
                    224:                case 2:
                    225:                        es->es_vmemsize = 64*1024;
                    226:                        break;
                    227:                }
                    228:        }
                    229:        iechipreset(es);
                    230:        localetheraddr(NULL, es->myetheradr);
                    231:        ieinit(md->md_unit);
                    232:        es->attached = 1;
                    233: }
                    234: 
                    235: /* ARGSUSED */
                    236: ieopen(q, dev)
                    237: register struct queue *q;
                    238: register dev_t dev;
                    239: {
                    240:        register struct iechan *ied;
                    241:        register struct ie_softc *es;
                    242:        register unit;
                    243: 
                    244:        dev = minor(dev);
                    245:        unit = dev / CHANS_PER_UNIT;
                    246: 
                    247:        if (dev >= NIECHAN)
                    248:                return(0);
                    249:        if (unit >= NIE)
                    250:                return(0);
                    251: 
                    252:        es = &ie_softc[unit];
                    253:        if(!es->attached)
                    254:                return(0);
                    255:        ied = &iechan[dev];
                    256:        if (ied->ieq)
                    257:                return(0);
                    258: 
                    259:        ied->unit = unit;
                    260:        ied->ieq = q;
                    261:        q->ptr = (caddr_t)ied;
                    262:        q->flag |= QBIGB | QDELIM;
                    263:        WR(q)->ptr = (caddr_t)ied;
                    264:        WR(q)->flag |= QBIGB|QDELIM;
                    265:        return(1);
                    266: }
                    267: 
                    268: ieclose(q)
                    269: register struct queue *q;
                    270: {
                    271:        register struct iechan *ied;
                    272: 
                    273:        ied = (struct iechan *)q->ptr;
                    274:        flushq(WR(q), 1);
                    275:        ied->ieq = NULL;
                    276: }
                    277: 
                    278: ieput(q, bp)
                    279: register struct queue *q;
                    280: register struct block *bp;
                    281: {
                    282:        register struct iechan *ied;
                    283:        register struct ie_softc *es;
                    284:        register unit, s;
                    285: 
                    286:        ied = (struct iechan *)q->ptr;
                    287:        unit = ied->unit;
                    288:        es = &ie_softc[unit];
                    289: 
                    290:        switch(bp->type) {
                    291:        
                    292:                case M_IOCTL:
                    293:                        ieioctl(q, bp);
                    294:                        return;
                    295: 
                    296:                case M_DATA:
                    297:                        putq(q, bp);
                    298:                        return;
                    299:                
                    300:                case M_DELIM:
                    301:                        break;
                    302: 
                    303:                default:
                    304:                        freeb(bp);
                    305:                        return;
                    306:        }
                    307: 
                    308:        putq(q, bp);
                    309:        s = splie();
                    310:        ied->packets++;
                    311:        if (es->es_tfree)
                    312:                iestartout(unit);
                    313:        splx(s);
                    314: }
                    315: 
                    316: /*
                    317:  * Process an ioctl request.
                    318:  */
                    319: ieioctl(q, bp)
                    320: register struct queue *q;
                    321: register struct block *bp;
                    322: {
                    323:        register struct iechan *ied;
                    324:        register struct ie_softc *es;
                    325:        register u_char *msg;
                    326:        int     unit, cmd;
                    327:        
                    328:        ied = (struct iechan *)q->ptr;
                    329:        unit = ied->unit;
                    330:        es = &ie_softc[unit];
                    331:        cmd = ((union stmsg *)(bp->rptr))->ioc1.com;
                    332:        msg = (u_char *)&((union stmsg *)(bp->rptr))->ioc1.sb;
                    333: 
                    334:        bp->type = M_IOCACK;
                    335:        switch (cmd) {
                    336:                case ENIOADDR:          /* get my Ethernet address */
                    337:                        bcopy(es->myetheradr, (int *)msg, 6);
                    338:                        break;
                    339: 
                    340:                case ENIOTYPE:
                    341:                        ied->type = *(int *)msg;
                    342:                        break;
                    343:                        
                    344:                default:
                    345:                        bp->type = M_IOCNAK;
                    346:                        break;
                    347:        }
                    348:        qreply(q, bp);
                    349: }
                    350: 
                    351: /*
                    352:  * Unconditionally restart the interface from ground zero.
                    353:  */
                    354: ieinit(unit)
                    355:        int unit;
                    356: {
                    357:        struct ie_softc *es = &ie_softc[unit];
                    358:        int s = splie();
                    359: 
                    360:        iechipreset(es);
                    361: 
                    362:        iedomaps(es);
                    363:        if (!iechipinit(es))
                    364:                goto exit;
                    365:        iedoaddr(es);
                    366:        /*
                    367:         * Hang out receive buffers and start any pending writes.
                    368:         */
                    369:        ierustart(es);
                    370:        iesplice(es);
                    371:        iestartout(unit);
                    372: exit:
                    373:        (void) splx(s);
                    374: }
                    375: 
                    376: /*
                    377:  * Handle Polling Ethernet interrupts
                    378:  */
                    379: iepoll()
                    380: {
                    381:        register struct ie_softc *es;
                    382:        register int found = 0;
                    383: 
                    384:        for (es = ie_softc; es < &ie_softc[NIE]; es++) {
                    385:                switch (es->es_type) {
                    386:                case IE_MB:
                    387:                        if (es->es_mie->mie_pie && es->es_mie->mie_pe) {
                    388:                                ieparity(es);
                    389:                                return (1);
                    390:                        }
                    391:                        if (es->es_mie->mie_ie == 0)
                    392:                                continue;
                    393:                        if (es->es_mie->mie_intr)
                    394:                                found = 1;
                    395:                        break;
                    396:                case IE_OB:
                    397:                        if (es->es_obie->obie_buserr)
                    398:                                panic("ie: bus error");
                    399:                        if (es->es_obie->obie_ie == 0)
                    400:                                continue;
                    401:                        if (es->es_obie->obie_intr)
                    402:                                found = 1;
                    403:                        break;
                    404:                default:        /* not present */
                    405:                        continue;
                    406:                }
                    407:                /*
                    408:                 * Since the 82586 can take away an interrupt
                    409:                 * request after presenting it to the processsor
                    410:                 * (to facilitate an update of a new interrupt
                    411:                 * condition in the scb), we also have to check
                    412:                 * the scb to see if it indicates an interrupt
                    413:                 * condition from the chip.
                    414:                 */
                    415:                if (found == 0) {
                    416:                        register struct iescb *scb = es->es_scb;
                    417: 
                    418:                        if (scb->ie_cx || scb->ie_fr ||
                    419:                            scb->ie_cnr || scb->ie_rnr)
                    420:                                found = 1;
                    421:                }
                    422:                if (found) {
                    423:                        ieintr(es);
                    424:                        break;
                    425:                }
                    426:        }
                    427:        return (found);
                    428: }
                    429: 
                    430: /*
                    431:  * Handle Ethernet interrupts
                    432:  */
                    433: ieintr(es)
                    434:        register struct ie_softc *es;
                    435: {
                    436:        register struct iescb *scb;
                    437:        register int cmd, unit;
                    438: 
                    439:        unit = es - ie_softc;
                    440:        scb = es->es_scb;
                    441:        iechkcca(scb);
                    442:        if (scb->ie_cmd != 0)  {
                    443:                register struct mb_device *md;
                    444: 
                    445:                printf("ie%d: lost synch\n", unit);
                    446:                iestat(es);
                    447:                if (unit >= NIE || (md = ieinfo[unit]) == 0 ||
                    448:                    md->md_alive == 0)
                    449:                        return;
                    450:                ieinit(unit);
                    451:                return;
                    452:        }
                    453:        cmd = 0;
                    454: /*
                    455:  * This can be done faster with something like:
                    456:  * cmd = (*(short *)scb->ie_cx) &
                    457:  *                (IECMD_ACK_CX|IECMD_ACK_FR|IECMD_ACK_CNR|IECMD_ACK_RNR);
                    458:  */
                    459: 
                    460:        if (scb->ie_cx)
                    461:                cmd |= IECMD_ACK_CX;
                    462:        if (scb->ie_fr)
                    463:                cmd |= IECMD_ACK_FR;
                    464:        if (scb->ie_cnr)
                    465:                cmd |= IECMD_ACK_CNR;
                    466:        if (scb->ie_rnr)
                    467:                cmd |= IECMD_ACK_RNR;
                    468:        if (cmd == 0) {
                    469:                printf("ie%d: spurious intr\n", unit);
                    470:                cmd = IECMD_ACK_CX+IECMD_ACK_FR+IECMD_ACK_CNR+IECMD_ACK_RNR;
                    471:        }
                    472:        scb->ie_cmd = cmd;
                    473:        ieca(es);
                    474: 
                    475:        if (cmd & (IECMD_ACK_RNR|IECMD_ACK_FR))
                    476:                ierecv(es);
                    477:        if (cmd & (IECMD_ACK_CNR|IECMD_ACK_CX))
                    478:                iecbdone(es);
                    479: 
                    480:        if (es->es_cbhead && scb->ie_cus == IECUS_IDLE) {
                    481:                iechkcca(scb);
                    482:                if (es->es_cbhead && scb->ie_cus == IECUS_IDLE &&
                    483:                    !scb->ie_cx && !scb->ie_cnr)
                    484:                        printf("ie%d: CU out of synch\n", unit);
                    485:        }
                    486: }
                    487: 
                    488: /*
                    489:  * Tell the chip its ethernet address
                    490:  */
                    491: iedoaddr(es)
                    492:        register struct ie_softc *es;
                    493: {
                    494:        register struct ieiaddr *iad;
                    495: 
                    496:        iad = escballoc(es, struct ieiaddr, 1);
                    497:        if (iad == 0)
                    498:                panic("iedoaddr: iad");
                    499:        bzero((caddr_t)iad, sizeof (struct ieiaddr));
                    500:        iad->ieia_cb.ie_cmd = IE_IADDR;
                    501:        bcopy(es->myetheradr, iad->ieia_addr, sizeof(es->myetheradr));
                    502:        iesimple(es, &iad->ieia_cb);
                    503:        escbfree(es, iad);
                    504: }
                    505: 
                    506: /*
                    507:  * Move info from driver toward protocol interface
                    508:  */
                    509: ieread(es, rfd)
                    510:        register struct ie_softc *es;
                    511:        register struct ierfd *rfd;
                    512: {
                    513:        int unit = es - ie_softc;
                    514:        register struct etherpup *header;
                    515:        register struct ierbd *rbd;
                    516:        register struct iechan *ied;
                    517:        register struct queue *q;
                    518:        register struct block *bp;
                    519:        register len, min, i;
                    520:        register u_char *p;
                    521:        short type;
                    522: 
                    523:        if (!rfd->ierfd_ok) {
                    524:                es->ierrors++;
                    525:                printf("ie%d: receive error\n", unit);
                    526:                return;
                    527:        }
                    528:        if (rfd->ierfd_rbd == IENORBD) {
                    529:                printf("ie%d: runt packet\n", unit);
                    530:                es->ierrors++;
                    531:                return;
                    532:        }
                    533:        rbd = (struct ierbd *)from_ieoff(es, (ieoff_t)rfd->ierfd_rbd);
                    534:        if (!rbd->ierbd_eof) {          /* length > 1500  */
                    535:                printf("ie%d: giant packet\n", unit);
                    536:                es->ierrors++;
                    537:                return;
                    538:        }
                    539:        /*
                    540:         * Pull packet off interface.
                    541:         */
                    542:        header = (struct etherpup *)rfd->ierfd_dhost;
                    543:        type = header->type;
                    544:        ied = &iechan[unit * CHANS_PER_UNIT];
                    545:        for (i = 0; i < CHANS_PER_UNIT; i++, ied++)
                    546:                if (ied->ieq && ied->type == type)
                    547:                        break;
                    548:        if (i >= CHANS_PER_UNIT)
                    549:                return;
                    550:        q = ied->ieq;
                    551:        if (q->next->flag & QFULL) {
                    552:                es->ierrors++;
                    553:                return;
                    554:        }
                    555:        len = (rbd->ierbd_cnthi << 8) + rbd->ierbd_cntlo;
                    556: 
                    557:        /*
                    558:         * Splice in the ethernet header
                    559:         * Assumes allocb will return a block at least as big as etherpup.
                    560:         */
                    561:        bp = allocb(len + sizeof(struct etherpup));
                    562:        *(struct etherpup *)bp->wptr = *header;
                    563:        bp->wptr += sizeof(struct etherpup);
                    564: 
                    565:        /*
                    566:         * Now copy the data
                    567:         */
                    568:        p = (u_char *)from_ieaddr(es, rbd->ierbd_buf);
                    569:        i = MIN(((bp->lim - bp->base) - sizeof(struct etherpup)), len);
                    570:        for(;;) {
                    571:                len -= i;
                    572:                while (i-- > 0)
                    573:                        *bp->wptr++ = *p++;
                    574:                (*q->next->qinfo->putp)(q->next, bp);
                    575:                if (len <= 0)
                    576:                        break;
                    577:                bp = allocb(len);
                    578:                i = MIN((bp->lim - bp->base), len);
                    579:        }
                    580:        if (putctl(q->next, M_DELIM))
                    581:                es->ipackets++;
                    582:        else 
                    583:                printf("ierint no DELIM bp\n");
                    584: }
                    585: 
                    586: /*
                    587:  * Process completed input packets
                    588:  * and recycle resources;
                    589:  * only called from interrupt level by ieintr
                    590:  */
                    591: ierecv(es)
                    592:        register struct ie_softc *es;
                    593: {
                    594:        register struct ierfd *rfd, *nrfd;
                    595:        register struct ierbd *rbd, *nrbd;
                    596:        register struct iescb *scb = es->es_scb;
                    597:        int eof, e;
                    598: 
                    599:        rfd = es->es_rfdhead;
                    600:        if (rfd == NULL)                /* not initialized */
                    601:                return;
                    602: top:
                    603:        while (rfd && rfd->ierfd_done) {
                    604:                ieread(es, rfd);
                    605:                if (rfd->ierfd_rbd != IENORBD) {
                    606:                        rbd = (struct ierbd *)from_ieoff(es,
                    607:                            (ieoff_t)rfd->ierfd_rbd);
                    608:                        if (rbd != es->es_rbdhead)
                    609:                                panic("ierecv rbd");
                    610:                        while (rbd && rbd->ierbd_used) {
                    611:                                if (rbd != (struct ierbd *)from_ieoff(es,
                    612:                                    (ieoff_t)es->es_rbdtail->ierbd_next))
                    613:                                        panic("ierecv rbd list");
                    614:                                nrbd = (struct ierbd *)from_ieoff(es,
                    615:                                        (ieoff_t)rbd->ierbd_next);
                    616:                                rbd->ierbd_el = 1;
                    617:                                eof = rbd->ierbd_eof;
                    618:                                *(short *)rbd = 0;
                    619:                                es->es_rbdtail->ierbd_el = 0;
                    620:                                es->es_rbdtail = rbd;
                    621:                                rbd = es->es_rbdhead = nrbd;
                    622:                                if (eof)
                    623:                                        break;
                    624:                        }
                    625:                }
                    626:                if (rfd != (struct ierfd *)from_ieoff(es,
                    627:                    (ieoff_t)es->es_rfdtail->ierfd_next))
                    628:                        panic("ierecv rfd list");
                    629:                nrfd = (struct ierfd *)from_ieoff(es, (ieoff_t)rfd->ierfd_next);
                    630:                rfd->ierfd_rbd = IENORBD;
                    631:                rfd->ierfd_el = 1;
                    632:                *(short *)rfd = 0;
                    633:                es->es_rfdtail->ierfd_el = 0;
                    634:                es->es_rfdtail = rfd;
                    635:                rfd = es->es_rfdhead = nrfd;
                    636:        }
                    637:        if (e = scb->ie_crcerrs) {      /* count of CRC errors */
                    638:                scb->ie_crcerrs = 0;
                    639:                e = from_ieint(e);
                    640:                es->ierrors += e;
                    641:                es->es_ierr.crc += e;
                    642:        }
                    643:        if (e = scb->ie_alnerrs) {      /* count of alignment errors */
                    644:                scb->ie_alnerrs = 0;
                    645:                e = from_ieint(e);
                    646:                es->ierrors += e;
                    647:                es->es_ierr.aln += e;
                    648:        }
                    649:        if (e = scb->ie_rscerrs) {      /* count of discarded packets */
                    650:                scb->ie_rscerrs = 0;
                    651:                e = from_ieint(e);
                    652:                es->ierrors += e;
                    653:                es->es_ierr.rsc += e;
                    654:        }
                    655:        if (e = scb->ie_ovrnerrs) {     /* count of overrun packets */
                    656:                scb->ie_ovrnerrs = 0;
                    657:                e = from_ieint(e);
                    658:                es->ierrors += e;
                    659:                es->es_ierr.ovr += e;
                    660:        }
                    661:        if (scb->ie_rus == IERUS_READY)         /* as expected */
                    662:                return;
                    663:        es->es_runotready++;
                    664:        /* following test must be made when we know chip is quiet */
                    665:        if (es->es_rfdhead->ierfd_done)         /* more snuck in */
                    666:                goto top;
                    667:        es->es_rfdhead->ierfd_rbd = to_ieoff(es, (caddr_t)es->es_rbdhead);
                    668:        iechkcca(scb);
                    669:        scb->ie_rfa = to_ieoff(es, (caddr_t)es->es_rfdhead);
                    670:        scb->ie_cmd = IECMD_RU_START;
                    671:        ieca(es);
                    672: }
                    673: 
                    674: /*
                    675:  * Free up the resources after transmitting a packet.
                    676:  * Called by iecuclean at splie or hardware level 3.
                    677:  */
                    678: iexmitdone(es, td)
                    679:        register struct ie_softc *es;
                    680:        register struct ietfd *td;
                    681: {
                    682:        int unit = es - ie_softc;
                    683:        register int i;
                    684: 
                    685:        if (td->ietfd_ok) {
                    686:                es->collisions += td->ietfd_ncoll;
                    687:                es->opackets++;
                    688:                if (td->ietfd_defer) es->es_iedefer++;
                    689:                if (td->ietfd_heart) es->es_ieheart++;
                    690:        } else {
                    691:                es->oerrors++;
                    692:                if (td->ietfd_xcoll)
                    693:                        printf("ie%d: Ethernet jammed\n", unit);
                    694:                if (td->ietfd_nocarr)
                    695:                        printf("ie%d: no carrier\n", unit);
                    696:                if (td->ietfd_nocts)
                    697:                        printf("ie%d: no CTS\n", unit);
                    698:                if (td->ietfd_underrun)
                    699:                        es->es_xmiturun++;
                    700:        }
                    701:        if (!td->ietfd_tbd)
                    702:                panic("ie%d: iexmitdone: no tbd");
                    703:        for(i = 0; i < NTRANSBUF; i++)
                    704:                if (td == es->es_tfd[i])
                    705:                        break;
                    706:        if (es->es_tfree & (1 << i))
                    707:                printf("ie%d stray xmit interrupt\n", unit);
                    708:        es->es_tfree |= (1 << i);
                    709: }
                    710: 
                    711: #define rndtoeven(x)   (((x)+1) & ~1)
                    712: /*
                    713:  * Start or restart output to wire.
                    714:  */
                    715: iestartout(unit)
                    716:        int unit;
                    717: {
                    718:        register struct ie_softc *es = &ie_softc[unit];
                    719:        register struct iechan *ied;
                    720:        register cnt, i;
                    721:        register caddr_t to;
                    722:        int count, bufnum;
                    723:        struct ietfd *td;
                    724:        register struct ietbd *tbd;
                    725:        register struct queue *q;
                    726:        register struct block *bp, *nbp;
                    727:        struct block *head, **bnext;
                    728: 
                    729:        if (!es->es_tfree)
                    730:                goto out;
                    731:        ied = &iechan[unit * CHANS_PER_UNIT];
                    732:        for(i = 0; i < CHANS_PER_UNIT; i++, ied++)
                    733:                if (ied->ieq && ied->packets > 0)
                    734:                        break;
                    735:        if (i >= CHANS_PER_UNIT)
                    736:                goto out;
                    737: 
                    738:        ied->packets--;
                    739:        q = WR(ied->ieq);
                    740: 
                    741:        /* The packet must be justified to the end of the buffer.
                    742:         * Therefore, we have to count the bytes before copying.
                    743:         */
                    744:        bnext = &head;
                    745:        while (*bnext = bp = getq(q)) {
                    746:                if (bp->type == M_DELIM) {
                    747:                        bp->next = 0;
                    748:                        break;
                    749:                }
                    750:                cnt += bp->wptr - bp->rptr;
                    751:                bnext = &bp->next;
                    752:        }
                    753:        bp = head;
                    754: 
                    755:        /* if there is no ethernet header in packet, throw it out */
                    756:        if (cnt < sizeof(struct etherpup) ||
                    757:            (bp->wptr - bp->rptr) < sizeof(struct etherpup)) {
                    758:                while(bp) {
                    759:                        nbp = bp->next;
                    760:                        freeb(bp);
                    761:                        bp = nbp;
                    762:                }
                    763:                goto out;
                    764:        }
                    765: 
1.1.1.2 ! root      766:        for (bufnum = 0; ; bufnum++)
        !           767:                if (es->es_tfree & (1 << bufnum))
        !           768:                        break;
1.1       root      769:        es->es_tfree &= ~(1 << bufnum);
                    770:        td = es->es_tfd[bufnum];
                    771:        tbd = es->es_tbd[bufnum];
                    772: 
                    773:        /* Setup the header */
                    774:        bcopy(bp->rptr, (caddr_t)td->ietfd_dhost, 6);   /* Dest */
                    775:        bp->rptr += 12;                                 /* Skip src */
                    776:        bcopy(bp->rptr, (caddr_t)&td->ietfd_type, 2);   /* Type */
                    777:        bp->rptr += 2;                                  /* Skip src */
                    778:        cnt -= sizeof(struct etherpup);
                    779: 
                    780:        /* Setup the data */
                    781:        if (cnt > 1500)                 /* test for too large packets */
                    782:                cnt = 1500;
                    783:        count = cnt;
                    784:        to = es->es_tbuffer[bufnum];
                    785:        while (cnt > 0 && bp != 0) {
                    786:                i = bp->wptr - bp->rptr;
                    787:                bcopy(bp->rptr, to, i);
                    788:                cnt -= i;
                    789:                to += i;
                    790:                nbp = bp->next;
                    791:                freeb(bp);
                    792:                bp = nbp;
                    793:        }
                    794: 
                    795:        if (count < 46)                 /* test for small packets */
                    796:                count = 46;
                    797: 
                    798:        /* flush remaining buffers, if any (too large packet: count > 1500) */
                    799:        while (bp) {
                    800:                nbp = bp->next;
                    801:                freeb(bp);
                    802:                bp = nbp;
                    803:        }
                    804: 
                    805:        /* Setup the buffer descriptor */
                    806:        tbd->ietbd_eof = 1;
                    807:        tbd->ietbd_next = 0;
                    808:        tbd->ietbd_buf = to_ieaddr(es, es->es_tbuffer[bufnum]);
                    809:        tbd->ietbd_cntlo = count & 0xFF;
                    810:        tbd->ietbd_cnthi = count >> 8;
                    811:        td->ietfd_tbd = to_ieoff(es, (caddr_t)tbd);
                    812:        td->ietfd_cmd = IE_TRANSMIT;
                    813:        iedocb(es, (struct iecb *)td);
                    814: out:
                    815:        iecustart(es);
                    816:        return;
                    817: }
                    818: 
                    819: /*
                    820:  * Set the control block area size
                    821:  */
                    822: iesetcbsize(es)
                    823:        register struct ie_softc *es;
                    824: {
                    825:        int tfds;       /* number of tfd's */
                    826:        int tfdsize;    /* cbsize for each tfd */
                    827:        int tbufsize;   /* cbsize for each tbuf */
                    828:        int rbufs;      /* number of rbuf's in cb area */
                    829:        int rbufsize;   /* cbsize for each rbuf */
                    830:        int rfds;       /* number of rfd's */
                    831:        int rfdsize;    /* cbsize for each rfd */
                    832:        int fixed;      /* fixed overhead, including slop */
                    833: 
                    834:        fixed = sizeof (struct iescp) + sizeof (struct ieiscp)
                    835:                + sizeof (struct iescb) + sizeof (struct ieconf)
                    836:                + 100;
                    837:        tfdsize = sizeof (struct ietfd) + sizeof (struct ietbd);
                    838:        tbufsize = sizeof (struct ieipack);
                    839:        rbufsize = sizeof (struct ieipack);
                    840:        rfdsize = sizeof (struct ierfd) + sizeof (struct ierbd);
                    841: 
                    842:        switch (es->es_type) {
                    843:        case IE_OB:
                    844:                tfds = NTRANSBUF;
                    845:                rbufs = (es->es_obmem - fixed - tfds * (tfdsize+tbufsize)) /
                    846:                        (rbufsize + rfdsize);
                    847:                break;
                    848:        case IE_MB:
                    849:                tfds = 50;              /* maximum if_snd */
                    850:                /* each rbuf eats into a 2K section of vmemsize */
                    851:                rbufs = min(NPOOL_RBD, (u_int)(es->es_vmemsize>>11));
                    852:                break;
                    853:        }
                    854:        rfds = rbufs;
                    855: 
                    856:        es->es_cbsize = fixed
                    857:                + tfds * tfdsize
                    858:                + rfds * rfdsize;
                    859: }
                    860: 
                    861: /*
                    862:  * Called by ieinit to (allocate and re)initialize rmap's
                    863:  * We need to be careful, since the board may be in use
                    864:  * (ieipacks loaned out, pages swapped)
                    865:  */
                    866: iedomaps(es)
                    867:        register struct ie_softc *es;
                    868: {
                    869:        int unit = es - ie_softc;
                    870: 
                    871:        iesetcbsize(es);
                    872:        bzero((caddr_t)iecbmap[unit], sizeof iecbmap[unit]);
                    873:        bzero((caddr_t)iememmap[unit], sizeof iememmap[unit]);
                    874:        es->es_cbhead = NULL;
                    875:        es->es_cbcbusy = NULL;
                    876:        iecbcinit(es);
                    877: 
                    878:        if (es->es_type == IE_OB) {
                    879:                int memall();
                    880:                caddr_t va;
                    881: 
                    882:                if (es->es_base == 0) {
                    883:                        va = wmemall(memall, es->es_obmem);
                    884:                        if (va == 0)
                    885:                                panic("ieattach: no memory");
                    886:                        es->es_base = va;
                    887:                }
                    888:                va = es->es_base;
                    889:                es->es_cbmap = &iecbmap[unit][0];
                    890:                es->es_memmap = es->es_cbmap;
                    891:                rminit(es->es_cbmap, (long)es->es_obmem,
                    892:                    (long)es->es_base, "iecb", IEMAPSIZ);
                    893:                es->es_memspace = (caddr_t)KERNELBASE;
                    894: #ifdef sun3
                    895:                /* use the page already set up by the prom monitor */
                    896:                es->es_scp = (struct iescp *)(IESCPADDR+es->es_memspace);
                    897: #else
                    898:                /*
                    899:                  * Remap the [preallocated] virtual page containing
                    900:                  * the SCP to make it point to the same physical
                    901:                  * location as va, so that we can muck with the
                    902:                  * control blocks using the address returned from
                    903:                  * memall, and the chip can locate the scp at its
                    904:                  * fixed address
                    905:                  * Cache note: since we can not, in general, enforce
                    906:                  * the cache antialiasing separation requirement, we
                    907:                  * would need to avoid caching this physical page
                    908:                 */
                    909:                {
                    910:                        struct pte dummypte;    /* for mapin to write on */
                    911:                        int paddr = getkpgmap(va) & PG_PFNUM;
                    912: 
                    913:                        mapin(&dummypte, (u_int)btop(IESCPADDR+
                    914:                            es->es_memspace), (u_int)paddr, 1, PG_V | PG_KW);
                    915:                        es->es_scp = (struct iescp *)escbpin(es, 
                    916:                            (long)sizeof (struct iescp),
                    917:                            (long)es->es_base + (IESCPADDR & PGOFSET));
                    918:                }
                    919: #endif sun3
                    920:        } else { /* IE_MB */
                    921:                register struct mie_device *mie = es->es_mie;
                    922:                struct miepg *pg;
                    923:                short *ap;
                    924:                int i;
                    925:                int a, vaddr, paddr;
                    926:                int firsttime = es->es_memspace == 0;
                    927: 
                    928:                if (firsttime) {
                    929:                        if ((a = rmalloc(kernelmap,(long)btoc(es->es_vmemsize)))
                    930:                              == 0) {
                    931:                                printf("ie%d: no kernelmap for ie memory\n",
                    932:                                    unit);
                    933:                                panic("iedomaps");
                    934:                        }
                    935:                        es->es_memspace = (caddr_t)kmxtob(a);
                    936:                }
                    937:                vaddr = (int)es->es_memspace;
                    938:                a = btokmx((struct pte *)vaddr);
                    939:                /* board's mem boundary to byte addr */
                    940:                paddr = mie->mie_mbmhi << 16;
                    941:                /* preserve pagetype bits and which megabyte its in (for VME) */
                    942:                es->es_paddr = getkpgmap((caddr_t)mie) & PG_PFNUM;
                    943:                es->es_paddr &= ~(0x100000/NBPG -1);
                    944:                es->es_paddr |= btop(paddr);
                    945:                mapin(&Usrptmap[a], (u_int)btop(vaddr), (u_int)es->es_paddr,
                    946:                        (int)btoc(es->es_vmemsize), PG_V | PG_KW);
                    947: 
                    948:                /* clear the board unless in use */
                    949:                if (firsttime) {
                    950:                        ap = (short *)mie->mie_pgmap;
                    951:                        for (i=0; i<IEVVSIZ; i++)       /* clears mp_p2mem */
                    952:                                *ap++ = 0;
                    953:                        for (i=0; i<IEPMEMSIZ/IEPAGSIZ; i++) {
                    954:                                mie->mie_pgmap[0].mp_pfnum = i;
                    955:                                bzero(es->es_memspace, IEPAGSIZ);
                    956:                        }
                    957:                        pg = &mie->mie_pgmap[0];
                    958:                        for (i=0; i<es->es_vmemsize/IEPAGSIZ; i++) {
                    959:                                pg->mp_swab = 1;
                    960:                                pg->mp_pfnum = i;
                    961:                                pg++;
                    962:                        }
                    963: 
                    964:                        /* use last onboard ie page for chip init */
                    965:                        /* (no need to reclaim, since beyond vmemsize) */
                    966:                        pg = &mie->mie_pgmap[IEVVSIZ-1];
                    967:                        pg->mp_swab = 1;
                    968:                        pg->mp_pfnum = 0;
                    969: 
                    970:                        /* patch potential powerup parity problem */
                    971:                        mie->mie_peack = 1;
                    972:                }
                    973: 
                    974:                es->es_base = es->es_memspace;
                    975:                es->es_cbmap = &iecbmap[unit][0];
                    976:                rminit(es->es_cbmap, (long)es->es_cbsize,
                    977:                    (long)es->es_base, "iecb", IEMAPSIZ);
                    978:                es->es_scp = (struct iescp *)escbpin(es, 
                    979:                        (long)sizeof (struct iescp),
                    980:                        (long)es->es_base + (IESCPADDR & (IEPAGSIZ-1)));
                    981:                es->es_memmap = &iememmap[unit][0];
                    982:                es->es_pgmap = &iepgmap[unit][0];
                    983:                /*
                    984:                 * if we have enough memory, create a page pool which
                    985:                 * can manipulated via if_memmap, say by ND
                    986:                 */
                    987:                if (es->es_vmemsize == 256*1024) {
                    988:                        rminit(es->es_memmap, (long)(128*1024-es->es_cbsize),
                    989:                            (long)(es->es_memspace+es->es_cbsize),
                    990:                            "iemem", IEMAPSIZ);
                    991:                        if (firsttime)
                    992:                                rminit(es->es_pgmap, (long)(128*1024),
                    993:                                    (long)(es->es_memspace+128*1024),
                    994:                                    "iepg", IEMAPSIZ);
                    995:                } else {
                    996:                        rminit(es->es_memmap,
                    997:                            (long)(es->es_vmemsize-es->es_cbsize), 
                    998:                            (long)(es->es_memspace+es->es_cbsize),
                    999:                            "iemem", IEMAPSIZ);
                   1000:                        rminit(es->es_pgmap, (long)0, (long)0,
                   1001:                            "iepg", IEMAPSIZ);
                   1002:                }
                   1003:        }
                   1004: }
                   1005: 
                   1006: /*
                   1007:  * Basic 82586 initialization
                   1008:  */
                   1009: int
                   1010: iechipinit(es)
                   1011:        register struct ie_softc *es;
                   1012: {
                   1013:        int unit = es - ie_softc;
                   1014:        struct ieiscp *iscp;
                   1015:        struct iescb *scb;
                   1016:        struct iecb *cb;
                   1017:        struct ieconf *ic;
                   1018:        int ok = 0;
                   1019:        int gotintr;
                   1020:        int i;
                   1021: #ifdef notdef
                   1022:        struct ietdr *tdr;
                   1023: #endif
                   1024: 
                   1025:        if (es->es_scp == 0) {
                   1026:                printf("ie%d: scp alloc failed\n", unit);
                   1027:                goto exit;
                   1028:        }
                   1029:        iscp = escballoc(es, struct ieiscp, 0);
                   1030:        if (iscp == 0) {
                   1031:                printf("ie%d: iscp alloc failed\n", unit);
                   1032:                goto exit;
                   1033:        }
                   1034:        scb = escballoc(es, struct iescb, 0);
                   1035:        if (scb == 0) {
                   1036:                printf("ie%d: scb alloc failed\n", unit);
                   1037:                goto exit;
                   1038:        }
                   1039:        es->es_scb = scb;
                   1040: 
                   1041: reset:
                   1042:        bzero((caddr_t)es->es_scp, sizeof (struct iescp));
                   1043:        es->es_scp->ie_iscp = to_ieaddr(es, (caddr_t)iscp);
                   1044:        bzero((caddr_t)iscp, sizeof (struct ieiscp));
                   1045:        iscp->ie_busy = 1;
                   1046:        iscp->ie_cbbase = to_ieaddr(es, es->es_base);
                   1047:        iscp->ie_scb = to_ieoff(es, (caddr_t)scb);
                   1048:        bzero((caddr_t)scb, sizeof (struct iescb));
                   1049:        scb->ie_magic = IEMAGIC;
                   1050:        /*
                   1051:         * Hardware reset the chip.  We make the interval from
                   1052:         * reset to initial channel attention as small as reasonable
                   1053:         * to reduce the risk of scribbling chips getting us.
                   1054:         */
                   1055:        switch (es->es_type) {
                   1056:        case IE_MB:
                   1057:                /* hardware reset already occurred in iechipreset */
                   1058:                break;
                   1059: 
                   1060:        case IE_OB:
                   1061:                es->es_obie->obie_noreset = 1;
                   1062:                DELAY(IEKLUDGE);                /* REQUIRED */
                   1063:                break;
                   1064:        }
                   1065:        ieca(es);
                   1066:        CDELAY(!iscp->ie_busy, IEDELAY);        /* ensure chip eats iscp */
                   1067:        CDELAY(scb->ie_cnr, IEDELAY);           /* ensure scb updated too */
                   1068:        gotintr = iewaitintr(es);               /* wait for interrupt */
                   1069:        if (iscp->ie_busy || !scb->ie_cnr || !gotintr) {
                   1070:                printf("ie%d: init failed:%s%s%s\n", unit,
                   1071:                    iscp->ie_busy?" iscp busy":"",
                   1072:                    !scb->ie_cnr ?" no cnr":"",
                   1073:                    !gotintr     ?" no intr":"");
                   1074:                goto exit;
                   1075:        }
                   1076:        if (scb->ie_cus != IECUS_IDLE ) {
                   1077:                printf("ie%d: cus not idle after reset\n", unit);
                   1078:                iechipreset(es);
                   1079:                goto reset;
                   1080:        }
                   1081: 
                   1082:        cb = escballoc(es, struct iecb, 1);
                   1083:        if (cb == NULL) {
                   1084:                printf("ie%d: cb alloc failed\n", unit);
                   1085:                goto exit;
                   1086:        }
                   1087:        bzero((caddr_t)cb, sizeof (struct iecb));
                   1088:        cb->ie_cmd = IE_DIAGNOSE;
                   1089:        iesimple(es, cb);
                   1090:        if (!cb->ie_ok) {
                   1091:                printf("ie%d: Intel 82586 failed diagnostics\n", unit);
                   1092:                escbfree(es, cb);
                   1093:                goto exit;
                   1094:        }
                   1095:        escbfree(es, cb);
                   1096: #ifdef notdef
                   1097:        /* skip, since hardware requires quiet net to work */
                   1098:        tdr = escballoc(es, struct ietdr, 1);
                   1099:        if (tdr == NULL) {
                   1100:                printf("ie%d: tdr alloc failed\n", unit);
                   1101:                goto exit;
                   1102:        }
                   1103:        bzero((caddr_t)tdr, sizeof (struct ietdr));
                   1104:        tdr->ietdr_cb.ie_cmd = IE_TDR;
                   1105:        iesimple(es, &tdr->ietdr_cb);
                   1106:        if (!tdr->ietdr_ok) {
                   1107: #define TDRCONST       12      /* approx 0.77c/10Mhz */
                   1108:                int dist = (tdr->ietdr_timhi<<8)+tdr->ietdr_timlo;
                   1109:                if (dist != 0x7FF)
                   1110:                        printf("ie%d: link not OK - distance = ~%dm\n",
                   1111:                                unit, TDRCONST*dist);
                   1112:                else
                   1113:                        printf("ie%d: link not OK\n", unit);
                   1114:                escbfree(es, tdr);
                   1115:                goto exit;
                   1116:        }
                   1117:        if (tdr->ietdr_xcvr) printf("ie%d: transceiver bad\n", unit);
                   1118:        if (tdr->ietdr_open) printf("ie%d: net not terminated\n", unit);
                   1119:        if (tdr->ietdr_shrt) printf("ie%d: net shorted\n", unit);
                   1120:        escbfree(es, tdr);
                   1121: #endif notdef
                   1122:        ic = escballoc(es, struct ieconf, 1);
                   1123:        if (ic == NULL) {
                   1124:                printf("ie%d: ic alloc failed\n", unit);
                   1125:                goto exit;
                   1126:        }
                   1127:        iedefaultconf(ic);
                   1128:        iesimple(es, &ic->ieconf_cb);
                   1129:        escbfree(es, ic);
                   1130:        for (i = 0; i < NTRANSBUF; i++) {
                   1131:                if ((es->es_tfd[i] = escballoc(es, struct ietfd, 0)) == NULL) {
                   1132:                        printf("ie%d: tfd alloc failed\n", unit);
                   1133:                        goto exit;
                   1134:                }
                   1135:                if ((es->es_tbd[i] = escballoc(es, struct ietbd, 0)) == NULL) {
                   1136:                        printf("ie%d: tbd alloc failed\n", unit);
                   1137:                        goto exit;
                   1138:                }
                   1139:                if ((es->es_tbuffer[i]=(caddr_t)esmemalloc(es, 1500)) ==NULL) {
                   1140:                        printf("ie%d: tbuffer alloc failed\n", unit);
                   1141:                        goto exit;
                   1142:                }
                   1143:                es->es_tfree |= (1 << i);
                   1144:        }
                   1145:        ok = 1;
                   1146: exit:
                   1147:        return (ok);
                   1148: }
                   1149: 
                   1150: /*
                   1151:  * called by ierustart to create the receiver buffer list
                   1152:  */
                   1153: iegetrbufs(es)
                   1154:        register struct ie_softc *es;
                   1155: {
                   1156:        caddr_t addr;
                   1157:        int count, avail;
                   1158:        register int page, last;
                   1159:        register struct ieipack *iep;
                   1160: 
                   1161:        es->es_iepavail = NULL;
                   1162:        if (es->es_type == IE_OB) {
                   1163:                last = (es->es_obmem-es->es_cbsize) /
                   1164:                        (sizeof (struct ieipack)) - NTRANSBUF;
                   1165:                for (count = 0; count < last; count++) {
                   1166:                        iep = (struct ieipack *)esmemalloc(es,
                   1167:                                sizeof (struct ieipack));
                   1168:                        if (iep == 0)
                   1169:                                break;
                   1170:                        iep->iep_es = es;
                   1171:                        iep->iep_next = es->es_iepavail;
                   1172:                        es->es_iepavail = iep;
                   1173:                }
                   1174:                avail = count;
                   1175:        } else { /* IE_MB */
                   1176:                count = NPOOL_RBD;
                   1177:                /* XXX not really, since there could be page pool */
                   1178:                last = es->es_vmemsize >> IEPAGSHIFT;
                   1179:                /* 2 pages for xmit (vice receive) buffer */
                   1180:                page = iepages(es->es_cbsize) + 2;
                   1181:                for (;  count > 0 && page < last; page++) {
                   1182:                        addr = es->es_memspace + page*IEPAGSIZ;
                   1183:                        addr += IEPAGSIZ - (IPACKOVH + OPTHDRSIZ);
                   1184:                        if (!esmempin(es, sizeof (struct ieipack), (int)addr))
                   1185:                                continue;
                   1186:                        count--;
                   1187:                        iep = (struct ieipack *)addr;
                   1188:                        iep->iep_es = es;
                   1189:                        iep->iep_next = es->es_iepavail;
                   1190:                        es->es_iepavail = iep;
                   1191:                }
                   1192:                avail = NPOOL_RBD - count;
                   1193:        }
                   1194: 
                   1195:        return (avail);
                   1196: }
                   1197: 
                   1198: /*
                   1199:  * Initialize and start the Receive Unit
                   1200:  */
                   1201: ierustart(es)
                   1202:        register struct ie_softc *es;
                   1203: {
                   1204:        int unit = es - ie_softc;
                   1205:        register struct ierbd *rbd;
                   1206:        register struct ierfd *rfd;
                   1207:        register struct iescb *scb;
                   1208:        register struct ieipack *iep;
                   1209:        register int i, nrfd, ninit_rbd;
                   1210: 
                   1211:        ninit_rbd = iegetrbufs(es);
                   1212:        es->es_rbdhead = NULL;
                   1213:        for (i = 0; i < ninit_rbd; i++) {
                   1214:                if ((iep = es->es_iepavail) == NULL)
                   1215:                         break;
                   1216:                 rbd = escballoc(es, struct ierbd, 0);
                   1217:                 if (rbd == NULL)
                   1218:                         break;
                   1219:                 es->es_iepavail = iep->iep_next;
                   1220:                *(short *)rbd = 0;
                   1221:                if (es->es_rbdhead) {
                   1222:                        rbd->ierbd_next = to_ieoff(es, (caddr_t)es->es_rbdhead);
                   1223:                        rbd->ierbd_el = 0;
                   1224:                } else {
                   1225:                        es->es_rbdtail = rbd;
                   1226:                        rbd->ierbd_next = 0;
                   1227:                        rbd->ierbd_el = 1;
                   1228:                }
                   1229:                es->es_rbdhead = rbd;
                   1230:                rbd->ierbd_buf = to_ieaddr(es, iep->iep_data);
                   1231:                rbd->ierbd_sizehi = 1500 >> 8;
                   1232:                rbd->ierbd_sizelo = 1500 & 0xFF;
                   1233:                rbd->ierbd_iep = iep;
                   1234:        }
                   1235:        /*
                   1236:         * We allocate one fewer RFD than RBD to
                   1237:         * avoid a suspected microcode bug in the chip
                   1238:         */
                   1239:        nrfd = i-1;
                   1240:        es->es_rbdtail->ierbd_next = to_ieoff(es, (caddr_t)es->es_rbdhead);
                   1241:        es->es_rfdhead = NULL;
                   1242:        for (i=0; i<nrfd; i++) {
                   1243:                rfd = escballoc(es, struct ierfd, 0);
                   1244:                if (rfd == NULL) {
                   1245:                        break;
                   1246:                }
                   1247:                *(short *)rfd = 0;
                   1248:                if (es->es_rfdhead) {
                   1249:                        rfd->ierfd_next = to_ieoff(es, (caddr_t)es->es_rfdhead);
                   1250:                        rfd->ierfd_el = 0;
                   1251:                } else {
                   1252:                        es->es_rfdtail = rfd;
                   1253:                        rfd->ierfd_next = 0;
                   1254:                        rfd->ierfd_el = 1;
                   1255:                }
                   1256:                es->es_rfdhead = rfd;
                   1257:                rfd->ierfd_susp = 0;
                   1258:                rfd->ierfd_rbd = IENORBD;
                   1259:        }
                   1260:        if (i != nrfd)
                   1261:                printf("ie%d: fewer RFD's were allocated than expected\n",
                   1262:                    unit);
                   1263:        es->es_rfdtail->ierfd_next = to_ieoff(es, (caddr_t)es->es_rfdhead);
                   1264:        rfd = es->es_rfdhead;
                   1265:        rfd->ierfd_rbd = to_ieoff(es, (caddr_t)rbd);
                   1266:        scb = es->es_scb;
                   1267:        if (scb->ie_rus != IERUS_IDLE) {
                   1268:                printf("ie%d: RU not idle??\n", unit);
                   1269:                iestat(es);
                   1270:                iechkcca(scb);
                   1271:                scb->ie_cmd = IECMD_RU_ABORT;
                   1272:                ieca(es);
                   1273:        }
                   1274:        iechkcca(scb);
                   1275:        scb->ie_rfa = to_ieoff(es, (caddr_t)rfd);
                   1276:        scb->ie_cmd = IECMD_RU_START;
                   1277:        ieca(es);
                   1278:        CDELAY(scb->ie_rus == IERUS_READY, IEDELAY);
                   1279:        if (scb->ie_rus != IERUS_READY)
                   1280:                printf("ie%d: RU did not become ready\n", unit);
                   1281: }
                   1282: 
                   1283: /*
                   1284:  * Put a CB on the CBL
                   1285:  */
                   1286: iedocb(es, cb)
                   1287:        register struct ie_softc *es;
                   1288:        register struct iecb *cb;
                   1289: {
                   1290:        int s = splie();
                   1291: 
                   1292:        *(short *)cb = 0;       /* clear status bits */
                   1293:         cb->ie_susp = 0;        /* clear suspend bit */
                   1294:        cb->ie_el = 1;          /* will be reset in iecustart */
                   1295:        cb->ie_intr = 1;
                   1296:        cb->ie_next = 0;
                   1297:        if (es->es_cbhead) {
                   1298:                es->es_cbtail->ie_next = to_ieoff(es, (caddr_t)cb);
                   1299:                es->es_cbtail = cb;
                   1300:        } else {
                   1301:                es->es_cbhead = es->es_cbtail = cb;
                   1302:        }
                   1303:        (void) splx(s);
                   1304: }
                   1305: 
                   1306: /*
                   1307:  * Process completed CBs, reclaiming specified storage.
                   1308:  * Allocator is responsible for reclaiming other storage.
                   1309:  * Called by iecustart at splie.
                   1310:  * Called by iecbdone at splie or hardware level 3.
                   1311:  */
                   1312: iecuclean(es)
                   1313:        register struct ie_softc *es;
                   1314: {
                   1315:        register struct iecb *cb;
                   1316:                
                   1317:        while ((cb = es->es_cbhead) && cb->ie_done) {
                   1318:                if (cb->ie_next)
                   1319:                        es->es_cbhead = (struct iecb *)from_ieoff(es,
                   1320:                                                        (ieoff_t)cb->ie_next);
                   1321:                else
                   1322:                        es->es_cbhead = NULL;
                   1323:                switch (cb->ie_cmd) {
                   1324:                case IE_TRANSMIT:
                   1325:                        iexmitdone(es, (struct ietfd *)cb);
                   1326:                        break;
                   1327:                default:
                   1328:                        if (!es->es_simple)
                   1329:                                printf("ie%d: unknown cmd %x done\n",
                   1330:                                        es-ie_softc, cb->ie_cmd);
                   1331:                        break;
                   1332:                }
                   1333:        }
                   1334: }
                   1335: 
                   1336: /*
                   1337:  * Start the CU with the current CBL
                   1338:  */
                   1339: iecustart(es)
                   1340:        register struct ie_softc *es;
                   1341: {
                   1342:        register struct iecb *cb;
                   1343:        register struct iescb *scb = es->es_scb;
                   1344:        int s = splie();
                   1345:                
                   1346:        iechkcca(scb);
                   1347:        if (es->es_cbhead == NULL ||
                   1348:            scb->ie_cus == IECUS_READY) {       /* still going */
                   1349:                (void) splx(s);
                   1350:                return;
                   1351:        }
                   1352:        iecuclean(es);
                   1353:        /* link remaining CBs into continuous list */
                   1354:        if ((cb = es->es_cbhead) == NULL) {
                   1355:                (void) splx(s);
                   1356:                return;
                   1357:        }
                   1358:        while (cb && cb->ie_next) {
                   1359:                cb->ie_el = 0;
                   1360:                cb = (struct iecb *)from_ieoff(es, (ieoff_t)cb->ie_next);
                   1361:        }
                   1362:        /* start CU */
                   1363:        scb->ie_cbl = to_ieoff(es, (caddr_t)es->es_cbhead);
                   1364:        scb->ie_cmd = IECMD_CU_START;
                   1365:        ieca(es);
                   1366:        (void) splx(s);
                   1367: }
                   1368: 
                   1369: /*
                   1370:  * Clean up and restart the CBs on the CBL
                   1371:  * Called by ieintr at hardware level 3.
                   1372:  * Called by iesimple at splie.
                   1373:  */
                   1374: iecbdone(es)
                   1375:        register struct ie_softc *es;
                   1376: {
                   1377: 
                   1378:        iecuclean(es);
                   1379:        /* generate more CBs */
                   1380:        iestartout(es - ie_softc);
                   1381: }
                   1382: 
                   1383: /*
                   1384:  * Do the command simply.
                   1385:  * Attempted sleep/wakeup calls, but it refused to work.
                   1386:  */
                   1387: iesimple(es, cb)
                   1388:        register struct ie_softc *es;
                   1389:        register struct iecb *cb;
                   1390: {
                   1391:        register struct iescb *scb = es->es_scb;
                   1392:        int s, cmd = 0;
                   1393: 
                   1394:        es->es_simple++;
                   1395:        iedocb(es, cb);
                   1396:        iecustart(es);
                   1397:        CDELAY(cb->ie_done, IEDELAY);
                   1398:        if (!cb->ie_done) {
                   1399:                iestat(es);
                   1400:                panic("iesimple");
                   1401:        }
                   1402:        s = splie();
                   1403:        iechkcca(scb);
                   1404:        if (scb->ie_cx)
                   1405:                cmd |= IECMD_ACK_CX;
                   1406:        if (scb->ie_cnr)
                   1407:                cmd |= IECMD_ACK_CNR;
                   1408:        scb->ie_cmd = cmd;
                   1409:        ieca(es);
                   1410:        if (cmd & (IECMD_ACK_CNR|IECMD_ACK_CX))
                   1411:                iecbdone(es);
                   1412:        es->es_simple--;
                   1413:        (void) splx(s);
                   1414: }
                   1415: 
                   1416: /*
                   1417:  * Return chip's idea of given address or 0 if not chip accessible
                   1418:  */
                   1419: ieaddr(es, cp)
                   1420:        register struct ie_softc *es;
                   1421:        caddr_t cp;
                   1422: {
                   1423:        int pte;
                   1424: 
                   1425:        if (es->es_type == IE_OB) {
                   1426:                /* onboard ie may only reference obmem */
                   1427:                if ((getkpgmap(cp) & PGT_MASK) != PGT_OBMEM)
                   1428:                        cp = (caddr_t)0;
                   1429: #ifdef sun3
                   1430:                else if (cp < es->es_memspace)
                   1431:                        cp = (caddr_t)0;
                   1432:                else
                   1433:                        cp -= (u_long)es->es_memspace;
                   1434: #endif sun3
                   1435:                return ((int)cp);
                   1436:        }
                   1437:        pte = getkpgmap(cp) & PG_PFNUM;
                   1438:        if (pte >= es->es_paddr && pte < es->es_paddr + btoc(es->es_vmemsize))
                   1439:                return ((pte - es->es_paddr) << BSHIFT(0)) + ((int)cp & CLOFSET);
                   1440:        return (0);
                   1441: }
                   1442: 
                   1443: /*
                   1444:  * Check Control Command Acceptance by 82586
                   1445:  */
                   1446: iechkcca(scb)
                   1447:        register struct iescb *scb;
                   1448: {
                   1449:        register i;
                   1450: 
                   1451:        for (i=0; i < IEDELAY; i++) {
                   1452:                if (scb->ie_magic != IEMAGIC)
                   1453:                        panic("ie: scb overwritten");
                   1454:                if (scb->ie_cmd == 0)
                   1455:                        break;
                   1456:        }
                   1457:        if (i >= IEDELAY) {
                   1458:                printf("ie: cmd not accepted\n");
                   1459:                panic("iechkcca");
                   1460:        }
                   1461: }
                   1462: 
                   1463: /*
                   1464:  * The control block caching code to bypass rmalloc/rmfree.
                   1465:  * It also allows us to check allocated lengths, as well
                   1466:  * as aiding instrumentation for verification and tuning.
                   1467:  * We have two sizes, small and large.
                   1468:  * If the request exceeds the small threshold, we allocate
                   1469:  * the larger block.
                   1470:  */
                   1471: 
                   1472: #define lo     es->es_cbc_lo
                   1473: #define hi     es->es_cbc_hi
                   1474: #define cache  es->es_cbcache
                   1475: #define ovfl   es->es_cbc_ovfl
                   1476: #define small  iecbcsmall
                   1477: #define large  iecbclarge
                   1478: #define head   es->es_cbchain.next
                   1479: #define chain  es->es_cbchain
                   1480: 
                   1481: /*
                   1482:  * Initialize the control block cache
                   1483:  */
                   1484: iecbcinit(es)
                   1485:        register struct ie_softc *es;
                   1486: {
                   1487:        if (es->es_cbcbusy)
                   1488:                iecbcflush(es);
                   1489:        lo = -1;
                   1490:        hi = CBCACHESIZ;
                   1491:        small = sizeof (struct ietbd);
                   1492:        large = sizeof (struct ietfd);
                   1493: }
                   1494: 
                   1495: /*
                   1496:  * cached is a flag used to indicate that the block must be
                   1497:  * cached, as it will be freed (for reallocation.)
                   1498:  */
                   1499: long
                   1500: escbget(es, len0, cached)
                   1501:        register struct ie_softc *es;
                   1502:        int len0;
                   1503:        int cached;
                   1504: {
                   1505:        long result;
                   1506:        int len = rndtoeven(len0);
                   1507:        if (!cached)
                   1508:                result = (rmalloc(es->es_cbmap, (long)len));
                   1509:        else if (len <= small)
                   1510:                if (lo > -1)
                   1511:                        result = (cache[lo--]);
                   1512:                else
                   1513:                        result = (rmalloc(es->es_cbmap, (long)small));
                   1514:        else if (len <= large)
                   1515:                if (hi < CBCACHESIZ)
                   1516:                        result = (cache[hi++]);
                   1517:                else
                   1518:                        result = (rmalloc(es->es_cbmap, (long)large));
                   1519:        else
                   1520:                panic ("escbget");      /* len too large */
                   1521: 
                   1522:        if (result == 0 && es->es_cbcbusy) {
                   1523:                iecbcflush(es);
                   1524:                result = escbget(es, len0, cached);
                   1525:        }
                   1526:        return (result);
                   1527: }
                   1528: 
                   1529: /*
                   1530:  * flush the cb cache
                   1531:  */
                   1532: iecbcflush(es)
                   1533:        struct ie_softc *es;
                   1534: {
                   1535:        printf("WARNING: ie%d: flushing cb cache\n", es - ie_softc);
                   1536:        while (lo > -1)
                   1537:                rmfree(es->es_cbmap, (long)small, (long)cache[lo--]);
                   1538:        while (hi < CBCACHESIZ)
                   1539:                rmfree(es->es_cbmap, (long)large, (long)cache[hi++]);
                   1540:        es->es_cbcbusy = 0;
                   1541: }
                   1542: 
                   1543: long
                   1544: escbput(es, len, ptr)
                   1545:        register struct ie_softc *es;
                   1546:        int len;
                   1547:        long ptr;
                   1548: {
                   1549:        int overflow = 0;
                   1550: 
                   1551:        es->es_cbcbusy = 1;
                   1552:        len = rndtoeven(len);
                   1553:        if (len <= small)
                   1554:                if (lo < hi - 1)
                   1555:                        cache[++lo] = ptr;
                   1556:                else {
                   1557:                        overflow++;
                   1558:                        rmfree(es->es_cbmap, (long)small, (long)ptr); 
                   1559:                }
                   1560:        else if (len <= large)
                   1561:                if (hi > lo + 1)
                   1562:                        cache[--hi] = ptr;
                   1563:                else {
                   1564:                        overflow++;
                   1565:                        rmfree(es->es_cbmap, (long)large, (long)ptr);
                   1566:                }
                   1567:        else
                   1568:                panic("escbput");
                   1569: 
                   1570:        if (overflow) {
                   1571:                ovfl++;
                   1572:                if ((ovfl & OVFLWARNMASK) == 0) {
                   1573:                        ovfl = 0;
                   1574:                        printf("ie%d: cache overflowed\n", es - ie_softc);
                   1575:                }
                   1576:        }
                   1577: }
                   1578: 
                   1579: #undef lo
                   1580: #undef hi
                   1581: #undef cache
                   1582: #undef ovfl
                   1583: #undef small
                   1584: #undef large
                   1585: 
                   1586: int iefifolim = 12;
                   1587: /*
                   1588:  * Set default configuration parameters
                   1589:  */
                   1590: iedefaultconf(ic)
                   1591:        register struct ieconf *ic;
                   1592: {
                   1593:        bzero((caddr_t)ic, sizeof (struct ieconf));
                   1594:        ic->ieconf_cb.ie_cmd = IE_CONFIG;
                   1595:        ic->ieconf_bytes = 12;
                   1596:        ic->ieconf_fifolim = iefifolim;
                   1597:        ic->ieconf_pream = 2;           /* 8 byte preamble */
                   1598:        ic->ieconf_alen = 6;
                   1599:        ic->ieconf_acloc = 0;
                   1600:        ic->ieconf_space = 96;
                   1601:        ic->ieconf_slttmh = 512 >> 8;
                   1602:        ic->ieconf_minfrm = 64;
                   1603:        ic->ieconf_retry = 15;
                   1604:        ic->ieconf_crfilt = 3;
                   1605: }
                   1606: 
                   1607: iestat(es)
                   1608:        struct ie_softc *es;
                   1609: {
                   1610:        register struct iescb *scb = es->es_scb;
                   1611:        static char *cus[] = { "idle", "suspended", "ready", "<3>",
                   1612:                                "<4>", "<5>", "<6>", "<7>" };
                   1613:        static char *rus[] = { "idle", "suspended", "no resources",
                   1614:                                "<3>", "ready", "<5>", "<6>", "<7>" };
                   1615: 
                   1616:        printf("ie%d: scb: ", es - ie_softc);
                   1617:        if (scb->ie_cx) printf("cx ");
                   1618:        if (scb->ie_fr) printf("fr ");
                   1619:        if (scb->ie_cnr) printf("cnr ");
                   1620:        if (scb->ie_rnr) printf("rnr ");
                   1621:        printf("cus=%s ", cus[scb->ie_cus]);
                   1622:        printf("rus=%s\n", rus[scb->ie_rus]);
                   1623:        printf("cbl=0x%x rfa=0x%x crc=0x%x aln=0x%x rsc=0x%x ovrn=0x%x\n",
                   1624:                scb->ie_cbl, scb->ie_rfa,
                   1625:                scb->ie_crcerrs, scb->ie_alnerrs, scb->ie_rscerrs,
                   1626:                scb->ie_ovrnerrs);
                   1627:        if (scb->ie_cmd) printf("cmd=0x%x\n", scb->ie_cmd & 0xFFFF);
                   1628: }
                   1629: 
                   1630: /*
                   1631:  * Parity error! Scan entire memory for errors
                   1632:  */
                   1633: ieparity(es)
                   1634:        register struct ie_softc *es;
                   1635: {
                   1636:        register struct mie_device *mie = es->es_mie;
                   1637:        register u_short *s, *e, x;
                   1638: 
                   1639:        printf("ie%d: parity error src=%d byte=%d addr=%x\n", es-ie_softc,
                   1640:                mie->mie_pesrc, mie->mie_pebyte, mie->mie_erraddr);
                   1641:        mie->mie_peack = 1;
                   1642:        s = (u_short *)es->es_memspace;
                   1643:        e = (u_short *)(es->es_memspace + es->es_vmemsize);
                   1644:        printf("scanning...\n");
                   1645:        while (s < e) {
                   1646:                x = *s;
                   1647: #ifdef lint
                   1648:                x = x;
                   1649: #endif
                   1650:                if (mie->mie_pe) {
                   1651:                        printf("off=%x src=%d byte=%d addr=%x\n", 
                   1652:                                (int)s - (int)es->es_memspace,
                   1653:                                mie->mie_pesrc, mie->mie_pebyte,
                   1654:                                mie->mie_erraddr);
                   1655:                        mie->mie_peack = 1;
                   1656:                }
                   1657:                s++;
                   1658:        }
                   1659:        printf("done\n");
                   1660: }
                   1661: 
                   1662: /*
                   1663:  * Activate the channel attention line
                   1664:  */
                   1665: ieca(es)
                   1666:        register struct ie_softc *es;
                   1667: {
                   1668:        if (es->es_type == IE_MB) {
                   1669:                es->es_mie->mie_ca = 1;
                   1670:                es->es_mie->mie_ca = 0;
                   1671:        } else {
                   1672:                es->es_obie->obie_ca = 1;
                   1673:                es->es_obie->obie_ca = 0;
                   1674:        }
                   1675: }
                   1676: 
                   1677: /*
                   1678:  * Wait for an interrupt and relay results
                   1679:  */
                   1680: int
                   1681: iewaitintr(es)
                   1682:        register struct ie_softc *es;
                   1683: {
                   1684:        register struct obie_device *obie = es->es_obie;
                   1685:        register struct mie_device *mie = es->es_mie;
                   1686:        int ok;
                   1687: 
                   1688:        switch (es->es_type) {
                   1689:        case IE_OB:
                   1690:                CDELAY(obie->obie_intr, IEDELAY);
                   1691:                ok = obie->obie_intr;
                   1692:                break;
                   1693: 
                   1694:        case IE_MB:
                   1695:                CDELAY(mie->mie_intr, IEDELAY);
                   1696:                ok = mie->mie_intr;
                   1697:                break;
                   1698:        }
                   1699:        return (ok);
                   1700: }
                   1701: 
                   1702: /*
                   1703:  * Cut the chip out of the loop and halt it by starting the reset cycle.
                   1704:  * For IE_MB, we must enable pagemaps, hence we complete the reset cycle.
                   1705:  */
                   1706: iechipreset(es)
                   1707:        register struct ie_softc *es;
                   1708: {
                   1709: 
                   1710:        switch (es->es_type) {
                   1711:        case IE_MB:
                   1712:                es->es_mie->mie_reset = 1;
                   1713:                DELAY(IEKLUDGE);                        /* REQUIRED */
                   1714:                *(char *)&es->es_mie->mie_status = 0;   /* power on reset */
                   1715:                break;
                   1716: 
                   1717:        case IE_OB:
                   1718:                *(char *)es->es_obie = 0;               /* power on reset */
                   1719:                break;
                   1720: 
                   1721:        default:
                   1722:                panic("iechipreset");
                   1723:        }
                   1724: }
                   1725: 
                   1726: /*
                   1727:  * Splice the chip into the loop
                   1728:  */
                   1729: iesplice(es)
                   1730:        register struct ie_softc *es;
                   1731: {
                   1732:        switch (es->es_type) {
                   1733:        case IE_MB:
                   1734:                es->es_mie->mie_ie = 1;         /* enable chip interrupts */
                   1735:                es->es_mie->mie_pie = 1;        /* enable parity interrupts */
                   1736:                es->es_mie->mie_noloop = 1;     /* enable cable */
                   1737:                break;
                   1738: 
                   1739:        case IE_OB:
                   1740:                es->es_obie->obie_ie = 1;       /* enable interrupts */
                   1741:                es->es_obie->obie_noloop = 1;   /* enable cable */
                   1742:                break;
                   1743:        }
                   1744: }
                   1745: 
                   1746: /* 
                   1747:  * Change 68000 address to Intel 24-bit address.
                   1748:  * We take advantage of the fact that all 82586 blocks with 24-bit
                   1749:  * addresses have an adjacent unused 8-bit field, and store 32 bits.
                   1750:  */
                   1751: ieaddr_t
                   1752: to_ieaddr(es, cp)
                   1753:        struct ie_softc *es;
                   1754:        caddr_t cp;
                   1755: {
                   1756:        union {
                   1757:                int     n;
                   1758:                char    c[4];
                   1759:        } a, b;
                   1760: 
                   1761:        a.n = ieaddr(es, cp);           /* necessary for double mapping */
                   1762:        b.c[0] = a.c[3];
                   1763:        b.c[1] = a.c[2];
                   1764:        b.c[2] = a.c[1];
                   1765:        b.c[3] = 0;
                   1766:        return (b.n);
                   1767: }
                   1768: 
                   1769: caddr_t
                   1770: from_ieaddr(es, n)
                   1771:        struct ie_softc *es;
                   1772:        ieaddr_t n;
                   1773: {
                   1774:        union {
                   1775:                int     n;
                   1776:                char    c[4];
                   1777:        } a, b;
                   1778: 
                   1779:        a.n = n;
                   1780:        b.c[0] = 0;
                   1781:        b.c[1] = a.c[2];
                   1782:        b.c[2] = a.c[1];
                   1783:        b.c[3] = a.c[0];
                   1784:        return (es->es_memspace + b.n);
                   1785: }
                   1786: 
                   1787: ieoff_t
                   1788: to_ieoff(es, addr)
                   1789:        register struct ie_softc *es;
                   1790:        caddr_t addr;
                   1791: {
1.1.1.2 ! root     1792:        union xxx {
1.1       root     1793:                ieoff_t s;
                   1794:                char    c[2];
                   1795:        } a, b;
                   1796: 
                   1797:        a.s = (ieoff_t)(addr - es->es_base);
                   1798:        b.c[0] = a.c[1];
                   1799:        b.c[1] = a.c[0];
                   1800:        return (b.s);
                   1801: }
                   1802: 
                   1803: caddr_t
                   1804: from_ieoff(es, off)
                   1805:        register struct ie_softc *es;
                   1806:        ieoff_t off;
                   1807: {
                   1808:        union {
                   1809:                ieoff_t s;
                   1810:                char    c[2];
                   1811:        } a, b;
                   1812: 
                   1813:        a.s = off;
                   1814:        b.c[0] = a.c[1];
                   1815:        b.c[1] = a.c[0];
                   1816:        return (es->es_base + b.s);
                   1817: }
                   1818: 
                   1819: ieint_t
                   1820: to_ieint(n)
                   1821:        ieint_t n;
                   1822: {
                   1823:        union {
                   1824:                ieint_t s;
                   1825:                char    c[2];
                   1826:        } a, b;
                   1827: 
                   1828:        a.s = n;
                   1829:        b.c[0] = a.c[1];
                   1830:        b.c[1] = a.c[0];
                   1831:        return (b.s);
                   1832: }
                   1833: #endif NIE > 0

unix.superglobalmegacorp.com

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