Annotation of lucent/sys/src/9/pc/ether509.c, revision 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.