Annotation of lucent/sys/src/boot/pc/f002808, revision 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.