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