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

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