~smartboyhw/wubi/bug-1080090-new

« back to all changes in this revision

Viewing changes to src/grub4dos/netboot/.svn/text-base/cs89x0.c.svn-base

  • Committer: Howard Chan
  • Date: 2012-11-20 10:16:05 UTC
  • Revision ID: smartboyhw@gmail.com-20121120101605-qfmjfsdynpzg9an9
Added images

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for grub4dos.
2
 
 *
3
 
 *  Copyright (C) 2007 Tinybit <tinybit@tom.com>
4
 
 *  Copyright (C) 1997-2007 Ken Yap <ken.yap@acm.org>
5
 
 *  Copyright (C) 1996-2007 Markus Gutschke <gutschk@math.uni-muenster.de>
6
 
 *  Copyright (C) 1988-2007 Russell Nelson, Crynwr Software
7
 
 *
8
 
 *  This program is free software; you can redistribute it and/or modify
9
 
 *  it under the terms of the GNU General Public License version 1 or
10
 
 *  version 2 as published by the Free Software Foundation.
11
 
 *
12
 
 *  This program is distributed in the hope that it will be useful,
13
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 *  GNU General Public License for more details.
16
 
 *
17
 
 *  You should have received a copy of the GNU General Public License
18
 
 *  along with this program; if not, write to the Free Software
19
 
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
 
 */
21
 
 
22
 
 
23
 
/*
24
 
 
25
 
In August 2, 2007, Sascha Sommer <ssommer@suse.de> posted a message to
26
 
the grub4dos-devel@gna.org mailing list as follows:
27
 
 
28
 
-------------------------------------------------------------------------------
29
 
        Subject:        [Grub4dos-devel] cs89x0.c driver
30
 
 
31
 
        Hi,
32
 
 
33
 
        the file netboot/cs98x0.txt contains the following statement:
34
 
 
35
 
        "Permission is granted to distribute the enclosed cs89x0.[ch] driver
36
 
        only in conjunction with the Etherboot package.  The code is
37
 
        ordinarily distributed under the GPL.
38
 
 
39
 
                        Russ Nelson, January 2000"
40
 
 
41
 
        So it looks like these files cannot be distributed with grub4dos. 
42
 
        As the Makefile in the netboot dir contains following statements
43
 
                "# Don't build the netboot support by default."
44
 
        I wonder if the cs89x0 driver cannot be removed from the grub4dos
45
 
        distribution.
46
 
 
47
 
                Regards
48
 
 
49
 
                Sascha
50
 
-------------------------------------------------------------------------------
51
 
 
52
 
In reply to the doubts above, I make the following note on the license issue,
53
 
and claim we are distributing the code under GPL at the very beginning of the
54
 
file.
55
 
 
56
 
In etherboot-4.2 which was released in June 5, 1999, the files cs89x0.[ch]
57
 
have this copyright notice by Markus Gutschke(gutschk@math.uni-muenster.de):
58
 
 
59
 
===============================================================================
60
 
  This code is heavily based on the linux driver as written by
61
 
  Russell Nelson <nelson@crynwr.com> and Donald Becker
62
 
  <becker@cesdis.gsfc.nasa.gov> and modified by Mike Cruse
63
 
  <mcruse@cti-ltd.com>. That driver has been released under the
64
 
  conditions of the GNU Public License, thus this one is probably to
65
 
  be considered "derived work". Therefore, there are some legal
66
 
  obstacles in combining this file with etherboot's code, which is
67
 
  released under a BSD style license.
68
 
 
69
 
  So, if you want to actually use this code, you should make sure that
70
 
  you are aware of the legal implications. I release *my* work into
71
 
  the PUBLIC DOMAIN which implies that you can use it either under a
72
 
  BSD style license, or under the conditions of the GPL, or under any
73
 
  other conditions that you like. N.B. this does not apply to the
74
 
  parts that originate from other authors. So, you should probably
75
 
  contact them first and verify if they agree with your intended use.
76
 
 
77
 
  If you contacted all of the above authors and they agreed to give
78
 
  special permission for using this code under the conditions of a BSD
79
 
  style license, then please do let me know.
80
 
===============================================================================
81
 
 
82
 
In a later etherboot release, the copyright notice changed to this:
83
 
 
84
 
**********************************************************************
85
 
  Permission is granted to distribute the enclosed cs89x0.[ch] driver
86
 
  only in conjunction with the Etherboot package.  The code is
87
 
  ordinarily distributed under the GPL.
88
 
 
89
 
  Russ Nelson, January 2000
90
 
**********************************************************************
91
 
 
92
 
Don't be confused by the statements. Look at the first statement:
93
 
 
94
 
  Permission is granted to distribute the enclosed cs89x0.[ch] driver
95
 
  only in conjunction with the Etherboot package.
96
 
 
97
 
It should be understood as:
98
 
 
99
 
  ----------------------------------------------------------------------------
100
 
                                (1)
101
 
  Permission is granted **(to distribute the enclosed cs89x0.[ch] driver
102
 
  only in conjunction with the Etherboot package)**.
103
 
  ----------------------------------------------------------------------------
104
 
 
105
 
which means if the driver is distributed only in conjunction with the
106
 
Etherboot package, then Permission is granted for it.
107
 
 
108
 
It should not be understood as this:
109
 
 
110
 
  ----------------------------------------------------------------------------
111
 
                                (2)
112
 
  **(Permission is granted to distribute the enclosed cs89x0.[ch] driver)**
113
 
  only in conjunction with the Etherboot package.
114
 
  ----------------------------------------------------------------------------
115
 
 
116
 
which means Permission is **only** granted to distribute the driver
117
 
in conjunction with the Etherboot package, and if it is not distributed in
118
 
conjunction with Etherboot, then Permission is not granted.
119
 
 
120
 
The latter understanding of (2) is obviously wrong because it directly
121
 
conflicts with GPL claimed above in the second statement by Russ Nelson.
122
 
 
123
 
But if you consider Russ Nelson's announcements as dual license: one license
124
 
is for how to use this driver in Etherboot:
125
 
 
126
 
  ----------------------------------------------------------------------------
127
 
  Permission is granted to distribute the enclosed cs89x0.[ch] driver
128
 
  only in conjunction with the Etherboot package.
129
 
  ----------------------------------------------------------------------------
130
 
 
131
 
and the other license is for how to use this driver in other packages:
132
 
 
133
 
  --------------------------------------------------------
134
 
  The code is ordinarily distributed under the GPL.
135
 
  --------------------------------------------------------
136
 
 
137
 
then the different understandings between (1) and (2) are not important.
138
 
This is because, for the dual license, either of the included licenses
139
 
can be chosen by the recipient. You don't have to accept both licenses
140
 
simultaneously.
141
 
 
142
 
We are introducing the driver from Etherboot, so we can legally inherit
143
 
the GPL from Etherboot. In any case, we can distribute the cs89x0.[ch]
144
 
driver under GPL. There are no problems. Don't worry.
145
 
 
146
 
             ---- Tinybit <tinybit@tom.com> August 20, 2007
147
 
*/
148
 
 
149
 
/***************************************************************************/
150
 
/***************************************************************************/
151
 
 
152
 
/* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for etherboot. */
153
 
/*
154
 
  Permission is granted to distribute the enclosed cs89x0.[ch] driver
155
 
  only in conjunction with the Etherboot package.  The code is
156
 
  ordinarily distributed under the GPL.
157
 
  
158
 
  Russ Nelson, January 2000
159
 
 
160
 
  ChangeLog:
161
 
 
162
 
  Thu Dec 6 22:40:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
163
 
 
164
 
  * disabled all "advanced" features; this should make the code more reliable
165
 
 
166
 
  * reorganized the reset function
167
 
 
168
 
  * always reset the address port, so that autoprobing will continue working
169
 
 
170
 
  * some cosmetic changes
171
 
 
172
 
  * 2.5
173
 
 
174
 
  Thu Dec 5 21:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
175
 
 
176
 
  * tested the code against a CS8900 card
177
 
 
178
 
  * lots of minor bug fixes and adjustments
179
 
 
180
 
  * this is the first release, that actually works! it still requires some
181
 
    changes in order to be more tolerant to different environments
182
 
 
183
 
  * 4
184
 
 
185
 
  Fri Nov 22 23:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
186
 
 
187
 
  * read the manuals for the CS89x0 chipsets and took note of all the
188
 
    changes that will be neccessary in order to adapt Russel Nelson's code
189
 
    to the requirements of a BOOT-Prom
190
 
 
191
 
  * 6
192
 
 
193
 
  Thu Nov 19 22:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
194
 
 
195
 
  * Synched with Russel Nelson's current code (v1.00)
196
 
 
197
 
  * 2
198
 
 
199
 
  Thu Nov 12 18:00:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
200
 
 
201
 
  * Cleaned up some of the code and tried to optimize the code size.
202
 
 
203
 
  * 1.5
204
 
 
205
 
  Sun Nov 10 16:30:00 1996  Markus Gutschke  <gutschk@math.uni-muenster.de>
206
 
 
207
 
  * First experimental release. This code compiles fine, but I
208
 
  have no way of testing whether it actually works.
209
 
 
210
 
  * I did not (yet) bother to make the code 16bit aware, so for
211
 
  the time being, it will only work for Etherboot/32.
212
 
 
213
 
  * 12
214
 
 
215
 
  */
216
 
 
217
 
#include "etherboot.h"
218
 
#include "nic.h"
219
 
#include "cards.h"
220
 
#include "cs89x0.h"
221
 
 
222
 
static unsigned short   eth_nic_base;
223
 
static unsigned long    eth_mem_start;
224
 
static unsigned short   eth_irq;
225
 
static unsigned short   eth_cs_type;    /* one of: CS8900, CS8920, CS8920M  */
226
 
static unsigned short   eth_auto_neg_cnf;
227
 
static unsigned short   eth_adapter_cnf;
228
 
static unsigned short   eth_linectl;
229
 
 
230
 
/*************************************************************************
231
 
        CS89x0 - specific routines
232
 
**************************************************************************/
233
 
 
234
 
static inline int readreg(int portno)
235
 
{
236
 
        outw(portno, eth_nic_base + ADD_PORT);
237
 
        return inw(eth_nic_base + DATA_PORT);
238
 
}
239
 
 
240
 
static inline void writereg(int portno, int value)
241
 
{
242
 
        outw(portno, eth_nic_base + ADD_PORT);
243
 
        outw(value, eth_nic_base + DATA_PORT);
244
 
        return;
245
 
}
246
 
 
247
 
/*************************************************************************
248
 
EEPROM access
249
 
**************************************************************************/
250
 
 
251
 
static int wait_eeprom_ready(void)
252
 
{
253
 
        unsigned long tmo = currticks() + 4*TICKS_PER_SEC;
254
 
 
255
 
        /* check to see if the EEPROM is ready, a timeout is used -
256
 
           just in case EEPROM is ready when SI_BUSY in the
257
 
           PP_SelfST is clear */
258
 
        while(readreg(PP_SelfST) & SI_BUSY) {
259
 
                if (currticks() >= tmo)
260
 
                        return -1; }
261
 
        return 0;
262
 
}
263
 
 
264
 
static int get_eeprom_data(int off, int len, unsigned short *buffer)
265
 
{
266
 
        int i;
267
 
 
268
 
#ifdef  EDEBUG
269
 
        printf("\ncs: EEPROM data from %hX for %hX:",off,len);
270
 
#endif
271
 
        for (i = 0; i < len; i++) {
272
 
                if (wait_eeprom_ready() < 0)
273
 
                        return -1;
274
 
                /* Now send the EEPROM read command and EEPROM location
275
 
                   to read */
276
 
                writereg(PP_EECMD, (off + i) | EEPROM_READ_CMD);
277
 
                if (wait_eeprom_ready() < 0)
278
 
                        return -1;
279
 
                buffer[i] = readreg(PP_EEData);
280
 
#ifdef  EDEBUG
281
 
                if (!(i%10))
282
 
                        printf("\ncs: ");
283
 
                printf("%hX ", buffer[i]);
284
 
#endif
285
 
        }
286
 
#ifdef  EDEBUG
287
 
        putchar('\n');
288
 
#endif
289
 
 
290
 
        return(0);
291
 
}
292
 
 
293
 
static int get_eeprom_chksum(int off, int len, unsigned short *buffer)
294
 
{
295
 
        int  i, cksum;
296
 
 
297
 
        cksum = 0;
298
 
        for (i = 0; i < len; i++)
299
 
                cksum += buffer[i];
300
 
        cksum &= 0xffff;
301
 
        if (cksum == 0)
302
 
                return 0;
303
 
        return -1;
304
 
}
305
 
 
306
 
/*************************************************************************
307
 
Activate all of the available media and probe for network
308
 
**************************************************************************/
309
 
 
310
 
static void clrline(void)
311
 
{
312
 
        int i;
313
 
 
314
 
        putchar('\r');
315
 
        for (i = 79; i--; ) putchar(' ');
316
 
        printf("\rcs: ");
317
 
        return;
318
 
}
319
 
 
320
 
static void control_dc_dc(int on_not_off)
321
 
{
322
 
        unsigned int selfcontrol;
323
 
        unsigned long tmo = currticks() + TICKS_PER_SEC;
324
 
 
325
 
        /* control the DC to DC convertor in the SelfControl register.  */
326
 
        selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */
327
 
        if (((eth_adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)
328
 
                selfcontrol |= HCB1;
329
 
        else
330
 
                selfcontrol &= ~HCB1;
331
 
        writereg(PP_SelfCTL, selfcontrol);
332
 
 
333
 
        /* Wait for the DC/DC converter to power up - 1000ms */
334
 
        while (currticks() < tmo);
335
 
 
336
 
        return;
337
 
}
338
 
 
339
 
static int detect_tp(void)
340
 
{
341
 
        unsigned long tmo;
342
 
 
343
 
        /* Turn on the chip auto detection of 10BT/ AUI */
344
 
 
345
 
        clrline(); printf("attempting %s:","TP");
346
 
 
347
 
        /* If connected to another full duplex capable 10-Base-T card
348
 
           the link pulses seem to be lost when the auto detect bit in
349
 
           the LineCTL is set.  To overcome this the auto detect bit
350
 
           will be cleared whilst testing the 10-Base-T interface.
351
 
           This would not be necessary for the sparrow chip but is
352
 
           simpler to do it anyway. */
353
 
        writereg(PP_LineCTL, eth_linectl &~ AUI_ONLY);
354
 
        control_dc_dc(0);
355
 
 
356
 
        /* Delay for the hardware to work out if the TP cable is
357
 
           present - 150ms */
358
 
        for (tmo = currticks() + 4; currticks() < tmo; );
359
 
 
360
 
        if ((readreg(PP_LineST) & LINK_OK) == 0)
361
 
                return 0;
362
 
 
363
 
        if (eth_cs_type != CS8900) {
364
 
 
365
 
                writereg(PP_AutoNegCTL, eth_auto_neg_cnf & AUTO_NEG_MASK);
366
 
 
367
 
                if ((eth_auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) {
368
 
                        printf(" negotiating duplex... ");
369
 
                        while (readreg(PP_AutoNegST) & AUTO_NEG_BUSY) {
370
 
                                if (currticks() - tmo > 40*TICKS_PER_SEC) {
371
 
                                        printf("time out ");
372
 
                                        break;
373
 
                                }
374
 
                        }
375
 
                }
376
 
                if (readreg(PP_AutoNegST) & FDX_ACTIVE)
377
 
                        printf("using full duplex");
378
 
                else
379
 
                        printf("using half duplex");
380
 
        }
381
 
 
382
 
        return A_CNF_MEDIA_10B_T;
383
 
}
384
 
 
385
 
/* send a test packet - return true if carrier bits are ok */
386
 
static int send_test_pkt(struct nic *nic)
387
 
{
388
 
        static unsigned char testpacket[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
389
 
                                     0, 46, /*A 46 in network order       */
390
 
                                     0, 0,  /*DSAP=0 & SSAP=0 fields      */
391
 
                                     0xf3,0 /*Control (Test Req+P bit set)*/ };
392
 
        unsigned long tmo;
393
 
 
394
 
        writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_TX_ON);
395
 
 
396
 
        memcpy(testpacket, nic->node_addr, ETH_ALEN);
397
 
        memcpy(testpacket+ETH_ALEN, nic->node_addr, ETH_ALEN);
398
 
 
399
 
        outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT);
400
 
        outw(ETH_ZLEN, eth_nic_base + TX_LEN_PORT);
401
 
 
402
 
        /* Test to see if the chip has allocated memory for the packet */
403
 
        for (tmo = currticks() + 2;
404
 
             (readreg(PP_BusST) & READY_FOR_TX_NOW) == 0; )
405
 
                if (currticks() >= tmo)
406
 
                        return(0);
407
 
 
408
 
        /* Write the contents of the packet */
409
 
        outsw(eth_nic_base + TX_FRAME_PORT, testpacket,
410
 
              (ETH_ZLEN+1)>>1);
411
 
 
412
 
        printf(" sending test packet ");
413
 
        /* wait a couple of timer ticks for packet to be received */
414
 
        for (tmo = currticks() + 2; currticks() < tmo; );
415
 
 
416
 
        if ((readreg(PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
417
 
                        printf("succeeded");
418
 
                        return 1;
419
 
        }
420
 
        printf("failed");
421
 
        return 0;
422
 
}
423
 
 
424
 
 
425
 
static int detect_aui(struct nic *nic)
426
 
{
427
 
        clrline(); printf("attempting %s:","AUI");
428
 
        control_dc_dc(0);
429
 
 
430
 
        writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
431
 
 
432
 
        if (send_test_pkt(nic)) {
433
 
                return A_CNF_MEDIA_AUI; }
434
 
        else
435
 
                return 0;
436
 
}
437
 
 
438
 
static int detect_bnc(struct nic *nic)
439
 
{
440
 
        clrline(); printf("attempting %s:","BNC");
441
 
        control_dc_dc(1);
442
 
 
443
 
        writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
444
 
 
445
 
        if (send_test_pkt(nic)) {
446
 
                return A_CNF_MEDIA_10B_2; }
447
 
        else
448
 
                return 0;
449
 
}
450
 
 
451
 
/**************************************************************************
452
 
ETH_RESET - Reset adapter
453
 
***************************************************************************/
454
 
 
455
 
static void cs89x0_reset(struct nic *nic)
456
 
{
457
 
        int  i;
458
 
        unsigned long reset_tmo;
459
 
 
460
 
        writereg(PP_SelfCTL, readreg(PP_SelfCTL) | POWER_ON_RESET);
461
 
 
462
 
        /* wait for two ticks; that is 2*55ms */
463
 
        for (reset_tmo = currticks() + 2; currticks() < reset_tmo; );
464
 
 
465
 
        if (eth_cs_type != CS8900) {
466
 
                /* Hardware problem requires PNP registers to be reconfigured
467
 
                   after a reset */
468
 
                if (eth_irq != 0xFFFF) {
469
 
                        outw(PP_CS8920_ISAINT, eth_nic_base + ADD_PORT);
470
 
                        outb(eth_irq, eth_nic_base + DATA_PORT);
471
 
                        outb(0, eth_nic_base + DATA_PORT + 1); }
472
 
 
473
 
                if (eth_mem_start) {
474
 
                        outw(PP_CS8920_ISAMemB, eth_nic_base + ADD_PORT);
475
 
                        outb((eth_mem_start >> 8) & 0xff, eth_nic_base + DATA_PORT);
476
 
                        outb((eth_mem_start >> 24) & 0xff, eth_nic_base + DATA_PORT + 1); } }
477
 
 
478
 
        /* Wait until the chip is reset */
479
 
        for (reset_tmo = currticks() + 2;
480
 
             (readreg(PP_SelfST) & INIT_DONE) == 0 &&
481
 
                     currticks() < reset_tmo; );
482
 
 
483
 
        /* disable interrupts and memory accesses */
484
 
        writereg(PP_BusCTL, 0);
485
 
 
486
 
        /* set the ethernet address */
487
 
        for (i=0; i < ETH_ALEN/2; i++)
488
 
                writereg(PP_IA+i*2,
489
 
                         nic->node_addr[i*2] |
490
 
                         (nic->node_addr[i*2+1] << 8));
491
 
 
492
 
        /* receive only error free packets addressed to this card */
493
 
        writereg(PP_RxCTL, DEF_RX_ACCEPT);
494
 
 
495
 
        /* do not generate any interrupts on receive operations */
496
 
        writereg(PP_RxCFG, 0);
497
 
 
498
 
        /* do not generate any interrupts on transmit operations */
499
 
        writereg(PP_TxCFG, 0);
500
 
 
501
 
        /* do not generate any interrupts on buffer operations */
502
 
        writereg(PP_BufCFG, 0);
503
 
 
504
 
        /* reset address port, so that autoprobing will keep working */
505
 
        outw(PP_ChipID, eth_nic_base + ADD_PORT);
506
 
 
507
 
        return;
508
 
}
509
 
 
510
 
/**************************************************************************
511
 
ETH_TRANSMIT - Transmit a frame
512
 
***************************************************************************/
513
 
 
514
 
static void cs89x0_transmit(
515
 
        struct nic *nic,
516
 
        const char *d,                  /* Destination */
517
 
        unsigned int t,                 /* Type */
518
 
        unsigned int s,                 /* size */
519
 
        const char *p)                  /* Packet */
520
 
{
521
 
        unsigned long tmo;
522
 
        int           sr;
523
 
 
524
 
        /* does this size have to be rounded??? please,
525
 
           somebody have a look in the specs */
526
 
        if ((sr = ((s + ETH_HLEN + 1)&~1)) < ETH_ZLEN)
527
 
                sr = ETH_ZLEN;
528
 
 
529
 
retry:
530
 
        /* initiate a transmit sequence */
531
 
        outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT);
532
 
        outw(sr, eth_nic_base + TX_LEN_PORT);
533
 
 
534
 
        /* Test to see if the chip has allocated memory for the packet */
535
 
        if ((readreg(PP_BusST) & READY_FOR_TX_NOW) == 0) {
536
 
                /* Oops... this should not happen! */
537
 
                printf("cs: unable to send packet; retrying...\n");
538
 
                for (tmo = currticks() + 5*TICKS_PER_SEC; currticks() < tmo; );
539
 
                cs89x0_reset(nic);
540
 
                goto retry; }
541
 
 
542
 
        /* Write the contents of the packet */
543
 
        outsw(eth_nic_base + TX_FRAME_PORT, d, ETH_ALEN/2);
544
 
        outsw(eth_nic_base + TX_FRAME_PORT, nic->node_addr,
545
 
              ETH_ALEN/2);
546
 
        outw(((t >> 8)&0xFF)|(t << 8), eth_nic_base + TX_FRAME_PORT);
547
 
        outsw(eth_nic_base + TX_FRAME_PORT, p, (s+1)/2);
548
 
        for (sr = sr/2 - (s+1)/2 - ETH_ALEN - 1; sr-- > 0;
549
 
             outw(0, eth_nic_base + TX_FRAME_PORT));
550
 
 
551
 
        /* wait for transfer to succeed */
552
 
        for (tmo = currticks()+5*TICKS_PER_SEC;
553
 
             (s = readreg(PP_TxEvent)&~0x1F) == 0 && currticks() < tmo;)
554
 
                /* nothing */ ;
555
 
        if ((s & TX_SEND_OK_BITS) != TX_OK) {
556
 
                printf("\ntransmission error %#hX\n", s);
557
 
        }
558
 
 
559
 
        return;
560
 
}
561
 
 
562
 
/**************************************************************************
563
 
ETH_POLL - Wait for a frame
564
 
***************************************************************************/
565
 
 
566
 
static int cs89x0_poll(struct nic *nic)
567
 
{
568
 
        int status;
569
 
 
570
 
        status = readreg(PP_RxEvent);
571
 
 
572
 
        if ((status & RX_OK) == 0)
573
 
                return(0);
574
 
 
575
 
        status = inw(eth_nic_base + RX_FRAME_PORT);
576
 
        nic->packetlen = inw(eth_nic_base + RX_FRAME_PORT);
577
 
        insw(eth_nic_base + RX_FRAME_PORT, nic->packet, nic->packetlen >> 1);
578
 
        if (nic->packetlen & 1)
579
 
                nic->packet[nic->packetlen-1] = inw(eth_nic_base + RX_FRAME_PORT);
580
 
        return 1;
581
 
}
582
 
 
583
 
static void cs89x0_disable(struct nic *nic)
584
 
{
585
 
        cs89x0_reset(nic);
586
 
}
587
 
 
588
 
/**************************************************************************
589
 
ETH_PROBE - Look for an adapter
590
 
***************************************************************************/
591
 
 
592
 
struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
593
 
{
594
 
        static const unsigned int netcard_portlist[] = {
595
 
#ifdef  CS_SCAN
596
 
                CS_SCAN,
597
 
#else   /* use "conservative" default values for autoprobing */
598
 
                0x300,0x320,0x340,0x200,0x220,0x240,
599
 
                0x260,0x280,0x2a0,0x2c0,0x2e0,
600
 
        /* if that did not work, then be more aggressive */
601
 
                0x301,0x321,0x341,0x201,0x221,0x241,
602
 
                0x261,0x281,0x2a1,0x2c1,0x2e1,
603
 
#endif
604
 
                0};
605
 
 
606
 
        int      i, result = -1;
607
 
        unsigned rev_type = 0, ioaddr, ioidx, isa_cnf, cs_revision;
608
 
        unsigned short eeprom_buff[CHKSUM_LEN];
609
 
 
610
 
 
611
 
        for (ioidx = 0; (ioaddr=netcard_portlist[ioidx++]) != 0; ) {
612
 
                /* if they give us an odd I/O address, then do ONE write to
613
 
                   the address port, to get it back to address zero, where we
614
 
                   expect to find the EISA signature word. */
615
 
                if (ioaddr & 1) {
616
 
                        ioaddr &= ~1;
617
 
                        if ((inw(ioaddr + ADD_PORT) & ADD_MASK) != ADD_SIG)
618
 
                                continue;
619
 
                        outw(PP_ChipID, ioaddr + ADD_PORT);
620
 
                }
621
 
 
622
 
                if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG)
623
 
                        continue;
624
 
                eth_nic_base = ioaddr;
625
 
 
626
 
                /* get the chip type */
627
 
                rev_type = readreg(PRODUCT_ID_ADD);
628
 
                eth_cs_type = rev_type &~ REVISON_BITS;
629
 
                cs_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
630
 
 
631
 
                printf("\ncs: cs89%c0%s rev %c, base %#hX",
632
 
                       eth_cs_type==CS8900?'0':'2',
633
 
                       eth_cs_type==CS8920M?"M":"",
634
 
                       cs_revision,
635
 
                       eth_nic_base);
636
 
 
637
 
                /* First check to see if an EEPROM is attached*/
638
 
                if ((readreg(PP_SelfST) & EEPROM_PRESENT) == 0) {
639
 
                        printf("\ncs: no EEPROM...\n");
640
 
                        outw(PP_ChipID, eth_nic_base + ADD_PORT);
641
 
                        continue; }
642
 
                else if (get_eeprom_data(START_EEPROM_DATA,CHKSUM_LEN,
643
 
                                         eeprom_buff) < 0) {
644
 
                        printf("\ncs: EEPROM read failed...\n");
645
 
                        outw(PP_ChipID, eth_nic_base + ADD_PORT);
646
 
                        continue; }
647
 
                else if (get_eeprom_chksum(START_EEPROM_DATA,CHKSUM_LEN,
648
 
                                           eeprom_buff) < 0) {
649
 
                        printf("\ncs: EEPROM checksum bad...\n");
650
 
                        outw(PP_ChipID, eth_nic_base + ADD_PORT);
651
 
                        continue; }
652
 
 
653
 
                /* get transmission control word but keep the
654
 
                   autonegotiation bits */
655
 
                eth_auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
656
 
                /* Store adapter configuration */
657
 
                eth_adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET/2];
658
 
                /* Store ISA configuration */
659
 
                isa_cnf = eeprom_buff[ISA_CNF_OFFSET/2];
660
 
 
661
 
                /* store the initial memory base address */
662
 
                eth_mem_start = eeprom_buff[PACKET_PAGE_OFFSET/2] << 8;
663
 
 
664
 
                printf("%s%s%s, addr ",
665
 
                       (eth_adapter_cnf & A_CNF_10B_T)?", RJ-45":"",
666
 
                       (eth_adapter_cnf & A_CNF_AUI)?", AUI":"",
667
 
                       (eth_adapter_cnf & A_CNF_10B_2)?", BNC":"");
668
 
 
669
 
                /* If this is a CS8900 then no pnp soft */
670
 
                if (eth_cs_type != CS8900 &&
671
 
                    /* Check if the ISA IRQ has been set  */
672
 
                    (i = readreg(PP_CS8920_ISAINT) & 0xff,
673
 
                     (i != 0 && i < CS8920_NO_INTS)))
674
 
                        eth_irq = i;
675
 
                else {
676
 
                        i = isa_cnf & INT_NO_MASK;
677
 
                        if (eth_cs_type == CS8900) {
678
 
                                /* the table that follows is dependent
679
 
                                   upon how you wired up your cs8900
680
 
                                   in your system.  The table is the
681
 
                                   same as the cs8900 engineering demo
682
 
                                   board.  irq_map also depends on the
683
 
                                   contents of the table.  Also see
684
 
                                   write_irq, which is the reverse
685
 
                                   mapping of the table below. */
686
 
                                if (i < 4) i = "\012\013\014\005"[i];
687
 
                                else printf("\ncs: BUG: isa_config is %d\n", i); }
688
 
                        eth_irq = i; }
689
 
 
690
 
                /* Retrieve and print the ethernet address. */
691
 
                for (i=0; i<ETH_ALEN; i++) {
692
 
                        nic->node_addr[i] = ((unsigned char *)eeprom_buff)[i];
693
 
                }
694
 
                printf("%!\n", nic->node_addr);
695
 
 
696
 
                /* Set the LineCTL quintuplet based on adapter
697
 
                   configuration read from EEPROM */
698
 
                if ((eth_adapter_cnf & A_CNF_EXTND_10B_2) &&
699
 
                    (eth_adapter_cnf & A_CNF_LOW_RX_SQUELCH))
700
 
                        eth_linectl = LOW_RX_SQUELCH;
701
 
                else
702
 
                        eth_linectl = 0;
703
 
 
704
 
                /* check to make sure that they have the "right"
705
 
                   hardware available */
706
 
                switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) {
707
 
                case A_CNF_MEDIA_10B_T: result = eth_adapter_cnf & A_CNF_10B_T;
708
 
                        break;
709
 
                case A_CNF_MEDIA_AUI:   result = eth_adapter_cnf & A_CNF_AUI;
710
 
                        break;
711
 
                case A_CNF_MEDIA_10B_2: result = eth_adapter_cnf & A_CNF_10B_2;
712
 
                        break;
713
 
                default: result = eth_adapter_cnf & (A_CNF_10B_T | A_CNF_AUI |
714
 
                                                     A_CNF_10B_2);
715
 
                }
716
 
                if (!result) {
717
 
                        printf("cs: EEPROM is configured for unavailable media\n");
718
 
                error:
719
 
                        writereg(PP_LineCTL, readreg(PP_LineCTL) &
720
 
                                 ~(SERIAL_TX_ON | SERIAL_RX_ON));
721
 
                        outw(PP_ChipID, eth_nic_base + ADD_PORT);
722
 
                        continue;
723
 
                }
724
 
 
725
 
                /* Initialize the card for probing of the attached media */
726
 
                cs89x0_reset(nic);
727
 
 
728
 
                /* set the hardware to the configured choice */
729
 
                switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) {
730
 
                case A_CNF_MEDIA_10B_T:
731
 
                        result = detect_tp();
732
 
                        if (!result) {
733
 
                                clrline();
734
 
                                printf("10Base-T (RJ-45%s",
735
 
                                       ") has no cable\n"); }
736
 
                        /* check "ignore missing media" bit */
737
 
                        if (eth_auto_neg_cnf & IMM_BIT)
738
 
                                /* Yes! I don't care if I see a link pulse */
739
 
                                result = A_CNF_MEDIA_10B_T;
740
 
                        break;
741
 
                case A_CNF_MEDIA_AUI:
742
 
                        result = detect_aui(nic);
743
 
                        if (!result) {
744
 
                                clrline();
745
 
                                printf("10Base-5 (AUI%s",
746
 
                                       ") has no cable\n"); }
747
 
                        /* check "ignore missing media" bit */
748
 
                        if (eth_auto_neg_cnf & IMM_BIT)
749
 
                                /* Yes! I don't care if I see a carrrier */
750
 
                                result = A_CNF_MEDIA_AUI;
751
 
                        break;
752
 
                case A_CNF_MEDIA_10B_2:
753
 
                        result = detect_bnc(nic);
754
 
                        if (!result) {
755
 
                                clrline();
756
 
                                printf("10Base-2 (BNC%s",
757
 
                                       ") has no cable\n"); }
758
 
                        /* check "ignore missing media" bit */
759
 
                        if (eth_auto_neg_cnf & IMM_BIT)
760
 
                                /* Yes! I don't care if I can xmit a packet */
761
 
                                result = A_CNF_MEDIA_10B_2;
762
 
                        break;
763
 
                case A_CNF_MEDIA_AUTO:
764
 
                        writereg(PP_LineCTL, eth_linectl | AUTO_AUI_10BASET);
765
 
                        if (eth_adapter_cnf & A_CNF_10B_T)
766
 
                                if ((result = detect_tp()) != 0)
767
 
                                        break;
768
 
                        if (eth_adapter_cnf & A_CNF_AUI)
769
 
                                if ((result = detect_aui(nic)) != 0)
770
 
                                        break;
771
 
                        if (eth_adapter_cnf & A_CNF_10B_2)
772
 
                                if ((result = detect_bnc(nic)) != 0)
773
 
                                        break;
774
 
                        clrline(); printf("no media detected\n");
775
 
                        goto error;
776
 
                }
777
 
                clrline();
778
 
                switch(result) {
779
 
                case 0:                 printf("no network cable attached to configured media\n");
780
 
                        goto error;
781
 
                case A_CNF_MEDIA_10B_T: printf("using 10Base-T (RJ-45)\n");
782
 
                        break;
783
 
                case A_CNF_MEDIA_AUI:   printf("using 10Base-5 (AUI)\n");
784
 
                        break;
785
 
                case A_CNF_MEDIA_10B_2: printf("using 10Base-2 (BNC)\n");
786
 
                        break;
787
 
                }
788
 
 
789
 
                /* Turn on both receive and transmit operations */
790
 
                writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_RX_ON |
791
 
                         SERIAL_TX_ON);
792
 
 
793
 
                break;
794
 
        }
795
 
 
796
 
        if (ioaddr == 0)
797
 
                return (0);
798
 
        nic->reset = cs89x0_reset;
799
 
        nic->poll = cs89x0_poll;
800
 
        nic->transmit = cs89x0_transmit;
801
 
        nic->disable = cs89x0_disable;
802
 
        return (nic);
803
 
}
804
 
 
805
 
/*
806
 
 * Local variables:
807
 
 *  c-basic-offset: 8
808
 
 * End:
809
 
 */
810