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