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