Annotation of qemu/roms/ipxe/src/drivers/net/cs89x0.c, revision 1.1.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.