1 #ifdef ALLMULTI
2 #error multicast support is not yet implemented
3 #endif
4
5 /**
6 Per an email message from Russ Nelson <nelson@crynwr.com> on
7 18 March 2008 this file is now licensed under GPL Version 2.
8
9 From: Russ Nelson <nelson@crynwr.com>
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 <gutschk@math.uni-muenster.de>
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 <gutschk@math.uni-muenster.de>
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 <gutschk@math.uni-muenster.de>
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 <gutschk@math.uni-muenster.de>
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 <gutschk@math.uni-muenster.de>
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 <gutschk@math.uni-muenster.de>
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 <gpxe/ethernet.h>
92 #include "etherboot.h"
93 #include "nic.h"
94 #include <gpxe/isa.h>
95 #include "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
readreg(int portno)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
writereg(int portno,int value)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
wait_eeprom_ready(void)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
get_eeprom_data(int off,int len,unsigned short * buffer)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
get_eeprom_chksum(int off __unused,int len,unsigned short * buffer)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
clrline(void)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
control_dc_dc(int on_not_off)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
detect_tp(void)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 */
send_test_pkt(struct nic * nic)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
detect_aui(struct nic * nic)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
detect_bnc(struct nic * nic)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
cs89x0_reset(struct nic * nic)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
cs89x0_transmit(struct nic * nic,const char * d,unsigned int t,unsigned int s,const char * p)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
cs89x0_poll(struct nic * nic,int retrieve)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
cs89x0_irq(struct nic * nic __unused,irq_action_t action __unused)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
cs89x0_probe_addr(isa_probe_addr_t ioaddr)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
cs89x0_probe(struct nic * nic,struct isa_device * isa __unused)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
cs89x0_disable(struct nic * nic,struct isa_device * isa __unused)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 */
740