|
|
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: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.