Annotation of lucent/sys/src/9/pc/ether509.c, revision 1.1.1.1

1.1       root        1: #include "u.h"
                      2: #include "../port/lib.h"
                      3: #include "mem.h"
                      4: #include "dat.h"
                      5: #include "fns.h"
                      6: #include "../port/error.h"
                      7: #include "io.h"
                      8: #include "devtab.h"
                      9: 
                     10: #include "ether.h"
                     11: 
                     12: enum {
                     13:        IDport          = 0x0110,       /* anywhere between 0x0100 and 0x01F0 */
                     14: 
                     15:                                        /* Commands */
                     16:        SelectWindow    = 0x01,         /* SelectWindow command */
                     17:        StartCoax       = 0x02,         /* Start Coaxial Transceiver */
                     18:        RxDisable       = 0x03,         /* RX Disable */
                     19:        RxEnable        = 0x04,         /* RX Enable */
                     20:        RxReset         = 0x05,         /* RX Reset */
                     21:        RxDiscard       = 0x08,         /* RX Discard Top Packet */
                     22:        TxEnable        = 0x09,         /* TX Enable */
                     23:        TxDisable       = 0x0A,         /* TX Disable */
                     24:        TxReset         = 0x0B,         /* TX Reset */
                     25:        AckIntr         = 0x0D,         /* Acknowledge Interrupt */
                     26:        SetIntrMask     = 0x0E,         /* Set Interrupt Mask */
                     27:        SetReadZeroMask = 0x0F,         /* Set Read Zero Mask */
                     28:        SetRxFilter     = 0x10,         /* Set RX Filter */
                     29:        SetTxAvailable  = 0x12,         /* Set TX Available Threshold */
                     30: 
                     31:                                        /* RX Filter Command Bits */
                     32:        MyEtherAddr     = 0x01,         /* Individual address */
                     33:        Multicast       = 0x02,         /* Group (multicast) addresses */
                     34:        Broadcast       = 0x04,         /* Broadcast address */
                     35:        Promiscuous     = 0x08,         /* All addresses (promiscuous mode) */
                     36: 
                     37:                                        /* Window Register Offsets */
                     38:        Command         = 0x0E,         /* all windows */
                     39:        Status          = 0x0E,
                     40: 
                     41:        ManufacturerID  = 0x00,         /* window 0 */
                     42:        ProductID       = 0x02,
                     43:        ConfigControl   = 0x04,
                     44:        AddressConfig   = 0x06,
                     45:        ResourceConfig  = 0x08,
                     46:        EEPROMcmd       = 0x0A,
                     47:        EEPROMdata      = 0x0C,
                     48: 
                     49:                                        /* AddressConfig Bits */
                     50:        XcvrTypeMask    = 0xC000,       /* Transceiver Type Select */
                     51:        Xcvr10BaseT     = 0x0000,
                     52:        XcvrAUI         = 0x4000,
                     53:        XcvrBNC         = 0xC000,
                     54: 
                     55:                                        /* ConfigControl */
                     56:        Rst             = 0x04,         /* Reset Adapter */
                     57:        Ena             = 0x01,         /* Enable Adapter */
                     58: 
                     59:        Fifo            = 0x00,         /* window 1 */
                     60:        RxStatus        = 0x08,
                     61:        Timer           = 0x0A,
                     62:        TxStatus        = 0x0B,
                     63:        TxFreeBytes     = 0x0C,
                     64: 
                     65:                                        /* Status/Interrupt Bits */
                     66:        Latch           = 0x0001,       /* Interrupt Latch */
                     67:        Failure         = 0x0002,       /* Adapter Failure */
                     68:        TxComplete      = 0x0004,       /* TX Complete */
                     69:        TxAvailable     = 0x0008,       /* TX Available */
                     70:        RxComplete      = 0x0010,       /* RX Complete */
                     71:        RxEarly         = 0x0020,       /* RX partial packet available */
                     72:        AllIntr         = 0x00FE,       /* All Interrupt Bits */
                     73:        CmdInProgress   = 0x1000,       /* Command In Progress */
                     74: 
                     75:                                        /* TxStatus Bits */
                     76:        TxJabber        = 0x20,         /* Jabber Error */
                     77:        TxUnderrun      = 0x10,         /* Underrun */
                     78:        TxMaxColl       = 0x08,         /* Maximum Collisions */
                     79: 
                     80:                                        /* RxStatus Bits */
                     81:        RxByteMask      = 0x07FF,       /* RX Bytes (0-1514) */
                     82:        RxErrMask       = 0x3800,       /* Type of Error: */
                     83:        RxErrOverrun    = 0x0000,       /*   Overrrun */
                     84:        RxErrOversize   = 0x0800,       /*   Oversize Packet (>1514) */
                     85:        RxErrDribble    = 0x1000,       /*   Dribble Bit(s) */
                     86:        RxErrRunt       = 0x1800,       /*   Runt Packet */
                     87:        RxErrFraming    = 0x2000,       /*   Alignment (Framing) */
                     88:        RxErrCRC        = 0x2800,       /*   CRC */
                     89:        RxError         = 0x4000,       /* Error */
                     90:        RxEmpty         = 0x8000,       /* Incomplete or FIFO empty */
                     91: 
                     92:        FIFOdiag        = 0x04,         /* window 4 */
                     93:        MediaStatus     = 0x0A,
                     94: 
                     95:                                        /* FIFOdiag bits */
                     96:        TxOverrun       = 0x0400,       /* TX Overrrun */
                     97:        RxOverrun       = 0x0800,       /* RX Overrun */
                     98:        RxStatusOverrun = 0x1000,       /* RX Status Overrun */
                     99:        RxUnderrun      = 0x2000,       /* RX Underrun */
                    100:        RxReceiving     = 0x8000,       /* RX Receiving */
                    101: 
                    102:                                        /* MediaStatus bits */
                    103:        JabberEna       = 0x0040,       /* Jabber Enabled (writeable) */
                    104:        LinkBeatEna     = 0x0080,       /* Link Beat Enabled (writeable) */
                    105: };
                    106: 
                    107: #define COMMAND(port, cmd, a)  outs(port+Command, ((cmd)<<11)|(a))
                    108: 
                    109: static void
                    110: attach(Ctlr *ctlr)
                    111: {
                    112:        ulong port;
                    113: 
                    114:        port = ctlr->card.port;
                    115:        /*
                    116:         * Set the receiver packet filter for our own and
                    117:         * and broadcast addresses, set the interrupt masks
                    118:         * for all interrupts, and enable the receiver and transmitter.
                    119:         * The only interrupt we should see under normal conditions
                    120:         * is the receiver interrupt. If the transmit FIFO fills up,
                    121:         * we will also see TxAvailable interrupts.
                    122:         */
                    123:        COMMAND(port, SetRxFilter, Broadcast|MyEtherAddr);
                    124:        COMMAND(port, SetReadZeroMask, AllIntr|Latch);
                    125:        COMMAND(port, SetIntrMask, AllIntr|Latch);
                    126:        COMMAND(port, RxEnable, 0);
                    127:        COMMAND(port, TxEnable, 0);
                    128: }
                    129: 
                    130: static void
                    131: mode(Ctlr *ctlr, int on)
                    132: {
                    133:        ulong port;
                    134: 
                    135:        port = ctlr->card.port;
                    136:        if(on)
                    137:                COMMAND(port, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr);
                    138:        else
                    139:                COMMAND(port, SetRxFilter, Broadcast|MyEtherAddr);
                    140: }
                    141: 
                    142: static void
                    143: receive(Ctlr *ctlr)
                    144: {
                    145:        ushort status;
                    146:        RingBuf *rb;
                    147:        int len;
                    148:        ulong port;
                    149: 
                    150:        port = ctlr->card.port;
                    151:        while(((status = ins(port+RxStatus)) & RxEmpty) == 0){
                    152:                /*
                    153:                 * If we had an error, log it and continue
                    154:                 * without updating the ring.
                    155:                 */
                    156:                if(status & RxError){
                    157:                        switch(status & RxErrMask){
                    158: 
                    159:                        case RxErrOverrun:      /* Overrrun */
                    160:                                ctlr->overflows++;
                    161:                                break;
                    162: 
                    163:                        case RxErrOversize:     /* Oversize Packet (>1514) */
                    164:                        case RxErrRunt:         /* Runt Packet */
                    165:                                ctlr->buffs++;
                    166:                                break;
                    167:                        case RxErrFraming:      /* Alignment (Framing) */
                    168:                                ctlr->frames++;
                    169:                                break;
                    170: 
                    171:                        case RxErrCRC:          /* CRC */
                    172:                                ctlr->crcs++;
                    173:                                break;
                    174:                        }
                    175:                }
                    176:                else {
                    177:                        /*
                    178:                         * We have a packet. Read it into the next
                    179:                         * free ring buffer, if any.
                    180:                         * The CRC is already stripped off.
                    181:                         */
                    182:                        rb = &ctlr->rb[ctlr->ri];
                    183:                        if(rb->owner == Interface){
                    184:                                len = (status & RxByteMask);
                    185:                                rb->len = len;
                    186:        
                    187:                                /*
                    188:                                 * Must read len bytes padded to a
                    189:                                 * doubleword. We can pick them out 32-bits
                    190:                                 * at a time .
                    191:                                 */
                    192:                                insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
                    193: 
                    194:                                /*
                    195:                                 * Update the ring.
                    196:                                 */
                    197:                                rb->owner = Host;
                    198:                                ctlr->ri = NEXT(ctlr->ri, ctlr->nrb);
                    199:                        }
                    200:                }
                    201: 
                    202:                /*
                    203:                 * Discard the packet as we're done with it.
                    204:                 * Wait for discard to complete.
                    205:                 */
                    206:                COMMAND(port, RxDiscard, 0);
                    207:                while(ins(port+Status) & CmdInProgress)
                    208:                        ;
                    209:        }
                    210: }
                    211: 
                    212: static void
                    213: transmit(Ctlr *ctlr)
                    214: {
                    215:        RingBuf *tb;
                    216:        ushort len;
                    217:        ulong port;
                    218: 
                    219:        port = ctlr->card.port;
                    220:        for(tb = &ctlr->tb[ctlr->ti]; tb->owner == Interface; tb = &ctlr->tb[ctlr->ti]){
                    221:                /*
                    222:                 * If there's no room in the FIFO for this packet,
                    223:                 * set up an interrupt for when space becomes available.
                    224:                 * Output packet must be a multiple of 4 in length and
                    225:                 * we need 4 bytes for the preamble.
                    226:                 */
                    227:                len = ROUNDUP(tb->len, 4);
                    228:                if(len+4 > ins(port+TxFreeBytes)){
                    229:                        COMMAND(port, SetTxAvailable, len);
                    230:                        break;
                    231:                }
                    232: 
                    233:                /*
                    234:                 * There's room, copy the packet to the FIFO and free
                    235:                 * the buffer back to the host.
                    236:                 */
                    237:                outs(port+Fifo, tb->len);
                    238:                outs(port+Fifo, 0);
                    239:                outsl(port+Fifo, tb->pkt, len/4);
                    240:                tb->owner = Host;
                    241:                ctlr->ti = NEXT(ctlr->ti, ctlr->ntb);
                    242:        }
                    243: }
                    244: 
                    245: static ushort
                    246: getdiag(Ctlr *ctlr)
                    247: {
                    248:        ushort bytes;
                    249:        ulong port;
                    250: 
                    251:        port = ctlr->card.port;
                    252:        COMMAND(port, SelectWindow, 4);
                    253:        bytes = ins(port+FIFOdiag);
                    254:        COMMAND(port, SelectWindow, 1);
                    255:        return bytes & 0xFFFF;
                    256: }
                    257: 
                    258: static void
                    259: interrupt(Ctlr *ctlr)
                    260: {
                    261:        ushort status, diag;
                    262:        uchar txstatus, x;
                    263:        ulong port;
                    264: 
                    265:        port = ctlr->card.port;
                    266:        status = ins(port+Status);
                    267: 
                    268:        if(status & Failure){
                    269:                /*
                    270:                 * Adapter failure, try to find out why.
                    271:                 * Reset if necessary.
                    272:                 * What happens if Tx is active and we reset,
                    273:                 * need to retransmit?
                    274:                 * This probably isn't right.
                    275:                 */
                    276:                diag = getdiag(ctlr);
                    277:                print("ether509: status #%ux, diag #%ux\n", status, diag);
                    278: 
                    279:                if(diag & TxOverrun){
                    280:                        COMMAND(port, TxReset, 0);
                    281:                        COMMAND(port, TxEnable, 0);
                    282:                }
                    283: 
                    284:                if(diag & RxUnderrun){
                    285:                        COMMAND(port, RxReset, 0);
                    286:                        attach(ctlr);
                    287:                }
                    288: 
                    289:                if(diag & TxOverrun)
                    290:                        transmit(ctlr);
                    291: 
                    292:                return;
                    293:        }
                    294: 
                    295:        if(status & RxComplete){
                    296:                receive(ctlr);
                    297:                wakeup(&ctlr->rr);
                    298:                status &= ~RxComplete;
                    299:        }
                    300: 
                    301:        if(status & TxComplete){
                    302:                /*
                    303:                 * Pop the TX Status stack, accumulating errors.
                    304:                 * If there was a Jabber or Underrun error, reset
                    305:                 * the transmitter. For all conditions enable
                    306:                 * the transmitter.
                    307:                 */
                    308:                txstatus = 0;
                    309:                do{
                    310:                        if(x = inb(port+TxStatus))
                    311:                                outb(port+TxStatus, 0);
                    312:                        txstatus |= x;
                    313:                }while(ins(port+Status) & TxComplete);
                    314: 
                    315:                if(txstatus & (TxJabber|TxUnderrun))
                    316:                        COMMAND(port, TxReset, 0);
                    317:                COMMAND(port, TxEnable, 0);
                    318:                ctlr->oerrs++;
                    319:        }
                    320: 
                    321:        if(status & (TxAvailable|TxComplete)){
                    322:                /*
                    323:                 * Reset the Tx FIFO threshold.
                    324:                 */
                    325:                if(status & TxAvailable)
                    326:                        COMMAND(port, AckIntr, TxAvailable);
                    327:                transmit(ctlr);
                    328:                wakeup(&ctlr->tr);
                    329:                status &= ~(TxAvailable|TxComplete);
                    330:        }
                    331: 
                    332:        /*
                    333:         * Panic if there are any interrupt bits on we haven't
                    334:         * dealt with other than Latch.
                    335:         * Otherwise, acknowledge the interrupt.
                    336:         */
                    337:        if(status & AllIntr)
                    338:                panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(ctlr));
                    339: 
                    340:        COMMAND(port, AckIntr, Latch);
                    341: }
                    342: 
                    343: typedef struct Adapter Adapter;
                    344: struct Adapter {
                    345:        Adapter *next;
                    346:        ulong   port;
                    347: };
                    348: static Adapter *adapter;
                    349: 
                    350: /*
                    351:  * Write two 0 bytes to identify the IDport and then reset the
                    352:  * ID sequence. Then send the ID sequence to the card to get
                    353:  * the card into command state.
                    354:  */
                    355: static void
                    356: idseq(void)
                    357: {
                    358:        int i;
                    359:        uchar al;
                    360: 
                    361:        outb(IDport, 0);
                    362:        outb(IDport, 0);
                    363:        for(al = 0xFF, i = 0; i < 255; i++){
                    364:                outb(IDport, al);
                    365:                if(al & 0x80){
                    366:                        al <<= 1;
                    367:                        al ^= 0xCF;
                    368:                }
                    369:                else
                    370:                        al <<= 1;
                    371:        }
                    372: }
                    373: 
                    374: static ulong
                    375: activate(int tag)
                    376: {
                    377:        int i;
                    378:        ushort x, acr;
                    379:        ulong port;
                    380: 
                    381:        /*
                    382:         * Do the little configuration dance:
                    383:         *
                    384:         * 2. write the ID sequence to get to command state.
                    385:         */
                    386:        idseq();
                    387: 
                    388:        /*
                    389:         * 3. Read the Manufacturer ID from the EEPROM.
                    390:         *    This is done by writing the IDPort with 0x87 (0x80
                    391:         *    is the 'read EEPROM' command, 0x07 is the offset of
                    392:         *    the Manufacturer ID field in the EEPROM).
                    393:         *    The data comes back 1 bit at a time.
                    394:         *    We seem to need a delay here between reading the bits.
                    395:         *
                    396:         * If the ID doesn't match, there are no more adapters.
                    397:         */
                    398:        outb(IDport, 0x87);
                    399:        for(x = 0, i = 0; i < 16; i++){
                    400:                delay(5);
                    401:                x <<= 1;
                    402:                x |= inb(IDport) & 0x01;
                    403:        }
                    404:        if(x != 0x6D50)
                    405:                return 0;
                    406: 
                    407:        /*
                    408:         * 3. Read the Address Configuration from the EEPROM.
                    409:         *    The Address Configuration field is at offset 0x08 in the EEPROM).
                    410:         */
                    411:        outb(IDport, 0x88);
                    412:        for(acr = 0, i = 0; i < 16; i++){
                    413:                delay(20);
                    414:                acr <<= 1;
                    415:                acr |= inb(IDport) & 0x01;
                    416:        }
                    417:        port = (acr & 0x1F)*0x10 + 0x200;
                    418: 
                    419:        if(tag){
                    420:                /*
                    421:                 * 6. Tag the adapter so it won't respond in future.
                    422:                 * 6. Activate the adapter by writing the Activate command
                    423:                 *    (0xFF).
                    424:                 */
                    425:                outb(IDport, 0xD1);
                    426:                outb(IDport, 0xFF);
                    427: 
                    428:                /*
                    429:                 * 8. Now we can talk to the adapter's I/O base addresses.
                    430:                 *    We get the I/O base address from the acr just read.
                    431:                 *
                    432:                 *    Enable the adapter.
                    433:                 */
                    434:                outs(port+ConfigControl, Ena);
                    435:        }
                    436: 
                    437:        return port;
                    438: }
                    439: 
                    440: static ulong
                    441: tcm509(ISAConf *isa)
                    442: {
                    443:        static int untag;
                    444:        ulong port;
                    445:        Adapter *ap;
                    446: 
                    447:        /*
                    448:         * One time only:
                    449:         *      write ID sequence to get the attention of all adapters;
                    450:         *      untag all adapters.
                    451:         * If we do a global reset here on all adapters we'll confuse any
                    452:         * ISA cards configured for EISA mode.
                    453:         */
                    454:        if(untag == 0){
                    455:                idseq();
                    456:                outb(IDport, 0xD0);
                    457:                untag = 1;
                    458:        }
                    459: 
                    460:        /*
                    461:         * Attempt to activate adapters until one matches our
                    462:         * address criteria. If adapter is set for EISA mode,
                    463:         * tag it and ignore. Otherwise, reset the adapter and
                    464:         * activate it fully.
                    465:         */
                    466:        while(port = activate(0)){
                    467:                if(port == 0x3F0){
                    468:                        outb(IDport, 0xD1);
                    469:                        continue;
                    470:                }
                    471:                outb(IDport, 0xC0);
                    472:                delay(2);
                    473:                if(activate(1) != port)
                    474:                        print("tcm509: activate\n");
                    475:                
                    476:                if(isa->port == 0 || isa->port == port)
                    477:                        return port;
                    478: 
                    479:                ap = malloc(sizeof(Adapter));
                    480:                ap->port = port;
                    481:                ap->next = adapter;
                    482:                adapter = ap;
                    483:        }
                    484: 
                    485:        return 0;
                    486: }
                    487: 
                    488: static ulong
                    489: tcm579(ISAConf *isa)
                    490: {
                    491:        static int slot = 1;
                    492:        ushort x;
                    493:        ulong port;
                    494:        Adapter *ap;
                    495: 
                    496:        /*
                    497:         * First time through, check if this is an EISA machine.
                    498:         * If not, nothing to do.
                    499:         */
                    500:        if(slot == 1 && strncmp((char*)(KZERO|0xFFFD9), "EISA", 4))
                    501:                return 0;
                    502: 
                    503:        /*
                    504:         * Continue through the EISA slots looking for a match on both
                    505:         * 3COM as the manufacturer and 3C579 or 3C579-TP as the product.
                    506:         * If we find an adapter, select window 0, enable it and clear
                    507:         * out any lingering status and interrupts.
                    508:         * Trying to do a GlobalReset here to re-init the card (as in the
                    509:         * 509 code) doesn't seem to work.
                    510:         */
                    511:        while(slot < 16){
                    512:                port = slot++*0x1000;
                    513:                if(ins(port+0xC80+ManufacturerID) != 0x6D50)
                    514:                        continue;
                    515:                x = ins(port+0xC80+ProductID);
                    516:                if((x & 0xF0FF) != 0x9050/* || (x != 0x9350 && x != 0x9250)*/)
                    517:                        continue;
                    518: 
                    519:                COMMAND(port, SelectWindow, 0);
                    520:                outs(port+ConfigControl, Ena);
                    521: 
                    522:                COMMAND(port, TxReset, 0);
                    523:                COMMAND(port, RxReset, 0);
                    524:                COMMAND(port, AckIntr, 0xFF);
                    525: 
                    526:                if(isa->port == 0 || isa->port == port)
                    527:                        return port;
                    528: 
                    529:                ap = malloc(sizeof(Adapter));
                    530:                ap->port = port;
                    531:                ap->next = adapter;
                    532:                adapter = ap;
                    533:        }
                    534: 
                    535:        return 0;
                    536: }
                    537: 
                    538: static ulong
                    539: tcm589(ISAConf *isa)
                    540: {
                    541:        USED(isa);
                    542:        return 0;
                    543: }
                    544: 
                    545: /*
                    546:  * Get configuration parameters.
                    547:  */
                    548: int
                    549: ether509reset(Ctlr *ctlr)
                    550: {
                    551:        int i, eax;
                    552:        uchar ea[Eaddrlen];
                    553:        ushort x, acr;
                    554:        ulong port;
                    555:        Adapter *ap, **app;
                    556: 
                    557:        /*
                    558:         * Any adapter matches if no port is supplied,
                    559:         * otherwise the ports must match.
                    560:         * See if we've already found an adapter that fits
                    561:         * the bill.
                    562:         * If no match then try for an EISA card, an ISA card
                    563:         * and finally for a PCMCIA card.
                    564:         */
                    565:        port = 0;
                    566:        for(app = &adapter, ap = *app; ap; app = &ap->next, ap = ap->next){
                    567:                if(ctlr->card.port == 0 || ctlr->card.port == ap->port){
                    568:                        port = ap->port;
                    569:                        *app = ap->next;
                    570:                        /*free(ap);lost*/
                    571:                        break;
                    572:                }
                    573:        }
                    574:        if(strcmp(ctlr->card.type, "3C589") == 0)
                    575:                port = ctlr->card.port;
                    576:        if(port == 0)
                    577:                port = tcm579(&ctlr->card);
                    578:        if(port == 0)
                    579:                port = tcm509(&ctlr->card);
                    580:        if(port == 0)
                    581:                return -1;
                    582: 
                    583:        /*
                    584:         * Read the IRQ from the Resource Configuration Register,
                    585:         * the ethernet address from the EEPROM, and the address configuration.
                    586:         * The EEPROM command is 8 bits, the lower 6 bits being
                    587:         * the address offset.
                    588:         */
                    589:        if(strcmp(ctlr->card.type, "3C589") != 0)
                    590:                ctlr->card.irq = (ins(port+ResourceConfig)>>12) & 0x0F;
                    591:        for(eax = 0, i = 0; i < 3; i++, eax += 2){
                    592:                while(ins(port+EEPROMcmd) & 0x8000)
                    593:                        ;
                    594:                outs(port+EEPROMcmd, (2<<6)|i);
                    595:                while(ins(port+EEPROMcmd) & 0x8000)
                    596:                        ;
                    597:                x = ins(port+EEPROMdata);
                    598:                ea[eax] = (x>>8) & 0xFF;
                    599:                ea[eax+1] = x & 0xFF;
                    600:        }
                    601:        acr = ins(port+AddressConfig);
                    602: 
                    603:        /*
                    604:         * Finished with window 0. Now set the ethernet address
                    605:         * in window 2.
                    606:         * CommandRs have the format 'CCCCCAAAAAAAAAAA' where C
                    607:         * is a bit in the command and A is a bit in the argument.
                    608:         */
                    609:        if((ctlr->ea[0]|ctlr->ea[1]|ctlr->ea[2]|ctlr->ea[3]|ctlr->ea[4]|ctlr->ea[5]) == 0)
                    610:                memmove(ctlr->ea, ea, Eaddrlen);
                    611:        COMMAND(port, SelectWindow, 2);
                    612:        for(i = 0; i < Eaddrlen; i++)
                    613:                outb(port+i, ctlr->ea[i]);
                    614: 
                    615:        /*
                    616:         * Enable the transceiver if necessary.
                    617:         */
                    618:        switch(acr & XcvrTypeMask){
                    619: 
                    620:        case Xcvr10BaseT:
                    621:                /*
                    622:                 * Enable Link Beat and Jabber to start the
                    623:                 * transceiver.
                    624:                 */
                    625:                COMMAND(port, SelectWindow, 4);
                    626:                outb(port+MediaStatus, LinkBeatEna|JabberEna);
                    627:                break;
                    628: 
                    629:        case XcvrBNC:
                    630:                /*
                    631:                 * Start the DC-DC converter.
                    632:                 * Wait > 800 microseconds.
                    633:                 */
                    634:                COMMAND(port, StartCoax, 0);
                    635:                delay(1);
                    636:                break;
                    637:        }
                    638: 
                    639:        /*
                    640:         * Set window 1 for normal operation.
                    641:         * Clear out any lingering Tx status.
                    642:         */
                    643:        COMMAND(port, SelectWindow, 1);
                    644:        while(inb(port+TxStatus))
                    645:                outb(port+TxStatus, 0);
                    646: 
                    647:        ctlr->card.port = port;
                    648: 
                    649:        /*
                    650:         * Set up the software configuration.
                    651:         */
                    652:        ctlr->card.reset = ether509reset;
                    653:        ctlr->card.attach = attach;
                    654:        ctlr->card.mode = mode;
                    655:        ctlr->card.transmit = transmit;
                    656:        ctlr->card.intr = interrupt;
                    657:        ctlr->card.bit16 = 1;
                    658: 
                    659:        return 0;
                    660: }
                    661: 
                    662: void
                    663: ether509link(void)
                    664: {
                    665:        addethercard("3C509",  ether509reset);
                    666: }

unix.superglobalmegacorp.com

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