Annotation of qemu/roms/ipxe/src/drivers/net/cs89x0.c, revision 1.1

1.1     ! root        1: #ifdef ALLMULTI
        !             2: #error multicast support is not yet implemented
        !             3: #endif
        !             4: 
        !             5: /**
        !             6:    Per an email message from Russ Nelson <[email protected]> on
        !             7:    18 March 2008 this file is now licensed under GPL Version 2.
        !             8: 
        !             9:    From: Russ Nelson <[email protected]>
        !            10:    Date: Tue, 18 Mar 2008 12:42:00 -0400
        !            11:    Subject: Re: [Etherboot-developers] cs89x0 driver in etherboot
        !            12:    -- quote from email 
        !            13:    As copyright holder, if I say it doesn't conflict with the GPL,
        !            14:    then it doesn't conflict with the GPL.
        !            15: 
        !            16:    However, there's no point in causing people's brains to overheat,
        !            17:    so yes, I grant permission for the code to be relicensed under the
        !            18:    GPLv2.  Please make sure that this change in licensing makes its
        !            19:    way upstream.  -russ 
        !            20:    -- quote from email
        !            21: **/
        !            22: 
        !            23: FILE_LICENCE ( GPL2_ONLY );
        !            24: 
        !            25: /* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for etherboot. */
        !            26: /*
        !            27:   Permission is granted to distribute the enclosed cs89x0.[ch] driver
        !            28:   only in conjunction with the Etherboot package.  The code is
        !            29:   ordinarily distributed under the GPL.
        !            30:   
        !            31:   Russ Nelson, January 2000
        !            32: 
        !            33:   ChangeLog:
        !            34: 
        !            35:   Thu Dec 6 22:40:00 1996  Markus Gutschke  <[email protected]>
        !            36: 
        !            37:   * disabled all "advanced" features; this should make the code more reliable
        !            38: 
        !            39:   * reorganized the reset function
        !            40: 
        !            41:   * always reset the address port, so that autoprobing will continue working
        !            42: 
        !            43:   * some cosmetic changes
        !            44: 
        !            45:   * 2.5
        !            46: 
        !            47:   Thu Dec 5 21:00:00 1996  Markus Gutschke  <[email protected]>
        !            48: 
        !            49:   * tested the code against a CS8900 card
        !            50: 
        !            51:   * lots of minor bug fixes and adjustments
        !            52: 
        !            53:   * this is the first release, that actually works! it still requires some
        !            54:     changes in order to be more tolerant to different environments
        !            55: 
        !            56:   * 4
        !            57: 
        !            58:   Fri Nov 22 23:00:00 1996  Markus Gutschke  <[email protected]>
        !            59: 
        !            60:   * read the manuals for the CS89x0 chipsets and took note of all the
        !            61:     changes that will be neccessary in order to adapt Russel Nelson's code
        !            62:     to the requirements of a BOOT-Prom
        !            63: 
        !            64:   * 6
        !            65: 
        !            66:   Thu Nov 19 22:00:00 1996  Markus Gutschke  <[email protected]>
        !            67: 
        !            68:   * Synched with Russel Nelson's current code (v1.00)
        !            69: 
        !            70:   * 2
        !            71: 
        !            72:   Thu Nov 12 18:00:00 1996  Markus Gutschke  <[email protected]>
        !            73: 
        !            74:   * Cleaned up some of the code and tried to optimize the code size.
        !            75: 
        !            76:   * 1.5
        !            77: 
        !            78:   Sun Nov 10 16:30:00 1996  Markus Gutschke  <[email protected]>
        !            79: 
        !            80:   * First experimental release. This code compiles fine, but I
        !            81:   have no way of testing whether it actually works.
        !            82: 
        !            83:   * I did not (yet) bother to make the code 16bit aware, so for
        !            84:   the time being, it will only work for Etherboot/32.
        !            85: 
        !            86:   * 12
        !            87: 
        !            88:   */
        !            89: 
        !            90: #include <errno.h>
        !            91: #include <ipxe/ethernet.h>
        !            92: #include "etherboot.h"
        !            93: #include "nic.h"
        !            94: #include <ipxe/isa.h>
        !            95: #include <ipxe/console.h>
        !            96: #include "cs89x0.h"
        !            97: 
        !            98: static unsigned short  eth_nic_base;
        !            99: static unsigned long    eth_mem_start;
        !           100: static unsigned short   eth_irqno;
        !           101: static unsigned short   eth_cs_type;   /* one of: CS8900, CS8920, CS8920M  */
        !           102: static unsigned short   eth_auto_neg_cnf;
        !           103: static unsigned short   eth_adapter_cnf;
        !           104: static unsigned short  eth_linectl;
        !           105: 
        !           106: /*************************************************************************
        !           107:        CS89x0 - specific routines
        !           108: **************************************************************************/
        !           109: 
        !           110: static inline int readreg(int portno)
        !           111: {
        !           112:        outw(portno, eth_nic_base + ADD_PORT);
        !           113:        return inw(eth_nic_base + DATA_PORT);
        !           114: }
        !           115: 
        !           116: static inline void writereg(int portno, int value)
        !           117: {
        !           118:        outw(portno, eth_nic_base + ADD_PORT);
        !           119:        outw(value, eth_nic_base + DATA_PORT);
        !           120:        return;
        !           121: }
        !           122: 
        !           123: /*************************************************************************
        !           124: EEPROM access
        !           125: **************************************************************************/
        !           126: 
        !           127: static int wait_eeprom_ready(void)
        !           128: {
        !           129:        unsigned long tmo = currticks() + 4*TICKS_PER_SEC;
        !           130: 
        !           131:        /* check to see if the EEPROM is ready, a timeout is used -
        !           132:           just in case EEPROM is ready when SI_BUSY in the
        !           133:           PP_SelfST is clear */
        !           134:        while(readreg(PP_SelfST) & SI_BUSY) {
        !           135:                if (currticks() >= tmo)
        !           136:                        return -1; }
        !           137:        return 0;
        !           138: }
        !           139: 
        !           140: static int get_eeprom_data(int off, int len, unsigned short *buffer)
        !           141: {
        !           142:        int i;
        !           143: 
        !           144: #ifdef EDEBUG
        !           145:        printf("\ncs: EEPROM data from %hX for %hX:",off,len);
        !           146: #endif
        !           147:        for (i = 0; i < len; i++) {
        !           148:                if (wait_eeprom_ready() < 0)
        !           149:                        return -1;
        !           150:                /* Now send the EEPROM read command and EEPROM location
        !           151:                   to read */
        !           152:                writereg(PP_EECMD, (off + i) | EEPROM_READ_CMD);
        !           153:                if (wait_eeprom_ready() < 0)
        !           154:                        return -1;
        !           155:                buffer[i] = readreg(PP_EEData);
        !           156: #ifdef EDEBUG
        !           157:                if (!(i%10))
        !           158:                        printf("\ncs: ");
        !           159:                printf("%hX ", buffer[i]);
        !           160: #endif
        !           161:        }
        !           162: #ifdef EDEBUG
        !           163:        putchar('\n');
        !           164: #endif
        !           165: 
        !           166:        return(0);
        !           167: }
        !           168: 
        !           169: static int get_eeprom_chksum(int off __unused, int len, unsigned short *buffer)
        !           170: {
        !           171:        int  i, cksum;
        !           172: 
        !           173:        cksum = 0;
        !           174:        for (i = 0; i < len; i++)
        !           175:                cksum += buffer[i];
        !           176:        cksum &= 0xffff;
        !           177:        if (cksum == 0)
        !           178:                return 0;
        !           179:        return -1;
        !           180: }
        !           181: 
        !           182: /*************************************************************************
        !           183: Activate all of the available media and probe for network
        !           184: **************************************************************************/
        !           185: 
        !           186: static void clrline(void)
        !           187: {
        !           188:        int i;
        !           189: 
        !           190:        putchar('\r');
        !           191:        for (i = 79; i--; ) putchar(' ');
        !           192:        printf("\rcs: ");
        !           193:        return;
        !           194: }
        !           195: 
        !           196: static void control_dc_dc(int on_not_off)
        !           197: {
        !           198:        unsigned int selfcontrol;
        !           199:        unsigned long tmo = currticks() + TICKS_PER_SEC;
        !           200: 
        !           201:        /* control the DC to DC convertor in the SelfControl register.  */
        !           202:        selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */
        !           203:        if (((eth_adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)
        !           204:                selfcontrol |= HCB1;
        !           205:        else
        !           206:                selfcontrol &= ~HCB1;
        !           207:        writereg(PP_SelfCTL, selfcontrol);
        !           208: 
        !           209:        /* Wait for the DC/DC converter to power up - 1000ms */
        !           210:        while (currticks() < tmo);
        !           211: 
        !           212:        return;
        !           213: }
        !           214: 
        !           215: static int detect_tp(void)
        !           216: {
        !           217:        unsigned long tmo;
        !           218: 
        !           219:        /* Turn on the chip auto detection of 10BT/ AUI */
        !           220: 
        !           221:        clrline(); printf("attempting %s:","TP");
        !           222: 
        !           223:         /* If connected to another full duplex capable 10-Base-T card
        !           224:           the link pulses seem to be lost when the auto detect bit in
        !           225:           the LineCTL is set.  To overcome this the auto detect bit
        !           226:           will be cleared whilst testing the 10-Base-T interface.
        !           227:           This would not be necessary for the sparrow chip but is
        !           228:           simpler to do it anyway. */
        !           229:        writereg(PP_LineCTL, eth_linectl &~ AUI_ONLY);
        !           230:        control_dc_dc(0);
        !           231: 
        !           232:         /* Delay for the hardware to work out if the TP cable is
        !           233:           present - 150ms */
        !           234:        for (tmo = currticks() + 4; currticks() < tmo; );
        !           235: 
        !           236:        if ((readreg(PP_LineST) & LINK_OK) == 0)
        !           237:                return 0;
        !           238: 
        !           239:        if (eth_cs_type != CS8900) {
        !           240: 
        !           241:                writereg(PP_AutoNegCTL, eth_auto_neg_cnf & AUTO_NEG_MASK);
        !           242: 
        !           243:                if ((eth_auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) {
        !           244:                        printf(" negotiating duplex... ");
        !           245:                        while (readreg(PP_AutoNegST) & AUTO_NEG_BUSY) {
        !           246:                                if (currticks() - tmo > 40*TICKS_PER_SEC) {
        !           247:                                        printf("time out ");
        !           248:                                        break;
        !           249:                                }
        !           250:                        }
        !           251:                }
        !           252:                if (readreg(PP_AutoNegST) & FDX_ACTIVE)
        !           253:                        printf("using full duplex");
        !           254:                else
        !           255:                        printf("using half duplex");
        !           256:        }
        !           257: 
        !           258:        return A_CNF_MEDIA_10B_T;
        !           259: }
        !           260: 
        !           261: /* send a test packet - return true if carrier bits are ok */
        !           262: static int send_test_pkt(struct nic *nic)
        !           263: {
        !           264:        static unsigned char testpacket[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
        !           265:                                     0, 46, /*A 46 in network order       */
        !           266:                                     0, 0,  /*DSAP=0 & SSAP=0 fields      */
        !           267:                                     0xf3,0 /*Control (Test Req+P bit set)*/ };
        !           268:        unsigned long tmo;
        !           269: 
        !           270:        writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_TX_ON);
        !           271: 
        !           272:        memcpy(testpacket, nic->node_addr, ETH_ALEN);
        !           273:        memcpy(testpacket+ETH_ALEN, nic->node_addr, ETH_ALEN);
        !           274: 
        !           275:        outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT);
        !           276:        outw(ETH_ZLEN, eth_nic_base + TX_LEN_PORT);
        !           277: 
        !           278:        /* Test to see if the chip has allocated memory for the packet */
        !           279:        for (tmo = currticks() + 2;
        !           280:             (readreg(PP_BusST) & READY_FOR_TX_NOW) == 0; )
        !           281:                if (currticks() >= tmo)
        !           282:                        return(0);
        !           283: 
        !           284:        /* Write the contents of the packet */
        !           285:        outsw(eth_nic_base + TX_FRAME_PORT, testpacket,
        !           286:              (ETH_ZLEN+1)>>1);
        !           287: 
        !           288:        printf(" sending test packet ");
        !           289:        /* wait a couple of timer ticks for packet to be received */
        !           290:        for (tmo = currticks() + 2; currticks() < tmo; );
        !           291: 
        !           292:        if ((readreg(PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
        !           293:                        printf("succeeded");
        !           294:                        return 1;
        !           295:        }
        !           296:        printf("failed");
        !           297:        return 0;
        !           298: }
        !           299: 
        !           300: 
        !           301: static int detect_aui(struct nic *nic)
        !           302: {
        !           303:        clrline(); printf("attempting %s:","AUI");
        !           304:        control_dc_dc(0);
        !           305: 
        !           306:        writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
        !           307: 
        !           308:        if (send_test_pkt(nic)) {
        !           309:                return A_CNF_MEDIA_AUI; }
        !           310:        else
        !           311:                return 0;
        !           312: }
        !           313: 
        !           314: static int detect_bnc(struct nic *nic)
        !           315: {
        !           316:        clrline(); printf("attempting %s:","BNC");
        !           317:        control_dc_dc(1);
        !           318: 
        !           319:        writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
        !           320: 
        !           321:        if (send_test_pkt(nic)) {
        !           322:                return A_CNF_MEDIA_10B_2; }
        !           323:        else
        !           324:                return 0;
        !           325: }
        !           326: 
        !           327: /**************************************************************************
        !           328: ETH_RESET - Reset adapter
        !           329: ***************************************************************************/
        !           330: 
        !           331: static void cs89x0_reset(struct nic *nic)
        !           332: {
        !           333:        int  i;
        !           334:        unsigned long reset_tmo;
        !           335: 
        !           336:        writereg(PP_SelfCTL, readreg(PP_SelfCTL) | POWER_ON_RESET);
        !           337: 
        !           338:        /* wait for two ticks; that is 2*55ms */
        !           339:        for (reset_tmo = currticks() + 2; currticks() < reset_tmo; );
        !           340: 
        !           341:        if (eth_cs_type != CS8900) {
        !           342:                /* Hardware problem requires PNP registers to be reconfigured
        !           343:                   after a reset */
        !           344:                if (eth_irqno != 0xFFFF) {
        !           345:                        outw(PP_CS8920_ISAINT, eth_nic_base + ADD_PORT);
        !           346:                        outb(eth_irqno, eth_nic_base + DATA_PORT);
        !           347:                        outb(0, eth_nic_base + DATA_PORT + 1); }
        !           348: 
        !           349:                if (eth_mem_start) {
        !           350:                        outw(PP_CS8920_ISAMemB, eth_nic_base + ADD_PORT);
        !           351:                        outb((eth_mem_start >> 8) & 0xff, eth_nic_base + DATA_PORT);
        !           352:                        outb((eth_mem_start >> 24) & 0xff, eth_nic_base + DATA_PORT + 1); } }
        !           353: 
        !           354:        /* Wait until the chip is reset */
        !           355:        for (reset_tmo = currticks() + 2;
        !           356:             (readreg(PP_SelfST) & INIT_DONE) == 0 &&
        !           357:                     currticks() < reset_tmo; );
        !           358: 
        !           359:        /* disable interrupts and memory accesses */
        !           360:        writereg(PP_BusCTL, 0);
        !           361: 
        !           362:        /* set the ethernet address */
        !           363:        for (i=0; i < ETH_ALEN/2; i++)
        !           364:                writereg(PP_IA+i*2,
        !           365:                         nic->node_addr[i*2] |
        !           366:                         (nic->node_addr[i*2+1] << 8));
        !           367: 
        !           368:        /* receive only error free packets addressed to this card */
        !           369:        writereg(PP_RxCTL, DEF_RX_ACCEPT);
        !           370: 
        !           371:        /* do not generate any interrupts on receive operations */
        !           372:        writereg(PP_RxCFG, 0);
        !           373: 
        !           374:        /* do not generate any interrupts on transmit operations */
        !           375:        writereg(PP_TxCFG, 0);
        !           376: 
        !           377:        /* do not generate any interrupts on buffer operations */
        !           378:        writereg(PP_BufCFG, 0);
        !           379: 
        !           380:        /* reset address port, so that autoprobing will keep working */
        !           381:        outw(PP_ChipID, eth_nic_base + ADD_PORT);
        !           382: 
        !           383:        return;
        !           384: }
        !           385: 
        !           386: /**************************************************************************
        !           387: ETH_TRANSMIT - Transmit a frame
        !           388: ***************************************************************************/
        !           389: 
        !           390: static void cs89x0_transmit(
        !           391:        struct nic *nic,
        !           392:        const char *d,                  /* Destination */
        !           393:        unsigned int t,                 /* Type */
        !           394:        unsigned int s,                 /* size */
        !           395:        const char *p)                  /* Packet */
        !           396: {
        !           397:        unsigned long tmo;
        !           398:        int           sr;
        !           399: 
        !           400:        /* does this size have to be rounded??? please,
        !           401:           somebody have a look in the specs */
        !           402:        if ((sr = ((s + ETH_HLEN + 1)&~1)) < ETH_ZLEN)
        !           403:                sr = ETH_ZLEN;
        !           404: 
        !           405: retry:
        !           406:        /* initiate a transmit sequence */
        !           407:        outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT);
        !           408:        outw(sr, eth_nic_base + TX_LEN_PORT);
        !           409: 
        !           410:        /* Test to see if the chip has allocated memory for the packet */
        !           411:        if ((readreg(PP_BusST) & READY_FOR_TX_NOW) == 0) {
        !           412:                /* Oops... this should not happen! */
        !           413:                printf("cs: unable to send packet; retrying...\n");
        !           414:                for (tmo = currticks() + 5*TICKS_PER_SEC; currticks() < tmo; );
        !           415:                cs89x0_reset(nic);
        !           416:                goto retry; }
        !           417: 
        !           418:        /* Write the contents of the packet */
        !           419:        outsw(eth_nic_base + TX_FRAME_PORT, d, ETH_ALEN/2);
        !           420:        outsw(eth_nic_base + TX_FRAME_PORT, nic->node_addr,
        !           421:              ETH_ALEN/2);
        !           422:        outw(((t >> 8)&0xFF)|(t << 8), eth_nic_base + TX_FRAME_PORT);
        !           423:        outsw(eth_nic_base + TX_FRAME_PORT, p, (s+1)/2);
        !           424:        for (sr = sr/2 - (s+1)/2 - ETH_ALEN - 1; sr > 0; sr--)
        !           425:                outw(0, eth_nic_base + TX_FRAME_PORT);
        !           426: 
        !           427:        /* wait for transfer to succeed */
        !           428:        for (tmo = currticks()+5*TICKS_PER_SEC;
        !           429:             (s = readreg(PP_TxEvent)&~0x1F) == 0 && currticks() < tmo;)
        !           430:                /* nothing */ ;
        !           431:        if ((s & TX_SEND_OK_BITS) != TX_OK) {
        !           432:                printf("\ntransmission error %#hX\n", s);
        !           433:        }
        !           434: 
        !           435:        return;
        !           436: }
        !           437: 
        !           438: /**************************************************************************
        !           439: ETH_POLL - Wait for a frame
        !           440: ***************************************************************************/
        !           441: 
        !           442: static int cs89x0_poll(struct nic *nic, int retrieve)
        !           443: {
        !           444:        int status;
        !           445: 
        !           446:        status = readreg(PP_RxEvent);
        !           447: 
        !           448:        if ((status & RX_OK) == 0)
        !           449:                return(0);
        !           450: 
        !           451:        if ( ! retrieve ) return 1;
        !           452: 
        !           453:        status = inw(eth_nic_base + RX_FRAME_PORT);
        !           454:        nic->packetlen = inw(eth_nic_base + RX_FRAME_PORT);
        !           455:        insw(eth_nic_base + RX_FRAME_PORT, nic->packet, nic->packetlen >> 1);
        !           456:        if (nic->packetlen & 1)
        !           457:                nic->packet[nic->packetlen-1] = inw(eth_nic_base + RX_FRAME_PORT);
        !           458:        return 1;
        !           459: }
        !           460: 
        !           461: static void cs89x0_irq(struct nic *nic __unused, irq_action_t action __unused)
        !           462: {
        !           463:   switch ( action ) {
        !           464:   case DISABLE :
        !           465:     break;
        !           466:   case ENABLE :
        !           467:     break;
        !           468:   case FORCE :
        !           469:     break;
        !           470:   }
        !           471: }
        !           472: 
        !           473: static struct nic_operations cs89x0_operations = {
        !           474:        .connect        = dummy_connect,
        !           475:        .poll           = cs89x0_poll,
        !           476:        .transmit       = cs89x0_transmit,
        !           477:        .irq            = cs89x0_irq,
        !           478: };
        !           479: 
        !           480: /**************************************************************************
        !           481: ETH_PROBE - Look for an adapter
        !           482: ***************************************************************************/
        !           483: 
        !           484: static int cs89x0_probe_addr ( isa_probe_addr_t ioaddr ) {
        !           485:        /* if they give us an odd I/O address, then do ONE write to
        !           486:           the address port, to get it back to address zero, where we
        !           487:           expect to find the EISA signature word. */
        !           488:        if (ioaddr & 1) {
        !           489:                ioaddr &= ~1;
        !           490:                if ((inw(ioaddr + ADD_PORT) & ADD_MASK) != ADD_SIG)
        !           491:                        return 0;
        !           492:                outw(PP_ChipID, ioaddr + ADD_PORT);
        !           493:        }
        !           494:        
        !           495:        if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG)
        !           496:                return 0;
        !           497: 
        !           498:        return 1;
        !           499: }
        !           500: 
        !           501: static int cs89x0_probe ( struct nic *nic, struct isa_device *isa __unused ) {
        !           502:        int      i, result = -1;
        !           503:        unsigned rev_type = 0, isa_cnf, cs_revision;
        !           504:        unsigned short eeprom_buff[CHKSUM_LEN];
        !           505: 
        !           506:        nic->ioaddr &= ~1; /* LSB = 1 indicates a more aggressive probe */
        !           507:        eth_nic_base = nic->ioaddr;
        !           508: 
        !           509:        /* get the chip type */
        !           510:        rev_type = readreg(PRODUCT_ID_ADD);
        !           511:        eth_cs_type = rev_type &~ REVISON_BITS;
        !           512:        cs_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
        !           513:        
        !           514:        printf("\ncs: cs89%c0%s rev %c, base %#hX",
        !           515:               eth_cs_type==CS8900?'0':'2',
        !           516:               eth_cs_type==CS8920M?"M":"",
        !           517:               cs_revision,
        !           518:               eth_nic_base);
        !           519: #ifndef EMBEDDED 
        !           520:        /* First check to see if an EEPROM is attached*/
        !           521:        if ((readreg(PP_SelfST) & EEPROM_PRESENT) == 0) {
        !           522:                printf("\ncs: no EEPROM...\n");
        !           523:                outw(PP_ChipID, eth_nic_base + ADD_PORT);
        !           524:                return 0;
        !           525:        } else if (get_eeprom_data(START_EEPROM_DATA,CHKSUM_LEN,
        !           526:                                   eeprom_buff) < 0) {
        !           527:                printf("\ncs: EEPROM read failed...\n");
        !           528:                outw(PP_ChipID, eth_nic_base + ADD_PORT);
        !           529:                return 0;
        !           530:        } else if (get_eeprom_chksum(START_EEPROM_DATA,CHKSUM_LEN,
        !           531:                                     eeprom_buff) < 0) {
        !           532:                printf("\ncs: EEPROM checksum bad...\n");
        !           533:                outw(PP_ChipID, eth_nic_base + ADD_PORT);
        !           534:                return 0;
        !           535:        }
        !           536: 
        !           537:        /* get transmission control word but keep the
        !           538:           autonegotiation bits */
        !           539:        eth_auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
        !           540:        /* Store adapter configuration */
        !           541:        eth_adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET/2];
        !           542:        /* Store ISA configuration */
        !           543:        isa_cnf = eeprom_buff[ISA_CNF_OFFSET/2];
        !           544:        
        !           545:        /* store the initial memory base address */
        !           546:        eth_mem_start = eeprom_buff[PACKET_PAGE_OFFSET/2] << 8;
        !           547:        
        !           548:        printf("%s%s%s, addr ",
        !           549:               (eth_adapter_cnf & A_CNF_10B_T)?", RJ-45":"",
        !           550:               (eth_adapter_cnf & A_CNF_AUI)?", AUI":"",
        !           551:               (eth_adapter_cnf & A_CNF_10B_2)?", BNC":"");
        !           552:        
        !           553:        /* If this is a CS8900 then no pnp soft */
        !           554:        if (eth_cs_type != CS8900 &&
        !           555:            /* Check if the ISA IRQ has been set  */
        !           556:            (i = readreg(PP_CS8920_ISAINT) & 0xff,
        !           557:             (i != 0 && i < CS8920_NO_INTS)))
        !           558:                eth_irqno = i;
        !           559:        else {
        !           560:                i = isa_cnf & INT_NO_MASK;
        !           561:                if (eth_cs_type == CS8900) {
        !           562:                        /* the table that follows is dependent
        !           563:                           upon how you wired up your cs8900
        !           564:                           in your system.  The table is the
        !           565:                           same as the cs8900 engineering demo
        !           566:                           board.  irq_map also depends on the
        !           567:                           contents of the table.  Also see
        !           568:                           write_irq, which is the reverse
        !           569:                           mapping of the table below. */
        !           570:                        if (i < 4) i = "\012\013\014\005"[i];
        !           571:                        else printf("\ncs: BUG: isa_config is %d\n", i); }
        !           572:                eth_irqno = i; }
        !           573:        
        !           574:         nic->irqno = eth_irqno;
        !           575: 
        !           576:        /* Retrieve and print the ethernet address. */
        !           577:        for (i=0; i<ETH_ALEN; i++) {
        !           578:                nic->node_addr[i] = ((unsigned char *)eeprom_buff)[i];
        !           579:        }
        !           580: 
        !           581:        DBG ( "%s\n", eth_ntoa ( nic->node_addr ) );
        !           582: 
        !           583: #endif
        !           584: #ifdef EMBEDDED
        !           585:        /* Retrieve and print the ethernet address. */
        !           586:        {
        !           587:                unsigned char MAC_HW_ADDR[6]={MAC_HW_ADDR_DRV};
        !           588:                memcpy(nic->node_addr, MAC_HW_ADDR, 6);
        !           589:        }
        !           590: 
        !           591:        DBG ( "%s\n", eth_ntoa ( nic->node_addr ) );
        !           592:        
        !           593:        eth_adapter_cnf = A_CNF_10B_T | A_CNF_MEDIA_10B_T;
        !           594:        eth_auto_neg_cnf = EE_AUTO_NEG_ENABLE | IMM_BIT;
        !           595: #endif
        !           596: #ifndef EMBEDDED 
        !           597:        /* Set the LineCTL quintuplet based on adapter
        !           598:           configuration read from EEPROM */
        !           599:        if ((eth_adapter_cnf & A_CNF_EXTND_10B_2) &&
        !           600:            (eth_adapter_cnf & A_CNF_LOW_RX_SQUELCH))
        !           601:                eth_linectl = LOW_RX_SQUELCH;
        !           602:        else
        !           603:                eth_linectl = 0;
        !           604:        
        !           605:        /* check to make sure that they have the "right"
        !           606:           hardware available */
        !           607:        switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) {
        !           608:        case A_CNF_MEDIA_10B_T: result = eth_adapter_cnf & A_CNF_10B_T;
        !           609:                break;
        !           610:        case A_CNF_MEDIA_AUI:   result = eth_adapter_cnf & A_CNF_AUI;
        !           611:                break;
        !           612:        case A_CNF_MEDIA_10B_2: result = eth_adapter_cnf & A_CNF_10B_2;
        !           613:                break;
        !           614:        default: result = eth_adapter_cnf & (A_CNF_10B_T | A_CNF_AUI |
        !           615:                                             A_CNF_10B_2);
        !           616:        }
        !           617:        if (!result) {
        !           618:                printf("cs: EEPROM is configured for unavailable media\n");
        !           619:        error:
        !           620:                writereg(PP_LineCTL, readreg(PP_LineCTL) &
        !           621:                         ~(SERIAL_TX_ON | SERIAL_RX_ON));
        !           622:                outw(PP_ChipID, eth_nic_base + ADD_PORT);
        !           623:                return 0;
        !           624:        }
        !           625: #endif
        !           626:        /* Initialize the card for probing of the attached media */
        !           627:        cs89x0_reset(nic);
        !           628:        
        !           629:        /* set the hardware to the configured choice */
        !           630:        switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) {
        !           631:        case A_CNF_MEDIA_10B_T:
        !           632:                result = detect_tp();
        !           633:                if (!result) {
        !           634:                        clrline();
        !           635:                        printf("10Base-T (RJ-45%s",
        !           636:                               ") has no cable\n"); }
        !           637:                /* check "ignore missing media" bit */
        !           638:                if (eth_auto_neg_cnf & IMM_BIT)
        !           639:                        /* Yes! I don't care if I see a link pulse */
        !           640:                        result = A_CNF_MEDIA_10B_T;
        !           641:                break;
        !           642:        case A_CNF_MEDIA_AUI:
        !           643:                result = detect_aui(nic);
        !           644:                if (!result) {
        !           645:                        clrline();
        !           646:                        printf("10Base-5 (AUI%s",
        !           647:                               ") has no cable\n"); }
        !           648:                /* check "ignore missing media" bit */
        !           649:                if (eth_auto_neg_cnf & IMM_BIT)
        !           650:                        /* Yes! I don't care if I see a carrrier */
        !           651:                        result = A_CNF_MEDIA_AUI;
        !           652:                break;
        !           653:        case A_CNF_MEDIA_10B_2:
        !           654:                result = detect_bnc(nic);
        !           655:                if (!result) {
        !           656:                        clrline();
        !           657:                        printf("10Base-2 (BNC%s",
        !           658:                               ") has no cable\n"); }
        !           659:                /* check "ignore missing media" bit */
        !           660:                if (eth_auto_neg_cnf & IMM_BIT)
        !           661:                        /* Yes! I don't care if I can xmit a packet */
        !           662:                        result = A_CNF_MEDIA_10B_2;
        !           663:                break;
        !           664:        case A_CNF_MEDIA_AUTO:
        !           665:                writereg(PP_LineCTL, eth_linectl | AUTO_AUI_10BASET);
        !           666:                if (eth_adapter_cnf & A_CNF_10B_T)
        !           667:                        if ((result = detect_tp()) != 0)
        !           668:                                break;
        !           669:                if (eth_adapter_cnf & A_CNF_AUI)
        !           670:                        if ((result = detect_aui(nic)) != 0)
        !           671:                                break;
        !           672:                if (eth_adapter_cnf & A_CNF_10B_2)
        !           673:                        if ((result = detect_bnc(nic)) != 0)
        !           674:                                break;
        !           675:                clrline(); printf("no media detected\n");
        !           676:                goto error;
        !           677:        }
        !           678:        clrline();
        !           679:        switch(result) {
        !           680:        case 0:                 printf("no network cable attached to configured media\n");
        !           681:                goto error;
        !           682:        case A_CNF_MEDIA_10B_T: printf("using 10Base-T (RJ-45)\n");
        !           683:                break;
        !           684:        case A_CNF_MEDIA_AUI:   printf("using 10Base-5 (AUI)\n");
        !           685:                break;
        !           686:        case A_CNF_MEDIA_10B_2: printf("using 10Base-2 (BNC)\n");
        !           687:                break;
        !           688:        }
        !           689:        
        !           690:        /* Turn on both receive and transmit operations */
        !           691:        writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_RX_ON |
        !           692:                 SERIAL_TX_ON);
        !           693:        
        !           694:        return 0;
        !           695: #ifdef EMBEDDED
        !           696:  error:
        !           697:        writereg(PP_LineCTL, readreg(PP_LineCTL) &
        !           698:                 ~(SERIAL_TX_ON | SERIAL_RX_ON));
        !           699:        outw(PP_ChipID, eth_nic_base + ADD_PORT);
        !           700:        return 0;
        !           701: #endif
        !           702: 
        !           703:        nic->nic_op   = &cs89x0_operations;
        !           704:        return 1;
        !           705: }
        !           706: 
        !           707: static void cs89x0_disable ( struct nic *nic,
        !           708:                             struct isa_device *isa __unused ) {
        !           709:        cs89x0_reset(nic);
        !           710: }
        !           711:        
        !           712: static isa_probe_addr_t cs89x0_probe_addrs[] = { 
        !           713: #ifndef EMBEDDED
        !           714:        /* use "conservative" default values for autoprobing */
        !           715:        0x300, 0x320, 0x340, 0x200, 0x220, 0x240,
        !           716:        0x260, 0x280, 0x2a0, 0x2c0, 0x2e0,
        !           717:        /* if that did not work, then be more aggressive */
        !           718:        0x301, 0x321, 0x341, 0x201, 0x221, 0x241,
        !           719:        0x261, 0x281, 0x2a1, 0x2c1, 0x2e1,
        !           720: #else
        !           721:        0x01000300,
        !           722: #endif
        !           723: };
        !           724: 
        !           725: ISA_DRIVER ( cs89x0_driver, cs89x0_probe_addrs, cs89x0_probe_addr,
        !           726:             ISAPNP_VENDOR('C','S','C'), 0x0007 );
        !           727: 
        !           728: DRIVER ( "cs89x0", nic_driver, isa_driver, cs89x0_driver,
        !           729:         cs89x0_probe, cs89x0_disable );
        !           730: 
        !           731: ISA_ROM ( "cs89x0", "Crystal Semiconductor CS89x0" );
        !           732: 
        !           733: /*
        !           734:  * Local variables:
        !           735:  *  c-basic-offset: 8
        !           736:  *  c-indent-level: 8
        !           737:  *  tab-width: 8
        !           738:  * End:
        !           739:  */

unix.superglobalmegacorp.com

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