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

unix.superglobalmegacorp.com

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