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