#include <errno.h>#include <gpxe/ethernet.h>#include "etherboot.h"#include "nic.h"#include <gpxe/isa.h>#include "console.h"#include "cs89x0.h"Go to the source code of this file.
Functions | |
| FILE_LICENCE (GPL2_ONLY) | |
| Per an email message from Russ Nelson <nelson@crynwr.com> on 18 March 2008 this file is now licensed under GPL Version 2. | |
| static int | readreg (int portno) |
| static void | writereg (int portno, int value) |
| static int | wait_eeprom_ready (void) |
| static int | get_eeprom_data (int off, int len, unsigned short *buffer) |
| static int | get_eeprom_chksum (int off __unused, int len, unsigned short *buffer) |
| static void | clrline (void) |
| static void | control_dc_dc (int on_not_off) |
| static int | detect_tp (void) |
| static int | send_test_pkt (struct nic *nic) |
| static int | detect_aui (struct nic *nic) |
| static int | detect_bnc (struct nic *nic) |
| static void | cs89x0_reset (struct nic *nic) |
| static void | cs89x0_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p) |
| static int | cs89x0_poll (struct nic *nic, int retrieve) |
| static void | cs89x0_irq (struct nic *nic __unused, irq_action_t action __unused) |
| static int | cs89x0_probe_addr (isa_probe_addr_t ioaddr) |
| static int | cs89x0_probe (struct nic *nic, struct isa_device *isa __unused) |
| static void | cs89x0_disable (struct nic *nic, struct isa_device *isa __unused) |
| ISA_DRIVER (cs89x0_driver, cs89x0_probe_addrs, cs89x0_probe_addr, ISAPNP_VENDOR('C','S','C'), 0x0007) | |
| DRIVER ("cs89x0", nic_driver, isa_driver, cs89x0_driver, cs89x0_probe, cs89x0_disable) | |
| ISA_ROM ("cs89x0","Crystal Semiconductor CS89x0") | |
Variables | |
| static unsigned short | eth_nic_base |
| static unsigned long | eth_mem_start |
| static unsigned short | eth_irqno |
| static unsigned short | eth_cs_type |
| static unsigned short | eth_auto_neg_cnf |
| static unsigned short | eth_adapter_cnf |
| static unsigned short | eth_linectl |
| static struct nic_operations | cs89x0_operations |
| static isa_probe_addr_t | cs89x0_probe_addrs [] |
| FILE_LICENCE | ( | GPL2_ONLY | ) |
Per an email message from Russ Nelson <nelson@crynwr.com> on 18 March 2008 this file is now licensed under GPL Version 2.
From: Russ Nelson <nelson@crynwr.com> Date: Tue, 18 Mar 2008 12:42:00 -0400 Subject: Re: [Etherboot-developers] cs89x0 driver in etherboot -- quote from email As copyright holder, if I say it doesn't conflict with the GPL, then it doesn't conflict with the GPL.
However, there's no point in causing people's brains to overheat, so yes, I grant permission for the code to be relicensed under the GPLv2. Please make sure that this change in licensing makes its way upstream. -russ -- quote from email
| static int readreg | ( | int | portno | ) | [inline, static] |
Definition at line 110 of file cs89x0.c.
References ADD_PORT, DATA_PORT, eth_nic_base, inw, and outw.
Referenced by cs89x0_poll(), cs89x0_probe(), cs89x0_reset(), cs89x0_transmit(), detect_tp(), get_eeprom_data(), send_test_pkt(), and wait_eeprom_ready().
00111 { 00112 outw(portno, eth_nic_base + ADD_PORT); 00113 return inw(eth_nic_base + DATA_PORT); 00114 }
| static void writereg | ( | int | portno, | |
| int | value | |||
| ) | [inline, static] |
Definition at line 116 of file cs89x0.c.
References ADD_PORT, DATA_PORT, eth_nic_base, and outw.
Referenced by control_dc_dc(), cs89x0_probe(), cs89x0_reset(), detect_aui(), detect_bnc(), detect_tp(), get_eeprom_data(), and send_test_pkt().
00117 { 00118 outw(portno, eth_nic_base + ADD_PORT); 00119 outw(value, eth_nic_base + DATA_PORT); 00120 return; 00121 }
| static int wait_eeprom_ready | ( | void | ) | [static] |
Definition at line 127 of file cs89x0.c.
References currticks(), PP_SelfST, readreg(), SI_BUSY, and TICKS_PER_SEC.
Referenced by get_eeprom_data().
00128 { 00129 unsigned long tmo = currticks() + 4*TICKS_PER_SEC; 00130 00131 /* check to see if the EEPROM is ready, a timeout is used - 00132 just in case EEPROM is ready when SI_BUSY in the 00133 PP_SelfST is clear */ 00134 while(readreg(PP_SelfST) & SI_BUSY) { 00135 if (currticks() >= tmo) 00136 return -1; } 00137 return 0; 00138 }
| static int get_eeprom_data | ( | int | off, | |
| int | len, | |||
| unsigned short * | buffer | |||
| ) | [static] |
Definition at line 140 of file cs89x0.c.
References EEPROM_READ_CMD, PP_EECMD, PP_EEData, printf(), putchar(), readreg(), wait_eeprom_ready(), and writereg().
Referenced by cs89x0_probe().
00141 { 00142 int i; 00143 00144 #ifdef EDEBUG 00145 printf("\ncs: EEPROM data from %hX for %hX:",off,len); 00146 #endif 00147 for (i = 0; i < len; i++) { 00148 if (wait_eeprom_ready() < 0) 00149 return -1; 00150 /* Now send the EEPROM read command and EEPROM location 00151 to read */ 00152 writereg(PP_EECMD, (off + i) | EEPROM_READ_CMD); 00153 if (wait_eeprom_ready() < 0) 00154 return -1; 00155 buffer[i] = readreg(PP_EEData); 00156 #ifdef EDEBUG 00157 if (!(i%10)) 00158 printf("\ncs: "); 00159 printf("%hX ", buffer[i]); 00160 #endif 00161 } 00162 #ifdef EDEBUG 00163 putchar('\n'); 00164 #endif 00165 00166 return(0); 00167 }
| static int get_eeprom_chksum | ( | int off | __unused, | |
| int | len, | |||
| unsigned short * | buffer | |||
| ) | [static] |
Definition at line 169 of file cs89x0.c.
Referenced by cs89x0_probe().
00170 { 00171 int i, cksum; 00172 00173 cksum = 0; 00174 for (i = 0; i < len; i++) 00175 cksum += buffer[i]; 00176 cksum &= 0xffff; 00177 if (cksum == 0) 00178 return 0; 00179 return -1; 00180 }
| static void clrline | ( | void | ) | [static] |
Definition at line 186 of file cs89x0.c.
References printf(), and putchar().
Referenced by cs89x0_probe(), detect_aui(), detect_bnc(), and detect_tp().
00187 { 00188 int i; 00189 00190 putchar('\r'); 00191 for (i = 79; i--; ) putchar(' '); 00192 printf("\rcs: "); 00193 return; 00194 }
| static void control_dc_dc | ( | int | on_not_off | ) | [static] |
Definition at line 196 of file cs89x0.c.
References A_CNF_DC_DC_POLARITY, currticks(), eth_adapter_cnf, HCB1, HCB1_ENBL, PP_SelfCTL, TICKS_PER_SEC, and writereg().
Referenced by detect_aui(), detect_bnc(), and detect_tp().
00197 { 00198 unsigned int selfcontrol; 00199 unsigned long tmo = currticks() + TICKS_PER_SEC; 00200 00201 /* control the DC to DC convertor in the SelfControl register. */ 00202 selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */ 00203 if (((eth_adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off) 00204 selfcontrol |= HCB1; 00205 else 00206 selfcontrol &= ~HCB1; 00207 writereg(PP_SelfCTL, selfcontrol); 00208 00209 /* Wait for the DC/DC converter to power up - 1000ms */ 00210 while (currticks() < tmo); 00211 00212 return; 00213 }
| static int detect_tp | ( | void | ) | [static] |
Definition at line 215 of file cs89x0.c.
References A_CNF_MEDIA_10B_T, AUI_ONLY, AUTO_NEG_BITS, AUTO_NEG_BUSY, AUTO_NEG_ENABLE, AUTO_NEG_MASK, clrline(), control_dc_dc(), CS8900, currticks(), eth_auto_neg_cnf, eth_cs_type, eth_linectl, FDX_ACTIVE, LINK_OK, PP_AutoNegCTL, PP_AutoNegST, PP_LineCTL, PP_LineST, printf(), readreg(), TICKS_PER_SEC, and writereg().
Referenced by cs89x0_probe().
00216 { 00217 unsigned long tmo; 00218 00219 /* Turn on the chip auto detection of 10BT/ AUI */ 00220 00221 clrline(); printf("attempting %s:","TP"); 00222 00223 /* If connected to another full duplex capable 10-Base-T card 00224 the link pulses seem to be lost when the auto detect bit in 00225 the LineCTL is set. To overcome this the auto detect bit 00226 will be cleared whilst testing the 10-Base-T interface. 00227 This would not be necessary for the sparrow chip but is 00228 simpler to do it anyway. */ 00229 writereg(PP_LineCTL, eth_linectl &~ AUI_ONLY); 00230 control_dc_dc(0); 00231 00232 /* Delay for the hardware to work out if the TP cable is 00233 present - 150ms */ 00234 for (tmo = currticks() + 4; currticks() < tmo; ); 00235 00236 if ((readreg(PP_LineST) & LINK_OK) == 0) 00237 return 0; 00238 00239 if (eth_cs_type != CS8900) { 00240 00241 writereg(PP_AutoNegCTL, eth_auto_neg_cnf & AUTO_NEG_MASK); 00242 00243 if ((eth_auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) { 00244 printf(" negotiating duplex... "); 00245 while (readreg(PP_AutoNegST) & AUTO_NEG_BUSY) { 00246 if (currticks() - tmo > 40*TICKS_PER_SEC) { 00247 printf("time out "); 00248 break; 00249 } 00250 } 00251 } 00252 if (readreg(PP_AutoNegST) & FDX_ACTIVE) 00253 printf("using full duplex"); 00254 else 00255 printf("using half duplex"); 00256 } 00257 00258 return A_CNF_MEDIA_10B_T; 00259 }
| static int send_test_pkt | ( | struct nic * | nic | ) | [static] |
Definition at line 262 of file cs89x0.c.
References currticks(), ETH_ALEN, eth_nic_base, ETH_ZLEN, memcpy, nic::node_addr, outsw, outw, PP_BusST, PP_LineCTL, PP_TxEvent, printf(), readreg(), READY_FOR_TX_NOW, SERIAL_TX_ON, TX_AFTER_ALL, TX_CMD_PORT, TX_FRAME_PORT, TX_LEN_PORT, TX_OK, TX_SEND_OK_BITS, and writereg().
Referenced by detect_aui(), and detect_bnc().
00263 { 00264 static unsigned char testpacket[] = { 0,0,0,0,0,0, 0,0,0,0,0,0, 00265 0, 46, /*A 46 in network order */ 00266 0, 0, /*DSAP=0 & SSAP=0 fields */ 00267 0xf3,0 /*Control (Test Req+P bit set)*/ }; 00268 unsigned long tmo; 00269 00270 writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_TX_ON); 00271 00272 memcpy(testpacket, nic->node_addr, ETH_ALEN); 00273 memcpy(testpacket+ETH_ALEN, nic->node_addr, ETH_ALEN); 00274 00275 outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT); 00276 outw(ETH_ZLEN, eth_nic_base + TX_LEN_PORT); 00277 00278 /* Test to see if the chip has allocated memory for the packet */ 00279 for (tmo = currticks() + 2; 00280 (readreg(PP_BusST) & READY_FOR_TX_NOW) == 0; ) 00281 if (currticks() >= tmo) 00282 return(0); 00283 00284 /* Write the contents of the packet */ 00285 outsw(eth_nic_base + TX_FRAME_PORT, testpacket, 00286 (ETH_ZLEN+1)>>1); 00287 00288 printf(" sending test packet "); 00289 /* wait a couple of timer ticks for packet to be received */ 00290 for (tmo = currticks() + 2; currticks() < tmo; ); 00291 00292 if ((readreg(PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) { 00293 printf("succeeded"); 00294 return 1; 00295 } 00296 printf("failed"); 00297 return 0; 00298 }
| static int detect_aui | ( | struct nic * | nic | ) | [static] |
Definition at line 301 of file cs89x0.c.
References A_CNF_MEDIA_AUI, AUI_ONLY, AUTO_AUI_10BASET, clrline(), control_dc_dc(), eth_linectl, PP_LineCTL, printf(), send_test_pkt(), and writereg().
Referenced by cs89x0_probe().
00302 { 00303 clrline(); printf("attempting %s:","AUI"); 00304 control_dc_dc(0); 00305 00306 writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY); 00307 00308 if (send_test_pkt(nic)) { 00309 return A_CNF_MEDIA_AUI; } 00310 else 00311 return 0; 00312 }
| static int detect_bnc | ( | struct nic * | nic | ) | [static] |
Definition at line 314 of file cs89x0.c.
References A_CNF_MEDIA_10B_2, AUI_ONLY, AUTO_AUI_10BASET, clrline(), control_dc_dc(), eth_linectl, PP_LineCTL, printf(), send_test_pkt(), and writereg().
Referenced by cs89x0_probe().
00315 { 00316 clrline(); printf("attempting %s:","BNC"); 00317 control_dc_dc(1); 00318 00319 writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY); 00320 00321 if (send_test_pkt(nic)) { 00322 return A_CNF_MEDIA_10B_2; } 00323 else 00324 return 0; 00325 }
| static void cs89x0_reset | ( | struct nic * | nic | ) | [static] |
Definition at line 331 of file cs89x0.c.
References ADD_PORT, CS8900, currticks(), DATA_PORT, DEF_RX_ACCEPT, ETH_ALEN, eth_cs_type, eth_irqno, eth_mem_start, eth_nic_base, INIT_DONE, nic::node_addr, outb, outw, POWER_ON_RESET, PP_BufCFG, PP_BusCTL, PP_ChipID, PP_CS8920_ISAINT, PP_CS8920_ISAMemB, PP_IA, PP_RxCFG, PP_RxCTL, PP_SelfCTL, PP_SelfST, PP_TxCFG, readreg(), and writereg().
Referenced by cs89x0_disable(), cs89x0_probe(), and cs89x0_transmit().
00332 { 00333 int i; 00334 unsigned long reset_tmo; 00335 00336 writereg(PP_SelfCTL, readreg(PP_SelfCTL) | POWER_ON_RESET); 00337 00338 /* wait for two ticks; that is 2*55ms */ 00339 for (reset_tmo = currticks() + 2; currticks() < reset_tmo; ); 00340 00341 if (eth_cs_type != CS8900) { 00342 /* Hardware problem requires PNP registers to be reconfigured 00343 after a reset */ 00344 if (eth_irqno != 0xFFFF) { 00345 outw(PP_CS8920_ISAINT, eth_nic_base + ADD_PORT); 00346 outb(eth_irqno, eth_nic_base + DATA_PORT); 00347 outb(0, eth_nic_base + DATA_PORT + 1); } 00348 00349 if (eth_mem_start) { 00350 outw(PP_CS8920_ISAMemB, eth_nic_base + ADD_PORT); 00351 outb((eth_mem_start >> 8) & 0xff, eth_nic_base + DATA_PORT); 00352 outb((eth_mem_start >> 24) & 0xff, eth_nic_base + DATA_PORT + 1); } } 00353 00354 /* Wait until the chip is reset */ 00355 for (reset_tmo = currticks() + 2; 00356 (readreg(PP_SelfST) & INIT_DONE) == 0 && 00357 currticks() < reset_tmo; ); 00358 00359 /* disable interrupts and memory accesses */ 00360 writereg(PP_BusCTL, 0); 00361 00362 /* set the ethernet address */ 00363 for (i=0; i < ETH_ALEN/2; i++) 00364 writereg(PP_IA+i*2, 00365 nic->node_addr[i*2] | 00366 (nic->node_addr[i*2+1] << 8)); 00367 00368 /* receive only error free packets addressed to this card */ 00369 writereg(PP_RxCTL, DEF_RX_ACCEPT); 00370 00371 /* do not generate any interrupts on receive operations */ 00372 writereg(PP_RxCFG, 0); 00373 00374 /* do not generate any interrupts on transmit operations */ 00375 writereg(PP_TxCFG, 0); 00376 00377 /* do not generate any interrupts on buffer operations */ 00378 writereg(PP_BufCFG, 0); 00379 00380 /* reset address port, so that autoprobing will keep working */ 00381 outw(PP_ChipID, eth_nic_base + ADD_PORT); 00382 00383 return; 00384 }
| static void cs89x0_transmit | ( | struct nic * | nic, | |
| const char * | d, | |||
| unsigned int | t, | |||
| unsigned int | s, | |||
| const char * | p | |||
| ) | [static] |
Definition at line 390 of file cs89x0.c.
References cs89x0_reset(), currticks(), ETH_ALEN, ETH_HLEN, eth_nic_base, ETH_ZLEN, nic::node_addr, outsw, outw, PP_BusST, PP_TxEvent, printf(), readreg(), READY_FOR_TX_NOW, TICKS_PER_SEC, TX_AFTER_ALL, TX_CMD_PORT, TX_FRAME_PORT, TX_LEN_PORT, TX_OK, and TX_SEND_OK_BITS.
00396 { 00397 unsigned long tmo; 00398 int sr; 00399 00400 /* does this size have to be rounded??? please, 00401 somebody have a look in the specs */ 00402 if ((sr = ((s + ETH_HLEN + 1)&~1)) < ETH_ZLEN) 00403 sr = ETH_ZLEN; 00404 00405 retry: 00406 /* initiate a transmit sequence */ 00407 outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT); 00408 outw(sr, eth_nic_base + TX_LEN_PORT); 00409 00410 /* Test to see if the chip has allocated memory for the packet */ 00411 if ((readreg(PP_BusST) & READY_FOR_TX_NOW) == 0) { 00412 /* Oops... this should not happen! */ 00413 printf("cs: unable to send packet; retrying...\n"); 00414 for (tmo = currticks() + 5*TICKS_PER_SEC; currticks() < tmo; ); 00415 cs89x0_reset(nic); 00416 goto retry; } 00417 00418 /* Write the contents of the packet */ 00419 outsw(eth_nic_base + TX_FRAME_PORT, d, ETH_ALEN/2); 00420 outsw(eth_nic_base + TX_FRAME_PORT, nic->node_addr, 00421 ETH_ALEN/2); 00422 outw(((t >> 8)&0xFF)|(t << 8), eth_nic_base + TX_FRAME_PORT); 00423 outsw(eth_nic_base + TX_FRAME_PORT, p, (s+1)/2); 00424 for (sr = sr/2 - (s+1)/2 - ETH_ALEN - 1; sr > 0; sr--) 00425 outw(0, eth_nic_base + TX_FRAME_PORT); 00426 00427 /* wait for transfer to succeed */ 00428 for (tmo = currticks()+5*TICKS_PER_SEC; 00429 (s = readreg(PP_TxEvent)&~0x1F) == 0 && currticks() < tmo;) 00430 /* nothing */ ; 00431 if ((s & TX_SEND_OK_BITS) != TX_OK) { 00432 printf("\ntransmission error %#hX\n", s); 00433 } 00434 00435 return; 00436 }
| static int cs89x0_poll | ( | struct nic * | nic, | |
| int | retrieve | |||
| ) | [static] |
Definition at line 442 of file cs89x0.c.
References eth_nic_base, insw, inw, nic::packet, nic::packetlen, PP_RxEvent, readreg(), RX_FRAME_PORT, and RX_OK.
00443 { 00444 int status; 00445 00446 status = readreg(PP_RxEvent); 00447 00448 if ((status & RX_OK) == 0) 00449 return(0); 00450 00451 if ( ! retrieve ) return 1; 00452 00453 status = inw(eth_nic_base + RX_FRAME_PORT); 00454 nic->packetlen = inw(eth_nic_base + RX_FRAME_PORT); 00455 insw(eth_nic_base + RX_FRAME_PORT, nic->packet, nic->packetlen >> 1); 00456 if (nic->packetlen & 1) 00457 nic->packet[nic->packetlen-1] = inw(eth_nic_base + RX_FRAME_PORT); 00458 return 1; 00459 }
| static void cs89x0_irq | ( | struct nic *nic | __unused, | |
| irq_action_t action | __unused | |||
| ) | [static] |
| static int cs89x0_probe_addr | ( | isa_probe_addr_t | ioaddr | ) | [static] |
Definition at line 484 of file cs89x0.c.
References ADD_MASK, ADD_PORT, ADD_SIG, CHIP_EISA_ID_SIG, DATA_PORT, inw, outw, and PP_ChipID.
00484 { 00485 /* if they give us an odd I/O address, then do ONE write to 00486 the address port, to get it back to address zero, where we 00487 expect to find the EISA signature word. */ 00488 if (ioaddr & 1) { 00489 ioaddr &= ~1; 00490 if ((inw(ioaddr + ADD_PORT) & ADD_MASK) != ADD_SIG) 00491 return 0; 00492 outw(PP_ChipID, ioaddr + ADD_PORT); 00493 } 00494 00495 if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) 00496 return 0; 00497 00498 return 1; 00499 }
| static int cs89x0_probe | ( | struct nic * | nic, | |
| struct isa_device *isa | __unused | |||
| ) | [static] |
Definition at line 501 of file cs89x0.c.
References A_CNF_10B_2, A_CNF_10B_T, A_CNF_AUI, A_CNF_EXTND_10B_2, A_CNF_LOW_RX_SQUELCH, A_CNF_MEDIA_10B_2, A_CNF_MEDIA_10B_T, A_CNF_MEDIA_AUI, A_CNF_MEDIA_AUTO, A_CNF_MEDIA_TYPE, ADAPTER_CNF_OFFSET, ADD_PORT, AUTO_AUI_10BASET, AUTO_NEG_CNF_OFFSET, CHKSUM_LEN, clrline(), CS8900, CS8920_NO_INTS, CS8920M, cs89x0_reset(), DBG, detect_aui(), detect_bnc(), detect_tp(), EE_AUTO_NEG_ENABLE, EEPROM_PRESENT, eth_adapter_cnf, ETH_ALEN, eth_auto_neg_cnf, eth_cs_type, eth_irqno, eth_linectl, eth_mem_start, eth_nic_base, eth_ntoa(), get_eeprom_chksum(), get_eeprom_data(), IMM_BIT, INT_NO_MASK, nic::ioaddr, nic::irqno, ISA_CNF_OFFSET, LOW_RX_SQUELCH, memcpy, nic::nic_op, nic::node_addr, outw, PACKET_PAGE_OFFSET, PP_ChipID, PP_CS8920_ISAINT, PP_LineCTL, PP_SelfST, printf(), PRODUCT_ID_ADD, readreg(), REVISON_BITS, SERIAL_RX_ON, SERIAL_TX_ON, START_EEPROM_DATA, and writereg().
00501 { 00502 int i, result = -1; 00503 unsigned rev_type = 0, isa_cnf, cs_revision; 00504 unsigned short eeprom_buff[CHKSUM_LEN]; 00505 00506 nic->ioaddr &= ~1; /* LSB = 1 indicates a more aggressive probe */ 00507 eth_nic_base = nic->ioaddr; 00508 00509 /* get the chip type */ 00510 rev_type = readreg(PRODUCT_ID_ADD); 00511 eth_cs_type = rev_type &~ REVISON_BITS; 00512 cs_revision = ((rev_type & REVISON_BITS) >> 8) + 'A'; 00513 00514 printf("\ncs: cs89%c0%s rev %c, base %#hX", 00515 eth_cs_type==CS8900?'0':'2', 00516 eth_cs_type==CS8920M?"M":"", 00517 cs_revision, 00518 eth_nic_base); 00519 #ifndef EMBEDDED 00520 /* First check to see if an EEPROM is attached*/ 00521 if ((readreg(PP_SelfST) & EEPROM_PRESENT) == 0) { 00522 printf("\ncs: no EEPROM...\n"); 00523 outw(PP_ChipID, eth_nic_base + ADD_PORT); 00524 return 0; 00525 } else if (get_eeprom_data(START_EEPROM_DATA,CHKSUM_LEN, 00526 eeprom_buff) < 0) { 00527 printf("\ncs: EEPROM read failed...\n"); 00528 outw(PP_ChipID, eth_nic_base + ADD_PORT); 00529 return 0; 00530 } else if (get_eeprom_chksum(START_EEPROM_DATA,CHKSUM_LEN, 00531 eeprom_buff) < 0) { 00532 printf("\ncs: EEPROM checksum bad...\n"); 00533 outw(PP_ChipID, eth_nic_base + ADD_PORT); 00534 return 0; 00535 } 00536 00537 /* get transmission control word but keep the 00538 autonegotiation bits */ 00539 eth_auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2]; 00540 /* Store adapter configuration */ 00541 eth_adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET/2]; 00542 /* Store ISA configuration */ 00543 isa_cnf = eeprom_buff[ISA_CNF_OFFSET/2]; 00544 00545 /* store the initial memory base address */ 00546 eth_mem_start = eeprom_buff[PACKET_PAGE_OFFSET/2] << 8; 00547 00548 printf("%s%s%s, addr ", 00549 (eth_adapter_cnf & A_CNF_10B_T)?", RJ-45":"", 00550 (eth_adapter_cnf & A_CNF_AUI)?", AUI":"", 00551 (eth_adapter_cnf & A_CNF_10B_2)?", BNC":""); 00552 00553 /* If this is a CS8900 then no pnp soft */ 00554 if (eth_cs_type != CS8900 && 00555 /* Check if the ISA IRQ has been set */ 00556 (i = readreg(PP_CS8920_ISAINT) & 0xff, 00557 (i != 0 && i < CS8920_NO_INTS))) 00558 eth_irqno = i; 00559 else { 00560 i = isa_cnf & INT_NO_MASK; 00561 if (eth_cs_type == CS8900) { 00562 /* the table that follows is dependent 00563 upon how you wired up your cs8900 00564 in your system. The table is the 00565 same as the cs8900 engineering demo 00566 board. irq_map also depends on the 00567 contents of the table. Also see 00568 write_irq, which is the reverse 00569 mapping of the table below. */ 00570 if (i < 4) i = "\012\013\014\005"[i]; 00571 else printf("\ncs: BUG: isa_config is %d\n", i); } 00572 eth_irqno = i; } 00573 00574 nic->irqno = eth_irqno; 00575 00576 /* Retrieve and print the ethernet address. */ 00577 for (i=0; i<ETH_ALEN; i++) { 00578 nic->node_addr[i] = ((unsigned char *)eeprom_buff)[i]; 00579 } 00580 00581 DBG ( "%s\n", eth_ntoa ( nic->node_addr ) ); 00582 00583 #endif 00584 #ifdef EMBEDDED 00585 /* Retrieve and print the ethernet address. */ 00586 { 00587 unsigned char MAC_HW_ADDR[6]={MAC_HW_ADDR_DRV}; 00588 memcpy(nic->node_addr, MAC_HW_ADDR, 6); 00589 } 00590 00591 DBG ( "%s\n", eth_ntoa ( nic->node_addr ) ); 00592 00593 eth_adapter_cnf = A_CNF_10B_T | A_CNF_MEDIA_10B_T; 00594 eth_auto_neg_cnf = EE_AUTO_NEG_ENABLE | IMM_BIT; 00595 #endif 00596 #ifndef EMBEDDED 00597 /* Set the LineCTL quintuplet based on adapter 00598 configuration read from EEPROM */ 00599 if ((eth_adapter_cnf & A_CNF_EXTND_10B_2) && 00600 (eth_adapter_cnf & A_CNF_LOW_RX_SQUELCH)) 00601 eth_linectl = LOW_RX_SQUELCH; 00602 else 00603 eth_linectl = 0; 00604 00605 /* check to make sure that they have the "right" 00606 hardware available */ 00607 switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) { 00608 case A_CNF_MEDIA_10B_T: result = eth_adapter_cnf & A_CNF_10B_T; 00609 break; 00610 case A_CNF_MEDIA_AUI: result = eth_adapter_cnf & A_CNF_AUI; 00611 break; 00612 case A_CNF_MEDIA_10B_2: result = eth_adapter_cnf & A_CNF_10B_2; 00613 break; 00614 default: result = eth_adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | 00615 A_CNF_10B_2); 00616 } 00617 if (!result) { 00618 printf("cs: EEPROM is configured for unavailable media\n"); 00619 error: 00620 writereg(PP_LineCTL, readreg(PP_LineCTL) & 00621 ~(SERIAL_TX_ON | SERIAL_RX_ON)); 00622 outw(PP_ChipID, eth_nic_base + ADD_PORT); 00623 return 0; 00624 } 00625 #endif 00626 /* Initialize the card for probing of the attached media */ 00627 cs89x0_reset(nic); 00628 00629 /* set the hardware to the configured choice */ 00630 switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) { 00631 case A_CNF_MEDIA_10B_T: 00632 result = detect_tp(); 00633 if (!result) { 00634 clrline(); 00635 printf("10Base-T (RJ-45%s", 00636 ") has no cable\n"); } 00637 /* check "ignore missing media" bit */ 00638 if (eth_auto_neg_cnf & IMM_BIT) 00639 /* Yes! I don't care if I see a link pulse */ 00640 result = A_CNF_MEDIA_10B_T; 00641 break; 00642 case A_CNF_MEDIA_AUI: 00643 result = detect_aui(nic); 00644 if (!result) { 00645 clrline(); 00646 printf("10Base-5 (AUI%s", 00647 ") has no cable\n"); } 00648 /* check "ignore missing media" bit */ 00649 if (eth_auto_neg_cnf & IMM_BIT) 00650 /* Yes! I don't care if I see a carrrier */ 00651 result = A_CNF_MEDIA_AUI; 00652 break; 00653 case A_CNF_MEDIA_10B_2: 00654 result = detect_bnc(nic); 00655 if (!result) { 00656 clrline(); 00657 printf("10Base-2 (BNC%s", 00658 ") has no cable\n"); } 00659 /* check "ignore missing media" bit */ 00660 if (eth_auto_neg_cnf & IMM_BIT) 00661 /* Yes! I don't care if I can xmit a packet */ 00662 result = A_CNF_MEDIA_10B_2; 00663 break; 00664 case A_CNF_MEDIA_AUTO: 00665 writereg(PP_LineCTL, eth_linectl | AUTO_AUI_10BASET); 00666 if (eth_adapter_cnf & A_CNF_10B_T) 00667 if ((result = detect_tp()) != 0) 00668 break; 00669 if (eth_adapter_cnf & A_CNF_AUI) 00670 if ((result = detect_aui(nic)) != 0) 00671 break; 00672 if (eth_adapter_cnf & A_CNF_10B_2) 00673 if ((result = detect_bnc(nic)) != 0) 00674 break; 00675 clrline(); printf("no media detected\n"); 00676 goto error; 00677 } 00678 clrline(); 00679 switch(result) { 00680 case 0: printf("no network cable attached to configured media\n"); 00681 goto error; 00682 case A_CNF_MEDIA_10B_T: printf("using 10Base-T (RJ-45)\n"); 00683 break; 00684 case A_CNF_MEDIA_AUI: printf("using 10Base-5 (AUI)\n"); 00685 break; 00686 case A_CNF_MEDIA_10B_2: printf("using 10Base-2 (BNC)\n"); 00687 break; 00688 } 00689 00690 /* Turn on both receive and transmit operations */ 00691 writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_RX_ON | 00692 SERIAL_TX_ON); 00693 00694 return 0; 00695 #ifdef EMBEDDED 00696 error: 00697 writereg(PP_LineCTL, readreg(PP_LineCTL) & 00698 ~(SERIAL_TX_ON | SERIAL_RX_ON)); 00699 outw(PP_ChipID, eth_nic_base + ADD_PORT); 00700 return 0; 00701 #endif 00702 00703 nic->nic_op = &cs89x0_operations; 00704 return 1; 00705 }
| static void cs89x0_disable | ( | struct nic * | nic, | |
| struct isa_device *isa | __unused | |||
| ) | [static] |
Definition at line 707 of file cs89x0.c.
References cs89x0_reset().
00708 { 00709 cs89x0_reset(nic); 00710 }
| ISA_DRIVER | ( | cs89x0_driver | , | |
| cs89x0_probe_addrs | , | |||
| cs89x0_probe_addr | , | |||
| ISAPNP_VENDOR('C','S','C') | , | |||
| 0x0007 | ||||
| ) |
| DRIVER | ( | "cs89x0" | , | |
| nic_driver | , | |||
| isa_driver | , | |||
| cs89x0_driver | , | |||
| cs89x0_probe | , | |||
| cs89x0_disable | ||||
| ) |
| ISA_ROM | ( | "cs89x0" | , | |
| "Crystal Semiconductor CS89x0" | ||||
| ) |
unsigned short eth_nic_base [static] |
unsigned long eth_mem_start [static] |
unsigned short eth_irqno [static] |
unsigned short eth_cs_type [static] |
Definition at line 101 of file cs89x0.c.
Referenced by cs89x0_probe(), cs89x0_reset(), and detect_tp().
unsigned short eth_auto_neg_cnf [static] |
unsigned short eth_adapter_cnf [static] |
unsigned short eth_linectl [static] |
Definition at line 104 of file cs89x0.c.
Referenced by cs89x0_probe(), detect_aui(), detect_bnc(), and detect_tp().
struct nic_operations cs89x0_operations [static] |
Initial value:
{
.connect = dummy_connect,
.poll = cs89x0_poll,
.transmit = cs89x0_transmit,
.irq = cs89x0_irq,
}
isa_probe_addr_t cs89x0_probe_addrs[] [static] |
1.5.7.1