Annotation of lucent/sys/src/boot/pc/f002808, revision 1.1.1.1

1.1       root        1: /*
                      2:  * National Semiconductor DP8390
                      3:  * and SMC 83C90
                      4:  * Network Interface Controller.
                      5:  */
                      6: #include "u.h"
                      7: #include "lib.h"
                      8: #include "mem.h"
                      9: #include "dat.h"
                     10: #include "fns.h"
                     11: #include "io.h"
                     12: 
                     13: #include "ether.h"
                     14: 
                     15: enum {
                     16:        Cr              = 0x00,         /* command register, all pages */
                     17: 
                     18:        Stp             = 0x01,         /* stop */
                     19:        Sta             = 0x02,         /* start */
                     20:        Txp             = 0x04,         /* transmit packet */
                     21:        RDMAread        = (1<<3),       /* remote DMA read */
                     22:        RDMAwrite       = (2<<3),       /* remote DMA write */
                     23:        RDMAsend        = (3<<3),       /* remote DMA send packet */
                     24:        RDMAabort       = (4<<3),       /* abort/complete remote DMA */
                     25:        Ps0             = 0x40,         /* page select */
                     26:        Ps1             = 0x80,         /* page select */
                     27:        Page0           = 0x00,
                     28:        Page1           = Ps0,
                     29:        Page2           = Ps1,
                     30: };
                     31: 
                     32: enum {                                 /* Page 0, read */
                     33:        Clda0           = 0x01,         /* current local DMA address 0 */
                     34:        Clda1           = 0x02,         /* current local DMA address 1 */
                     35:        Bnry            = 0x03,         /* boundary pointer (R/W) */
                     36:        Tsr             = 0x04,         /* transmit status register */
                     37:        Ncr             = 0x05,         /* number of collisions register */
                     38:        Fifo            = 0x06,         /* FIFO */
                     39:        Isr             = 0x07,         /* interrupt status register (R/W) */
                     40:        Crda0           = 0x08,         /* current remote DMA address 0 */
                     41:        Crda1           = 0x09,         /* current remote DMA address 1 */
                     42:        Rsr             = 0x0C,         /* receive status register */
                     43:        Cntr0           = 0x0D,         /* frame alignment errors */
                     44:        Cntr1           = 0x0E,         /* CRC errors */
                     45:        Cntr2           = 0x0F,         /* missed packet errors */
                     46: };
                     47: 
                     48: enum {                                 /* Page 0, write */
                     49:        Pstart          = 0x01,         /* page start register */
                     50:        Pstop           = 0x02,         /* page stop register */
                     51:        Tpsr            = 0x04,         /* transmit page start address */
                     52:        Tbcr0           = 0x05,         /* transmit byte count register 0 */
                     53:        Tbcr1           = 0x06,         /* transmit byte count register 1 */
                     54:        Rsar0           = 0x08,         /* remote start address register 0 */
                     55:        Rsar1           = 0x09,         /* remote start address register 1 */
                     56:        Rbcr0           = 0x0A,         /* remote byte count register 0 */
                     57:        Rbcr1           = 0x0B,         /* remote byte count register 1 */
                     58:        Rcr             = 0x0C,         /* receive configuration register */
                     59:        Tcr             = 0x0D,         /* transmit configuration register */
                     60:        Dcr             = 0x0E,         /* data configuration register */
                     61:        Imr             = 0x0F,         /* interrupt mask */
                     62: };
                     63: 
                     64: enum {                                 /* Page 1, read/write */
                     65:        Par0            = 0x01,         /* physical address register 0 */
                     66:        Curr            = 0x07,         /* current page register */
                     67:        Mar0            = 0x08,         /* multicast address register 0 */
                     68: };
                     69: 
                     70: enum {                                 /* Interrupt Status Register */
                     71:        Prx             = 0x01,         /* packet received */
                     72:        Ptx             = 0x02,         /* packet transmitted */
                     73:        Rxe             = 0x04,         /* receive error */
                     74:        Txe             = 0x08,         /* transmit error */
                     75:        Ovw             = 0x10,         /* overwrite warning */
                     76:        Cnt             = 0x20,         /* counter overflow */
                     77:        Rdc             = 0x40,         /* remote DMA complete */
                     78:        Rst             = 0x80,         /* reset status */
                     79: };
                     80: 
                     81: enum {                                 /* Interrupt Mask Register */
                     82:        Prxe            = 0x01,         /* packet received interrupt enable */
                     83:        Ptxe            = 0x02,         /* packet transmitted interrupt enable */
                     84:        Rxee            = 0x04,         /* receive error interrupt enable */
                     85:        Txee            = 0x08,         /* transmit error interrupt enable */
                     86:        Ovwe            = 0x10,         /* overwrite warning interrupt enable */
                     87:        Cnte            = 0x20,         /* counter overflow interrupt enable */
                     88:        Rdce            = 0x40,         /* DMA complete interrupt enable */
                     89: };
                     90: 
                     91: enum {                                 /* Data Configuration register */
                     92:        Wts             = 0x01,         /* word transfer select */
                     93:        Bos             = 0x02,         /* byte order select */
                     94:        Las             = 0x04,         /* long address select */
                     95:        Ls              = 0x08,         /* loopback select */
                     96:        Arm             = 0x10,         /* auto-initialise remote */
                     97:        Ft1             = (0x00<<5),    /* FIFO threshhold select 1 byte/word */
                     98:        Ft2             = (0x01<<5),    /* FIFO threshhold select 2 bytes/words */
                     99:        Ft4             = (0x02<<5),    /* FIFO threshhold select 4 bytes/words */
                    100:        Ft6             = (0x03<<5),    /* FIFO threshhold select 6 bytes/words */
                    101: };
                    102: 
                    103: enum {                                 /* Transmit Configuration Register */
                    104:        Crc             = 0x01,         /* inhibit CRC */
                    105:        Lb              = 0x02,         /* internal loopback */
                    106:        Atd             = 0x08,         /* auto transmit disable */
                    107:        Ofst            = 0x10,         /* collision offset enable */
                    108: };
                    109: 
                    110: enum {                                 /* Transmit Status Register */
                    111:        Ptxok           = 0x01,         /* packet transmitted */
                    112:        Col             = 0x04,         /* transmit collided */
                    113:        Abt             = 0x08,         /* tranmit aborted */
                    114:        Crs             = 0x10,         /* carrier sense lost */
                    115:        Fu              = 0x20,         /* FIFO underrun */
                    116:        Cdh             = 0x40,         /* CD heartbeat */
                    117:        Owc             = 0x80,         /* out of window collision */
                    118: };
                    119: 
                    120: enum {                                 /* Receive Configuration Register */
                    121:        Sep             = 0x01,         /* save errored packets */
                    122:        Ar              = 0x02,         /* accept runt packets */
                    123:        Ab              = 0x04,         /* accept broadcast */
                    124:        Am              = 0x08,         /* accept multicast */
                    125:        Pro             = 0x10,         /* promiscuous physical */
                    126:        Mon             = 0x20,         /* monitor mode */
                    127: };
                    128: 
                    129: enum {                                 /* Receive Status Register */
                    130:        Prxok           = 0x01,         /* packet received intact */
                    131:        Crce            = 0x02,         /* CRC error */
                    132:        Fae             = 0x04,         /* frame alignment error */
                    133:        Fo              = 0x08,         /* FIFO overrun */
                    134:        Mpa             = 0x10,         /* missed packet */
                    135:        Phy             = 0x20,         /* physical/multicast address */
                    136:        Dis             = 0x40,         /* receiver disabled */
                    137:        Dfr             = 0x80,         /* deferring */
                    138: };
                    139: 
                    140: typedef struct {
                    141:        uchar   status;
                    142:        uchar   next;
                    143:        uchar   len0;
                    144:        uchar   len1;
                    145: } Hdr;
                    146: 
                    147: static void
                    148: dp8390disable(Ctlr *ctlr)
                    149: {
                    150:        ulong dp8390;
                    151:        int timo;
                    152: 
                    153:        dp8390 = ctlr->card.dp8390;
                    154:        /*
                    155:         * Stop the chip. Set the Stp bit and wait for the chip
                    156:         * to finish whatever was on its tiny mind before it sets
                    157:         * the Rst bit.
                    158:         * We need the timeout because there may not be a real
                    159:         * chip there if this is called when probing for a device
                    160:         * at boot.
                    161:         */
                    162:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
                    163:        dp8390outb(dp8390+Rbcr0, 0);
                    164:        dp8390outb(dp8390+Rbcr1, 0);
                    165:        for(timo = 10000; (dp8390inb(dp8390+Isr) & Rst) == 0 && timo; timo--)
                    166:                        ;
                    167: }
                    168: 
                    169: static void
                    170: dp8390ring(Ctlr *ctlr)
                    171: {
                    172:        ulong dp8390;
                    173: 
                    174:        dp8390 = ctlr->card.dp8390;
                    175:        dp8390outb(dp8390+Pstart, ctlr->card.pstart);
                    176:        dp8390outb(dp8390+Pstop, ctlr->card.pstop);
                    177:        dp8390outb(dp8390+Bnry, ctlr->card.pstop-1);
                    178: 
                    179:        dp8390outb(dp8390+Cr, Page1|RDMAabort|Stp);
                    180:        dp8390outb(dp8390+Curr, ctlr->card.pstart);
                    181:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
                    182: 
                    183:        ctlr->card.nxtpkt = ctlr->card.pstart;
                    184: }
                    185: 
                    186: void
                    187: dp8390reset(Ctlr *ctlr)
                    188: {
                    189:        ulong dp8390;
                    190: 
                    191:        dp8390 = ctlr->card.dp8390;
                    192:        /*
                    193:         * This is the initialisation procedure described
                    194:         * as 'mandatory' in the datasheet, with references
                    195:         * to the 3Com503 technical reference manual.
                    196:         */ 
                    197:        dp8390disable(ctlr);
                    198:        if(ctlr->card.bit16)
                    199:                dp8390outb(dp8390+Dcr, Ft4|Ls|Wts);
                    200:        else
                    201:                dp8390outb(dp8390+Dcr, Ft4|Ls);
                    202: 
                    203:        dp8390outb(dp8390+Rbcr0, 0);
                    204:        dp8390outb(dp8390+Rbcr1, 0);
                    205: 
                    206:        dp8390outb(dp8390+Tcr, 0);
                    207:        dp8390outb(dp8390+Rcr, Mon);
                    208: 
                    209:        /*
                    210:         * Init the ring hardware and software ring pointers.
                    211:         * Can't initialise ethernet address as we may not know
                    212:         * it yet.
                    213:         */
                    214:        dp8390ring(ctlr);
                    215:        dp8390outb(dp8390+Tpsr, ctlr->card.tstart);
                    216: 
                    217:        dp8390outb(dp8390+Isr, 0xFF);
                    218:        dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
                    219: 
                    220:        /*
                    221:         * Leave the chip initialised,
                    222:         * but in monitor mode.
                    223:         */
                    224:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
                    225: }
                    226: 
                    227: void
                    228: dp8390attach(Ctlr *ctlr)
                    229: {
                    230:        /*
                    231:         * Enable the chip for transmit/receive.
                    232:         * The init routine leaves the chip in monitor
                    233:         * mode. Clear the missed-packet counter, it
                    234:         * increments while in monitor mode.
                    235:         */
                    236:        dp8390outb(ctlr->card.dp8390+Rcr, Ab);
                    237:        dp8390inb(ctlr->card.dp8390+Cntr2);
                    238: }
                    239: 
                    240: void
                    241: dp8390mode(Ctlr *ctlr, int on)
                    242: {
                    243:        /*
                    244:         * Set/reset promiscuous mode.
                    245:         */
                    246:        if(on)
                    247:                dp8390outb(ctlr->card.dp8390+Rcr, Pro|Ab);
                    248:        else
                    249:                dp8390outb(ctlr->card.dp8390+Rcr, Ab);
                    250: }
                    251: 
                    252: void
                    253: dp8390setea(Ctlr *ctlr)
                    254: {
                    255:        ulong dp8390;
                    256:        uchar cr;
                    257:        int i;
                    258: 
                    259:        dp8390 = ctlr->card.dp8390;
                    260:        /*
                    261:         * Set the ethernet address into the chip.
                    262:         * Take care to restore the command register
                    263:         * afterwards. We don't care about multicast
                    264:         * addresses as we never set the multicast
                    265:         * enable.
                    266:         */
                    267:        cr = dp8390inb(dp8390+Cr) & ~Txp;
                    268:        dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
                    269:        for(i = 0; i < sizeof(ctlr->card.ea); i++)
                    270:                dp8390outb(dp8390+Par0+i, ctlr->card.ea[i]);
                    271:        dp8390outb(dp8390+Cr, cr);
                    272: }
                    273: 
                    274: void
                    275: dp8390getea(Ctlr *ctlr)
                    276: {
                    277:        ulong dp8390;
                    278:        uchar cr;
                    279:        int i;
                    280: 
                    281:        dp8390 = ctlr->card.dp8390;
                    282:        /*
                    283:         * Set the ethernet address into the chip.
                    284:         * Take care to restore the command register
                    285:         * afterwards. We don't care about multicast
                    286:         * addresses as we never set the multicast
                    287:         * enable.
                    288:         */
                    289:        cr = dp8390inb(dp8390+Cr) & ~Txp;
                    290:        dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
                    291:        for(i = 0; i < sizeof(ctlr->card.ea); i++)
                    292:                ctlr->card.ea[i] = dp8390inb(dp8390+Par0+i);
                    293:        dp8390outb(dp8390+Cr, cr);
                    294: }
                    295: 
                    296: void*
                    297: dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len)
                    298: {
                    299:        ulong dp8390;
                    300:        uchar cr;
                    301:        int timo;
                    302: 
                    303:        dp8390 = ctlr->card.dp8390;
                    304:        /*
                    305:         * Read some data at offset 'from' in the card's memory
                    306:         * using the DP8390 remote DMA facility, and place it at
                    307:         * 'to' in main memory, via the I/O data port.
                    308:         */
                    309:        cr = dp8390inb(dp8390+Cr) & ~Txp;
                    310:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
                    311:        dp8390outb(dp8390+Isr, Rdc);
                    312: 
                    313:        /*
                    314:         * Set up the remote DMA address and count.
                    315:         */
                    316:        if(ctlr->card.bit16)
                    317:                len = ROUNDUP(len, 2);
                    318:        dp8390outb(dp8390+Rbcr0, len & 0xFF);
                    319:        dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF);
                    320:        dp8390outb(dp8390+Rsar0, from & 0xFF);
                    321:        dp8390outb(dp8390+Rsar1, (from>>8) & 0xFF);
                    322: 
                    323:        /*
                    324:         * Start the remote DMA read and suck the data
                    325:         * out of the I/O port.
                    326:         */
                    327:        dp8390outb(dp8390+Cr, Page0|RDMAread|Sta);
                    328:        if(ctlr->card.bit16)
                    329:                inss(ctlr->card.data, to, len/2);
                    330:        else
                    331:                insb(ctlr->card.data, to, len);
                    332: 
                    333:        /*
                    334:         * Wait for the remote DMA to complete. The timeout
                    335:         * is necessary because we may call this routine on
                    336:         * a non-existent chip during initialisation and, due
                    337:         * to the miracles of the bus, we could get this far
                    338:         * and still be talking to a slot full of nothing.
                    339:         */
                    340:        for(timo = 10000; (dp8390inb(dp8390+Isr) & Rdc) == 0 && timo; timo--)
                    341:                        ;
                    342: 
                    343:        dp8390outb(dp8390+Isr, Rdc);
                    344:        dp8390outb(dp8390+Cr, cr);
                    345:        return to;
                    346: }
                    347: 
                    348: void*
                    349: dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len)
                    350: {
                    351:        ulong dp8390, crda;
                    352:        uchar cr;
                    353: 
                    354:        dp8390 = ctlr->card.dp8390;
                    355:        /*
                    356:         * Write some data to offset 'to' in the card's memory
                    357:         * using the DP8390 remote DMA facility, reading it at
                    358:         * 'from' in main memory, via the I/O data port.
                    359:         */
                    360:        cr = dp8390inb(dp8390+Cr) & ~Txp;
                    361:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
                    362:        dp8390outb(dp8390+Isr, Rdc);
                    363: 
                    364:        if(ctlr->card.bit16)
                    365:                len = ROUNDUP(len, 2);
                    366: 
                    367:        /*
                    368:         * Set up the remote DMA address and count.
                    369:         * This is straight from the DP8390[12D] datasheet, hence
                    370:         * the initial set up for read.
                    371:         */
                    372:        crda = to-1-ctlr->card.bit16;
                    373:        dp8390outb(dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF);
                    374:        dp8390outb(dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF);
                    375:        dp8390outb(dp8390+Rsar0, crda & 0xFF);
                    376:        dp8390outb(dp8390+Rsar1, (crda>>8) & 0xFF);
                    377:        dp8390outb(dp8390+Cr, Page0|RDMAread|Sta);
                    378: 
                    379:        for(;;){
                    380:                crda = dp8390inb(dp8390+Crda0);
                    381:                crda |= dp8390inb(dp8390+Crda1)<<8;
                    382:                if(crda == to){
                    383:                        /*
                    384:                         * Start the remote DMA write and make sure
                    385:                         * the registers are correct.
                    386:                         */
                    387:                        dp8390outb(dp8390+Cr, Page0|RDMAwrite|Sta);
                    388: 
                    389:                        crda = dp8390inb(dp8390+Crda0);
                    390:                        crda |= dp8390inb(dp8390+Crda1)<<8;
                    391:                        if(crda != to)
                    392:                                panic("crda write %d to %d\n", crda, to);
                    393: 
                    394:                        break;
                    395:                }
                    396:        }
                    397: 
                    398:        /*
                    399:         * Pump the data into the I/O port.
                    400:         */
                    401:        if(ctlr->card.bit16)
                    402:                outss(ctlr->card.data, from, len/2);
                    403:        else
                    404:                outsb(ctlr->card.data, from, len);
                    405: 
                    406:        /*
                    407:         * Wait for the remote DMA to finish. We'll need
                    408:         * a timeout here if this ever gets called before
                    409:         * we know there really is a chip there.
                    410:         */
                    411:        while((dp8390inb(dp8390+Isr) & Rdc) == 0)
                    412:                        ;
                    413: 
                    414:        dp8390outb(dp8390+Isr, Rdc);
                    415:        dp8390outb(dp8390+Cr, cr);
                    416:        return (void*)to;
                    417: }
                    418: 
                    419: static uchar
                    420: getcurr(ulong dp8390)
                    421: {
                    422:        uchar cr, curr;
                    423: 
                    424:        cr = dp8390inb(dp8390+Cr) & ~Txp;
                    425:        dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
                    426:        curr = dp8390inb(dp8390+Curr);
                    427:        dp8390outb(dp8390+Cr, cr);
                    428:        return curr;
                    429: }
                    430: 
                    431: void
                    432: dp8390receive(Ctlr *ctlr)
                    433: {
                    434:        RingBuf *ring;
                    435:        uchar curr, len1, *pkt;
                    436:        Hdr hdr;
                    437:        ulong dp8390, data, len;
                    438: 
                    439:        dp8390 = ctlr->card.dp8390;
                    440:        for(curr = getcurr(dp8390); ctlr->card.nxtpkt != curr; curr = getcurr(dp8390)){
                    441:                ctlr->inpackets++;
                    442: 
                    443:                data = ctlr->card.nxtpkt*Dp8390BufSz;
                    444:                (*ctlr->card.read)(ctlr, &hdr, data, sizeof(Hdr));
                    445: 
                    446:                /*
                    447:                 * Don't believe the upper byte count, work it
                    448:                 * out from the software next-page pointer and
                    449:                 * the current next-page pointer.
                    450:                 */
                    451:                if(hdr.next > ctlr->card.nxtpkt)
                    452:                        len1 = hdr.next - ctlr->card.nxtpkt - 1;
                    453:                else
                    454:                        len1 = (ctlr->card.pstop-ctlr->card.nxtpkt) + (hdr.next-ctlr->card.pstart) - 1;
                    455:                if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr)))
                    456:                        len1--;
                    457: 
                    458:                len = ((len1<<8)|hdr.len0)-4;
                    459: 
                    460:                /*
                    461:                 * Chip is badly scrogged, reinitialise the ring.
                    462:                 */
                    463:                if(hdr.next < ctlr->card.pstart || hdr.next >= ctlr->card.pstop
                    464:                  || len < 60 || len > sizeof(Etherpkt)){
                    465:                        print("H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d|",
                    466:                                hdr.status, hdr.next, hdr.len0, hdr.len1, len);
                    467:                        dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
                    468:                        dp8390ring(ctlr);
                    469:                        dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
                    470:                        return;
                    471:                }
                    472: 
                    473:                /*
                    474:                 * If it's a good packet and we have a place to put it,
                    475:                 * read it in to the software ring.
                    476:                 * If the packet wraps round the hardware ring, read it
                    477:                 * in two pieces.
                    478:                 */
                    479:                ring = &ctlr->rb[ctlr->ri];
                    480:                if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){
                    481:                        pkt = ring->pkt;
                    482:                        data += sizeof(Hdr);
                    483:                        ring->len = len;
                    484: 
                    485:                        if((data+len) >= ctlr->card.pstop*Dp8390BufSz){
                    486:                                ulong count = ctlr->card.pstop*Dp8390BufSz - data;
                    487: 
                    488:                                (*ctlr->card.read)(ctlr, pkt, data, count);
                    489:                                pkt += count;
                    490:                                data = ctlr->card.pstart*Dp8390BufSz;
                    491:                                len -= count;
                    492:                        }
                    493:                        if(len)
                    494:                                (*ctlr->card.read)(ctlr, pkt, data, len);
                    495: 
                    496:                        ring->owner = Host;
                    497:                        ctlr->ri = NEXT(ctlr->ri, ctlr->nrb);
                    498:                }
                    499: 
                    500:                /*
                    501:                 * Finished woth this packet, update the
                    502:                 * hardware and software ring pointers.
                    503:                 */
                    504:                ctlr->card.nxtpkt = hdr.next;
                    505: 
                    506:                hdr.next--;
                    507:                if(hdr.next < ctlr->card.pstart)
                    508:                        hdr.next = ctlr->card.pstop-1;
                    509:                dp8390outb(dp8390+Bnry, hdr.next);
                    510:        }
                    511: }
                    512: 
                    513: /*
                    514:  * Initiate a transmission. Must be called splhi().
                    515:  */
                    516: void
                    517: dp8390transmit(Ctlr *ctlr)
                    518: {
                    519:        ulong dp8390;
                    520:        RingBuf *ring;
                    521: 
                    522:        dp8390 = ctlr->card.dp8390;
                    523:        ring = &ctlr->tb[ctlr->ti];
                    524:        if(ctlr->tbusy == 0 && ring->owner == Interface){
                    525: 
                    526:                ctlr->tbusy = 1;
                    527: 
                    528:                (*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len);
                    529: 
                    530:                dp8390outb(dp8390+Tbcr0, ring->len & 0xFF);
                    531:                dp8390outb(dp8390+Tbcr1, (ring->len>>8) & 0xFF);
                    532:                dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta);
                    533:        }
                    534: }
                    535: 
                    536: void
                    537: dp8390overflow(Ctlr *ctlr)
                    538: {
                    539:        ulong dp8390;
                    540:        uchar txp;
                    541:        int resend;
                    542: 
                    543:        dp8390 = ctlr->card.dp8390;
                    544:        /*
                    545:         * The following procedure is taken from the DP8390[12D] datasheet,
                    546:         * it seems pretty adamant that this is what has to be done.
                    547:         */
                    548:        txp = dp8390inb(dp8390+Cr) & Txp;
                    549:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
                    550:        delay(2);
                    551:        dp8390outb(dp8390+Rbcr0, 0);
                    552:        dp8390outb(dp8390+Rbcr1, 0);
                    553: 
                    554:        resend = 0;
                    555:        if(txp && (dp8390inb(dp8390+Isr) & (Txe|Ptx)) == 0)
                    556:                resend = 1;
                    557: 
                    558:        dp8390outb(dp8390+Tcr, Lb);
                    559:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
                    560:        (*ctlr->card.receive)(ctlr);
                    561:        dp8390outb(dp8390+Isr, Ovw);
                    562:        dp8390outb(dp8390+Tcr, 0);
                    563: 
                    564:        if(resend)
                    565:                dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta);
                    566: }
                    567: 
                    568: void
                    569: dp8390intr(Ureg*, Ctlr *ctlr)
                    570: {
                    571:        ulong dp8390;
                    572:        RingBuf *ring;
                    573:        uchar isr, r;
                    574: 
                    575:        dp8390 = ctlr->card.dp8390;
                    576:        /*
                    577:         * While there is something of interest,
                    578:         * clear all the interrupts and process.
                    579:         */
                    580:        dp8390outb(dp8390+Imr, 0x00);
                    581:        while(isr = dp8390inb(dp8390+Isr)){
                    582: 
                    583:                if(isr & Ovw){
                    584:                        if(ctlr->card.overflow)
                    585:                                (*ctlr->card.overflow)(ctlr);
                    586:                        dp8390outb(dp8390+Isr, Ovw);
                    587:                        ctlr->overflows++;
                    588:                }
                    589: 
                    590:                /*
                    591:                 * We have received packets.
                    592:                 * Take a spin round the ring and
                    593:                 * wakeup the kproc.
                    594:                 */
                    595:                if(isr & (Rxe|Prx)){
                    596:                        (*ctlr->card.receive)(ctlr);
                    597:                        dp8390outb(dp8390+Isr, Rxe|Prx);
                    598:                }
                    599: 
                    600:                /*
                    601:                 * A packet completed transmission, successfully or
                    602:                 * not. Start transmission on the next buffered packet,
                    603:                 * and wake the output routine.
                    604:                 */
                    605:                if(isr & (Txe|Ptx)){
                    606:                        r = dp8390inb(dp8390+Tsr);
                    607:                        if(isr & Txe){
                    608:                                if((r & (Cdh|Fu|Crs|Abt)))
                    609:                                        print("Tsr#%2.2ux|", r);
                    610:                                ctlr->oerrs++;
                    611:                        }
                    612: 
                    613:                        if(isr & Ptx)
                    614:                                ctlr->outpackets++;
                    615: 
                    616:                        dp8390outb(dp8390+Isr, Txe|Ptx);
                    617: 
                    618:                        ring = &ctlr->tb[ctlr->ti];
                    619:                        ring->owner = Host;
                    620:                        ctlr->tbusy = 0;
                    621:                        ctlr->ti = NEXT(ctlr->ti, ctlr->ntb);
                    622:                        (*ctlr->card.transmit)(ctlr);
                    623:                }
                    624: 
                    625:                if(isr & Cnt){
                    626:                        ctlr->frames += dp8390inb(dp8390+Cntr0);
                    627:                        ctlr->crcs += dp8390inb(dp8390+Cntr1);
                    628:                        ctlr->buffs += dp8390inb(dp8390+Cntr2);
                    629:                        dp8390outb(dp8390+Isr, Cnt);
                    630:                }
                    631:        }
                    632:        dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
                    633: }

unix.superglobalmegacorp.com

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