source: bootcd/isolinux/syslinux-6.03/gpxe/src/drivers/net/cs89x0.c @ dd1be7c

Last change on this file since dd1be7c was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 20.1 KB
Line 
1#ifdef ALLMULTI
2#error multicast support is not yet implemented
3#endif
4
5/**
6   Per an email message from Russ Nelson <nelson@crynwr.com> on
7   18 March 2008 this file is now licensed under GPL Version 2.
8
9   From: Russ Nelson <nelson@crynwr.com>
10   Date: Tue, 18 Mar 2008 12:42:00 -0400
11   Subject: Re: [Etherboot-developers] cs89x0 driver in etherboot
12   -- quote from email
13   As copyright holder, if I say it doesn't conflict with the GPL,
14   then it doesn't conflict with the GPL.
15
16   However, there's no point in causing people's brains to overheat,
17   so yes, I grant permission for the code to be relicensed under the
18   GPLv2.  Please make sure that this change in licensing makes its
19   way upstream.  -russ
20   -- quote from email
21**/
22
23FILE_LICENCE ( GPL2_ONLY );
24
25/* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for etherboot. */
26/*
27  Permission is granted to distribute the enclosed cs89x0.[ch] driver
28  only in conjunction with the Etherboot package.  The code is
29  ordinarily distributed under the GPL.
30 
31  Russ Nelson, January 2000
32
33  ChangeLog:
34
35  Thu Dec 6 22:40:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
36
37  * disabled all "advanced" features; this should make the code more reliable
38
39  * reorganized the reset function
40
41  * always reset the address port, so that autoprobing will continue working
42
43  * some cosmetic changes
44
45  * 2.5
46
47  Thu Dec 5 21:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
48
49  * tested the code against a CS8900 card
50
51  * lots of minor bug fixes and adjustments
52
53  * this is the first release, that actually works! it still requires some
54    changes in order to be more tolerant to different environments
55
56  * 4
57
58  Fri Nov 22 23:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
59
60  * read the manuals for the CS89x0 chipsets and took note of all the
61    changes that will be neccessary in order to adapt Russel Nelson's code
62    to the requirements of a BOOT-Prom
63
64  * 6
65
66  Thu Nov 19 22:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
67
68  * Synched with Russel Nelson's current code (v1.00)
69
70  * 2
71
72  Thu Nov 12 18:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
73
74  * Cleaned up some of the code and tried to optimize the code size.
75
76  * 1.5
77
78  Sun Nov 10 16:30:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
79
80  * First experimental release. This code compiles fine, but I
81  have no way of testing whether it actually works.
82
83  * I did not (yet) bother to make the code 16bit aware, so for
84  the time being, it will only work for Etherboot/32.
85
86  * 12
87
88  */
89
90#include <errno.h>
91#include <gpxe/ethernet.h>
92#include "etherboot.h"
93#include "nic.h"
94#include <gpxe/isa.h>
95#include "console.h"
96#include "cs89x0.h"
97
98static unsigned short   eth_nic_base;
99static unsigned long    eth_mem_start;
100static unsigned short   eth_irqno;
101static unsigned short   eth_cs_type;    /* one of: CS8900, CS8920, CS8920M  */
102static unsigned short   eth_auto_neg_cnf;
103static unsigned short   eth_adapter_cnf;
104static unsigned short   eth_linectl;
105
106/*************************************************************************
107        CS89x0 - specific routines
108**************************************************************************/
109
110static inline int readreg(int portno)
111{
112        outw(portno, eth_nic_base + ADD_PORT);
113        return inw(eth_nic_base + DATA_PORT);
114}
115
116static 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/*************************************************************************
124EEPROM access
125**************************************************************************/
126
127static 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
140static 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
169static 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/*************************************************************************
183Activate all of the available media and probe for network
184**************************************************************************/
185
186static void clrline(void)
187{
188        int i;
189
190        putchar('\r');
191        for (i = 79; i--; ) putchar(' ');
192        printf("\rcs: ");
193        return;
194}
195
196static 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
215static 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 */
262static 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
301static 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
314static 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/**************************************************************************
328ETH_RESET - Reset adapter
329***************************************************************************/
330
331static 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/**************************************************************************
387ETH_TRANSMIT - Transmit a frame
388***************************************************************************/
389
390static 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
405retry:
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/**************************************************************************
439ETH_POLL - Wait for a frame
440***************************************************************************/
441
442static 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
461static 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
473static struct nic_operations cs89x0_operations = {
474        .connect        = dummy_connect,
475        .poll           = cs89x0_poll,
476        .transmit       = cs89x0_transmit,
477        .irq            = cs89x0_irq,
478};
479
480/**************************************************************************
481ETH_PROBE - Look for an adapter
482***************************************************************************/
483
484static 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
501static 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
707static void cs89x0_disable ( struct nic *nic,
708                             struct isa_device *isa __unused ) {
709        cs89x0_reset(nic);
710}
711       
712static 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
725ISA_DRIVER ( cs89x0_driver, cs89x0_probe_addrs, cs89x0_probe_addr,
726             ISAPNP_VENDOR('C','S','C'), 0x0007 );
727
728DRIVER ( "cs89x0", nic_driver, isa_driver, cs89x0_driver,
729         cs89x0_probe, cs89x0_disable );
730
731ISA_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 */
Note: See TracBrowser for help on using the repository browser.