• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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@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@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@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@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@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 
readreg(int portno)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 
writereg(int portno,int value)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 
wait_eeprom_ready(void)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 
get_eeprom_data(int off,int len,unsigned short * buffer)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 
get_eeprom_chksum(int off,int len,unsigned short * buffer)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 
clrline(void)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 
control_dc_dc(int on_not_off)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 
detect_tp(void)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 */
send_test_pkt(struct nic * nic)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 
detect_aui(struct nic * nic)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 
detect_bnc(struct nic * nic)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 
cs89x0_reset(struct nic * nic)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 
cs89x0_transmit(struct nic * nic,const char * d,unsigned int t,unsigned int s,const char * p)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 
cs89x0_poll(struct nic * nic)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 
cs89x0_disable(struct nic * nic)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 
cs89x0_probe(struct nic * nic,unsigned short * probe_addrs)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