|
|
1.1 root 1: #ifdef ALLMULTI
2: #error multicast support is not yet implemented
3: #endif
4:
5: /**
6: Per an email message from Russ Nelson <[email protected]> on
7: 18 March 2008 this file is now licensed under GPL Version 2.
8:
9: From: Russ Nelson <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <ipxe/ethernet.h>
92: #include "etherboot.h"
93: #include "nic.h"
94: #include <ipxe/isa.h>
95: #include <ipxe/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:
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:
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:
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:
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:
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:
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:
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:
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 */
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:
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:
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:
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:
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:
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:
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:
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:
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:
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: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.