1 | /**************************************************************************
|
---|
2 | ETHERBOOT - BOOTP/TFTP Bootstrap Program
|
---|
3 |
|
---|
4 | Author: Martin Renters
|
---|
5 | Date: May/94
|
---|
6 |
|
---|
7 | This code is based heavily on David Greenman's if_ed.c driver
|
---|
8 |
|
---|
9 | Copyright (C) 1993-1994, David Greenman, Martin Renters.
|
---|
10 | This software may be used, modified, copied, distributed, and sold, in
|
---|
11 | both source and binary form provided that the above copyright and these
|
---|
12 | terms are retained. Under no circumstances are the authors responsible for
|
---|
13 | the proper functioning of this software, nor do the authors assume any
|
---|
14 | responsibility for damages incurred with its use.
|
---|
15 |
|
---|
16 | Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
|
---|
17 | Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
|
---|
18 | 3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
|
---|
19 | SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
|
---|
20 | 3c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
|
---|
21 | RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
|
---|
22 | parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
|
---|
23 | SMC8416 PIO support added by Andrew Bettison (andrewb@zip.com.au) on 4/3/02
|
---|
24 | based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
|
---|
25 |
|
---|
26 | **************************************************************************/
|
---|
27 |
|
---|
28 | #include "etherboot.h"
|
---|
29 | #include "nic.h"
|
---|
30 | #include "ns8390.h"
|
---|
31 | #ifdef INCLUDE_NS8390
|
---|
32 | #include "pci.h"
|
---|
33 | #else
|
---|
34 | #include "isa.h"
|
---|
35 | #endif
|
---|
36 |
|
---|
37 | static unsigned char eth_vendor, eth_flags;
|
---|
38 | #ifdef INCLUDE_WD
|
---|
39 | static unsigned char eth_laar;
|
---|
40 | #endif
|
---|
41 | static unsigned short eth_nic_base, eth_asic_base;
|
---|
42 | static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
|
---|
43 | static Address eth_bmem, eth_rmem;
|
---|
44 | static unsigned char eth_drain_receiver;
|
---|
45 |
|
---|
46 | #ifdef INCLUDE_WD
|
---|
47 | static struct wd_board {
|
---|
48 | const char *name;
|
---|
49 | char id;
|
---|
50 | char flags;
|
---|
51 | char memsize;
|
---|
52 | } wd_boards[] = {
|
---|
53 | {"WD8003S", TYPE_WD8003S, 0, MEM_8192},
|
---|
54 | {"WD8003E", TYPE_WD8003E, 0, MEM_8192},
|
---|
55 | {"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384},
|
---|
56 | {"WD8003W", TYPE_WD8003W, 0, MEM_8192},
|
---|
57 | {"WD8003EB", TYPE_WD8003EB, 0, MEM_8192},
|
---|
58 | {"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384},
|
---|
59 | {"WD8003EP/WD8013EP",
|
---|
60 | TYPE_WD8013EP, 0, MEM_8192},
|
---|
61 | {"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384},
|
---|
62 | {"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384},
|
---|
63 | {"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384},
|
---|
64 | {"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384},
|
---|
65 | {"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192},
|
---|
66 | {"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192},
|
---|
67 | {"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384},
|
---|
68 | {NULL, 0, 0, 0}
|
---|
69 | };
|
---|
70 | #endif
|
---|
71 |
|
---|
72 | #ifdef INCLUDE_3C503
|
---|
73 | static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */
|
---|
74 | #endif
|
---|
75 |
|
---|
76 | #if defined(INCLUDE_WD)
|
---|
77 | #define ASIC_PIO WD_IAR
|
---|
78 | #define eth_probe wd_probe
|
---|
79 | #if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
|
---|
80 | Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
|
---|
81 | #endif
|
---|
82 | #endif
|
---|
83 |
|
---|
84 | #if defined(INCLUDE_3C503)
|
---|
85 | #define eth_probe t503_probe
|
---|
86 | #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
|
---|
87 | Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
|
---|
88 | #endif
|
---|
89 | #endif
|
---|
90 |
|
---|
91 | #if defined(INCLUDE_NE)
|
---|
92 | #define eth_probe ne_probe
|
---|
93 | #if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
|
---|
94 | Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
|
---|
95 | #endif
|
---|
96 | #endif
|
---|
97 |
|
---|
98 | #if defined(INCLUDE_NS8390)
|
---|
99 | #define eth_probe nepci_probe
|
---|
100 | #if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
|
---|
101 | Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
|
---|
102 | #endif
|
---|
103 | #endif
|
---|
104 |
|
---|
105 | #if defined(INCLUDE_3C503)
|
---|
106 | #define ASIC_PIO _3COM_RFMSB
|
---|
107 | #else
|
---|
108 | #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
|
---|
109 | #define ASIC_PIO NE_DATA
|
---|
110 | #endif
|
---|
111 | #endif
|
---|
112 |
|
---|
113 | #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
|
---|
114 | /**************************************************************************
|
---|
115 | ETH_PIO_READ - Read a frame via Programmed I/O
|
---|
116 | **************************************************************************/
|
---|
117 | static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
|
---|
118 | {
|
---|
119 | #ifdef INCLUDE_WD
|
---|
120 | outb(src & 0xff, eth_asic_base + WD_GP2);
|
---|
121 | outb(src >> 8, eth_asic_base + WD_GP2);
|
---|
122 | #else
|
---|
123 | outb(D8390_COMMAND_RD2 |
|
---|
124 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
|
---|
125 | outb(cnt, eth_nic_base + D8390_P0_RBCR0);
|
---|
126 | outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
|
---|
127 | outb(src, eth_nic_base + D8390_P0_RSAR0);
|
---|
128 | outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
|
---|
129 | outb(D8390_COMMAND_RD0 |
|
---|
130 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
|
---|
131 |
|
---|
132 | #ifdef INCLUDE_3C503
|
---|
133 | outb(src & 0xff, eth_asic_base + _3COM_DALSB);
|
---|
134 | outb(src >> 8, eth_asic_base + _3COM_DAMSB);
|
---|
135 | outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
|
---|
136 | #endif
|
---|
137 | #endif
|
---|
138 |
|
---|
139 | if (eth_flags & FLAG_16BIT)
|
---|
140 | cnt = (cnt + 1) >> 1;
|
---|
141 |
|
---|
142 | while(cnt--) {
|
---|
143 | #ifdef INCLUDE_3C503
|
---|
144 | while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
|
---|
145 | ;
|
---|
146 | #endif
|
---|
147 |
|
---|
148 | if (eth_flags & FLAG_16BIT) {
|
---|
149 | *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
|
---|
150 | dst += 2;
|
---|
151 | }
|
---|
152 | else
|
---|
153 | *(dst++) = inb(eth_asic_base + ASIC_PIO);
|
---|
154 | }
|
---|
155 |
|
---|
156 | #ifdef INCLUDE_3C503
|
---|
157 | outb(t503_output, eth_asic_base + _3COM_CR);
|
---|
158 | #endif
|
---|
159 | }
|
---|
160 |
|
---|
161 | /**************************************************************************
|
---|
162 | ETH_PIO_WRITE - Write a frame via Programmed I/O
|
---|
163 | **************************************************************************/
|
---|
164 | static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
|
---|
165 | {
|
---|
166 | #ifdef COMPEX_RL2000_FIX
|
---|
167 | unsigned int x;
|
---|
168 | #endif /* COMPEX_RL2000_FIX */
|
---|
169 | #ifdef INCLUDE_WD
|
---|
170 | outb(dst & 0xff, eth_asic_base + WD_GP2);
|
---|
171 | outb(dst >> 8, eth_asic_base + WD_GP2);
|
---|
172 | #else
|
---|
173 | outb(D8390_COMMAND_RD2 |
|
---|
174 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
|
---|
175 | outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
|
---|
176 | outb(cnt, eth_nic_base + D8390_P0_RBCR0);
|
---|
177 | outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
|
---|
178 | outb(dst, eth_nic_base + D8390_P0_RSAR0);
|
---|
179 | outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
|
---|
180 | outb(D8390_COMMAND_RD1 |
|
---|
181 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
|
---|
182 |
|
---|
183 | #ifdef INCLUDE_3C503
|
---|
184 | outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
|
---|
185 | outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
|
---|
186 |
|
---|
187 | outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
|
---|
188 | #endif
|
---|
189 | #endif
|
---|
190 |
|
---|
191 | if (eth_flags & FLAG_16BIT)
|
---|
192 | cnt = (cnt + 1) >> 1;
|
---|
193 |
|
---|
194 | while(cnt--)
|
---|
195 | {
|
---|
196 | #ifdef INCLUDE_3C503
|
---|
197 | while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
|
---|
198 | ;
|
---|
199 | #endif
|
---|
200 |
|
---|
201 | if (eth_flags & FLAG_16BIT) {
|
---|
202 | outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
|
---|
203 | src += 2;
|
---|
204 | }
|
---|
205 | else
|
---|
206 | outb(*(src++), eth_asic_base + ASIC_PIO);
|
---|
207 | }
|
---|
208 |
|
---|
209 | #ifdef INCLUDE_3C503
|
---|
210 | outb(t503_output, eth_asic_base + _3COM_CR);
|
---|
211 | #else
|
---|
212 | #ifdef COMPEX_RL2000_FIX
|
---|
213 | for (x = 0;
|
---|
214 | x < COMPEX_RL2000_TRIES &&
|
---|
215 | (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
|
---|
216 | != D8390_ISR_RDC;
|
---|
217 | ++x);
|
---|
218 | if (x >= COMPEX_RL2000_TRIES)
|
---|
219 | printf("Warning: Compex RL2000 aborted wait!\n");
|
---|
220 | #endif /* COMPEX_RL2000_FIX */
|
---|
221 | #ifndef INCLUDE_WD
|
---|
222 | while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
|
---|
223 | != D8390_ISR_RDC);
|
---|
224 | #endif
|
---|
225 | #endif
|
---|
226 | }
|
---|
227 | #else
|
---|
228 | /**************************************************************************
|
---|
229 | ETH_PIO_READ - Dummy routine when NE2000 not compiled in
|
---|
230 | **************************************************************************/
|
---|
231 | static void eth_pio_read(unsigned int src __unused, unsigned char *dst __unused, unsigned int cnt __unused) {}
|
---|
232 | #endif
|
---|
233 |
|
---|
234 |
|
---|
235 | /**************************************************************************
|
---|
236 | enable_multycast - Enable Multicast
|
---|
237 | **************************************************************************/
|
---|
238 | static void enable_multicast(unsigned short eth_nic_base)
|
---|
239 | {
|
---|
240 | unsigned char mcfilter[8];
|
---|
241 | int i;
|
---|
242 | memset(mcfilter, 0xFF, 8);
|
---|
243 | outb(4, eth_nic_base+D8390_P0_RCR);
|
---|
244 | outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
|
---|
245 | for(i=0;i<8;i++)
|
---|
246 | {
|
---|
247 | outb(mcfilter[i], eth_nic_base + 8 + i);
|
---|
248 | if(inb(eth_nic_base + 8 + i)!=mcfilter[i])
|
---|
249 | printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i);
|
---|
250 | }
|
---|
251 | outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
|
---|
252 | outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);
|
---|
253 | }
|
---|
254 |
|
---|
255 | /**************************************************************************
|
---|
256 | NS8390_RESET - Reset adapter
|
---|
257 | **************************************************************************/
|
---|
258 | static void ns8390_reset(struct nic *nic)
|
---|
259 | {
|
---|
260 | int i;
|
---|
261 |
|
---|
262 | eth_drain_receiver = 0;
|
---|
263 | #ifdef INCLUDE_WD
|
---|
264 | if (eth_flags & FLAG_790)
|
---|
265 | outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
|
---|
266 | else
|
---|
267 | #endif
|
---|
268 | outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
|
---|
269 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
|
---|
270 | if (eth_flags & FLAG_16BIT)
|
---|
271 | outb(0x49, eth_nic_base+D8390_P0_DCR);
|
---|
272 | else
|
---|
273 | outb(0x48, eth_nic_base+D8390_P0_DCR);
|
---|
274 | outb(0, eth_nic_base+D8390_P0_RBCR0);
|
---|
275 | outb(0, eth_nic_base+D8390_P0_RBCR1);
|
---|
276 | outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
|
---|
277 | outb(2, eth_nic_base+D8390_P0_TCR);
|
---|
278 | outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
|
---|
279 | outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
|
---|
280 | #ifdef INCLUDE_WD
|
---|
281 | if (eth_flags & FLAG_790) {
|
---|
282 | #ifdef WD_790_PIO
|
---|
283 | outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */
|
---|
284 | outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */
|
---|
285 | #else
|
---|
286 | outb(0, eth_nic_base + 0x09);
|
---|
287 | #endif
|
---|
288 | }
|
---|
289 | #endif
|
---|
290 | outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
|
---|
291 | outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
|
---|
292 | outb(0xFF, eth_nic_base+D8390_P0_ISR);
|
---|
293 | outb(0, eth_nic_base+D8390_P0_IMR);
|
---|
294 | #ifdef INCLUDE_WD
|
---|
295 | if (eth_flags & FLAG_790)
|
---|
296 | outb(D8390_COMMAND_PS1 |
|
---|
297 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
|
---|
298 | else
|
---|
299 | #endif
|
---|
300 | outb(D8390_COMMAND_PS1 |
|
---|
301 | D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
|
---|
302 | for (i=0; i<ETH_ALEN; i++)
|
---|
303 | outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
|
---|
304 | for (i=0; i<ETH_ALEN; i++)
|
---|
305 | outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
|
---|
306 | outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
|
---|
307 | #ifdef INCLUDE_WD
|
---|
308 | if (eth_flags & FLAG_790)
|
---|
309 | outb(D8390_COMMAND_PS0 |
|
---|
310 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
|
---|
311 | else
|
---|
312 | #endif
|
---|
313 | outb(D8390_COMMAND_PS0 |
|
---|
314 | D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
|
---|
315 | outb(0xFF, eth_nic_base+D8390_P0_ISR);
|
---|
316 | outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
|
---|
317 | outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
|
---|
318 |
|
---|
319 | enable_multicast(eth_nic_base);
|
---|
320 |
|
---|
321 | #ifdef INCLUDE_3C503
|
---|
322 | /*
|
---|
323 | * No way to tell whether or not we're supposed to use
|
---|
324 | * the 3Com's transceiver unless the user tells us.
|
---|
325 | * 'flags' should have some compile time default value
|
---|
326 | * which can be changed from the command menu.
|
---|
327 | */
|
---|
328 | t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
|
---|
329 | outb(t503_output, eth_asic_base + _3COM_CR);
|
---|
330 | #endif
|
---|
331 | }
|
---|
332 |
|
---|
333 | static int ns8390_poll(struct nic *nic, int retrieve);
|
---|
334 |
|
---|
335 | #ifndef INCLUDE_3C503
|
---|
336 | /**************************************************************************
|
---|
337 | ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
|
---|
338 | **************************************************************************/
|
---|
339 | static void eth_rx_overrun(struct nic *nic)
|
---|
340 | {
|
---|
341 | int start_time;
|
---|
342 |
|
---|
343 | #ifdef INCLUDE_WD
|
---|
344 | if (eth_flags & FLAG_790)
|
---|
345 | outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
|
---|
346 | else
|
---|
347 | #endif
|
---|
348 | outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
|
---|
349 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
|
---|
350 |
|
---|
351 | /* wait for at least 1.6ms - we wait one timer tick */
|
---|
352 | start_time = currticks();
|
---|
353 | while (currticks() - start_time <= 1)
|
---|
354 | /* Nothing */;
|
---|
355 |
|
---|
356 | outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */
|
---|
357 | outb(0, eth_nic_base+D8390_P0_RBCR1);
|
---|
358 |
|
---|
359 | /*
|
---|
360 | * Linux driver checks for interrupted TX here. This is not necessary,
|
---|
361 | * because the transmit routine waits until the frame is sent.
|
---|
362 | */
|
---|
363 |
|
---|
364 | /* enter loopback mode and restart NIC */
|
---|
365 | outb(2, eth_nic_base+D8390_P0_TCR);
|
---|
366 | #ifdef INCLUDE_WD
|
---|
367 | if (eth_flags & FLAG_790)
|
---|
368 | outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
|
---|
369 | else
|
---|
370 | #endif
|
---|
371 | outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
|
---|
372 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
|
---|
373 |
|
---|
374 | /* clear the RX ring, acknowledge overrun interrupt */
|
---|
375 | eth_drain_receiver = 1;
|
---|
376 | while (ns8390_poll(nic, 1))
|
---|
377 | /* Nothing */;
|
---|
378 | eth_drain_receiver = 0;
|
---|
379 | outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
|
---|
380 |
|
---|
381 | /* leave loopback mode - no packets to be resent (see Linux driver) */
|
---|
382 | outb(0, eth_nic_base+D8390_P0_TCR);
|
---|
383 | }
|
---|
384 | #endif /* INCLUDE_3C503 */
|
---|
385 |
|
---|
386 | /**************************************************************************
|
---|
387 | NS8390_TRANSMIT - Transmit a frame
|
---|
388 | **************************************************************************/
|
---|
389 | static void ns8390_transmit(
|
---|
390 | struct nic *nic,
|
---|
391 | const char *d, /* Destination */
|
---|
392 | unsigned int t, /* Type */
|
---|
393 | unsigned int s, /* size */
|
---|
394 | const char *p) /* Packet */
|
---|
395 | {
|
---|
396 | #if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))
|
---|
397 | Address eth_vmem = bus_to_virt(eth_bmem);
|
---|
398 | #endif
|
---|
399 | #ifdef INCLUDE_3C503
|
---|
400 | if (!(eth_flags & FLAG_PIO)) {
|
---|
401 | memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
|
---|
402 | memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
|
---|
403 | *((char *)eth_vmem+12) = t>>8; /* type */
|
---|
404 | *((char *)eth_vmem+13) = t;
|
---|
405 | memcpy((char *)eth_vmem+ETH_HLEN, p, s);
|
---|
406 | s += ETH_HLEN;
|
---|
407 | while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
|
---|
408 | }
|
---|
409 | #endif
|
---|
410 |
|
---|
411 | #ifdef INCLUDE_WD
|
---|
412 | if (eth_flags & FLAG_16BIT) {
|
---|
413 | outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
|
---|
414 | inb(0x84);
|
---|
415 | }
|
---|
416 | #ifndef WD_790_PIO
|
---|
417 | /* Memory interface */
|
---|
418 | if (eth_flags & FLAG_790) {
|
---|
419 | outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
|
---|
420 | inb(0x84);
|
---|
421 | }
|
---|
422 | inb(0x84);
|
---|
423 | memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
|
---|
424 | memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
|
---|
425 | *((char *)eth_vmem+12) = t>>8; /* type */
|
---|
426 | *((char *)eth_vmem+13) = t;
|
---|
427 | memcpy((char *)eth_vmem+ETH_HLEN, p, s);
|
---|
428 | s += ETH_HLEN;
|
---|
429 | while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
|
---|
430 | if (eth_flags & FLAG_790) {
|
---|
431 | outb(0, eth_asic_base + WD_MSR);
|
---|
432 | inb(0x84);
|
---|
433 | }
|
---|
434 | #else
|
---|
435 | inb(0x84);
|
---|
436 | #endif
|
---|
437 | #endif
|
---|
438 |
|
---|
439 | #if defined(INCLUDE_3C503)
|
---|
440 | if (eth_flags & FLAG_PIO)
|
---|
441 | #endif
|
---|
442 | #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
|
---|
443 | {
|
---|
444 | /* Programmed I/O */
|
---|
445 | unsigned short type;
|
---|
446 | type = (t >> 8) | (t << 8);
|
---|
447 | eth_pio_write(d, eth_tx_start<<8, ETH_ALEN);
|
---|
448 | eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
|
---|
449 | /* bcc generates worse code without (const+const) below */
|
---|
450 | eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
|
---|
451 | eth_pio_write(p, (eth_tx_start<<8)+ETH_HLEN, s);
|
---|
452 | s += ETH_HLEN;
|
---|
453 | if (s < ETH_ZLEN) s = ETH_ZLEN;
|
---|
454 | }
|
---|
455 | #endif
|
---|
456 | #if defined(INCLUDE_3C503)
|
---|
457 | #endif
|
---|
458 |
|
---|
459 | #ifdef INCLUDE_WD
|
---|
460 | if (eth_flags & FLAG_16BIT) {
|
---|
461 | outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
|
---|
462 | inb(0x84);
|
---|
463 | }
|
---|
464 | if (eth_flags & FLAG_790)
|
---|
465 | outb(D8390_COMMAND_PS0 |
|
---|
466 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
|
---|
467 | else
|
---|
468 | #endif
|
---|
469 | outb(D8390_COMMAND_PS0 |
|
---|
470 | D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
|
---|
471 | outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
|
---|
472 | outb(s, eth_nic_base+D8390_P0_TBCR0);
|
---|
473 | outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
|
---|
474 | #ifdef INCLUDE_WD
|
---|
475 | if (eth_flags & FLAG_790)
|
---|
476 | outb(D8390_COMMAND_PS0 |
|
---|
477 | D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
|
---|
478 | else
|
---|
479 | #endif
|
---|
480 | outb(D8390_COMMAND_PS0 |
|
---|
481 | D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
|
---|
482 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
|
---|
483 | }
|
---|
484 |
|
---|
485 | /**************************************************************************
|
---|
486 | NS8390_POLL - Wait for a frame
|
---|
487 | **************************************************************************/
|
---|
488 | static int ns8390_poll(struct nic *nic, int retrieve)
|
---|
489 | {
|
---|
490 | int ret = 0;
|
---|
491 | unsigned char rstat, curr, next;
|
---|
492 | unsigned short len, frag;
|
---|
493 | unsigned short pktoff;
|
---|
494 | unsigned char *p;
|
---|
495 | struct ringbuffer pkthdr;
|
---|
496 |
|
---|
497 | #ifndef INCLUDE_3C503
|
---|
498 | /* avoid infinite recursion: see eth_rx_overrun() */
|
---|
499 | if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
|
---|
500 | eth_rx_overrun(nic);
|
---|
501 | return(0);
|
---|
502 | }
|
---|
503 | #endif /* INCLUDE_3C503 */
|
---|
504 | rstat = inb(eth_nic_base+D8390_P0_RSR);
|
---|
505 | if (!(rstat & D8390_RSTAT_PRX)) return(0);
|
---|
506 | next = inb(eth_nic_base+D8390_P0_BOUND)+1;
|
---|
507 | if (next >= eth_memsize) next = eth_rx_start;
|
---|
508 | outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
|
---|
509 | curr = inb(eth_nic_base+D8390_P1_CURR);
|
---|
510 | outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
|
---|
511 | if (curr >= eth_memsize) curr=eth_rx_start;
|
---|
512 | if (curr == next) return(0);
|
---|
513 |
|
---|
514 | if ( ! retrieve ) return 1;
|
---|
515 |
|
---|
516 | #ifdef INCLUDE_WD
|
---|
517 | if (eth_flags & FLAG_16BIT) {
|
---|
518 | outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
|
---|
519 | inb(0x84);
|
---|
520 | }
|
---|
521 | #ifndef WD_790_PIO
|
---|
522 | if (eth_flags & FLAG_790) {
|
---|
523 | outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
|
---|
524 | inb(0x84);
|
---|
525 | }
|
---|
526 | #endif
|
---|
527 | inb(0x84);
|
---|
528 | #endif
|
---|
529 | pktoff = next << 8;
|
---|
530 | if (eth_flags & FLAG_PIO)
|
---|
531 | eth_pio_read(pktoff, (char *)&pkthdr, 4);
|
---|
532 | else
|
---|
533 | memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
|
---|
534 | pktoff += sizeof(pkthdr);
|
---|
535 | /* incoming length includes FCS so must sub 4 */
|
---|
536 | len = pkthdr.len - 4;
|
---|
537 | if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
|
---|
538 | || len > ETH_FRAME_LEN) {
|
---|
539 | printf("Bogus packet, ignoring\n");
|
---|
540 | return (0);
|
---|
541 | }
|
---|
542 | else {
|
---|
543 | p = nic->packet;
|
---|
544 | nic->packetlen = len; /* available to caller */
|
---|
545 | frag = (eth_memsize << 8) - pktoff;
|
---|
546 | if (len > frag) { /* We have a wrap-around */
|
---|
547 | /* read first part */
|
---|
548 | if (eth_flags & FLAG_PIO)
|
---|
549 | eth_pio_read(pktoff, p, frag);
|
---|
550 | else
|
---|
551 | memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
|
---|
552 | pktoff = eth_rx_start << 8;
|
---|
553 | p += frag;
|
---|
554 | len -= frag;
|
---|
555 | }
|
---|
556 | /* read second part */
|
---|
557 | if (eth_flags & FLAG_PIO)
|
---|
558 | eth_pio_read(pktoff, p, len);
|
---|
559 | else
|
---|
560 | memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
|
---|
561 | ret = 1;
|
---|
562 | }
|
---|
563 | #ifdef INCLUDE_WD
|
---|
564 | #ifndef WD_790_PIO
|
---|
565 | if (eth_flags & FLAG_790) {
|
---|
566 | outb(0, eth_asic_base + WD_MSR);
|
---|
567 | inb(0x84);
|
---|
568 | }
|
---|
569 | #endif
|
---|
570 | if (eth_flags & FLAG_16BIT) {
|
---|
571 | outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
|
---|
572 | inb(0x84);
|
---|
573 | }
|
---|
574 | inb(0x84);
|
---|
575 | #endif
|
---|
576 | next = pkthdr.next; /* frame number of next packet */
|
---|
577 | if (next == eth_rx_start)
|
---|
578 | next = eth_memsize;
|
---|
579 | outb(next-1, eth_nic_base+D8390_P0_BOUND);
|
---|
580 | return(ret);
|
---|
581 | }
|
---|
582 |
|
---|
583 | /**************************************************************************
|
---|
584 | NS8390_DISABLE - Turn off adapter
|
---|
585 | **************************************************************************/
|
---|
586 | static void ns8390_disable(struct dev *dev)
|
---|
587 | {
|
---|
588 | struct nic *nic = (struct nic *)dev;
|
---|
589 | /* reset and disable merge */
|
---|
590 | ns8390_reset(nic);
|
---|
591 | }
|
---|
592 |
|
---|
593 | /**************************************************************************
|
---|
594 | NS8390_IRQ - Enable, Disable, or Force interrupts
|
---|
595 | **************************************************************************/
|
---|
596 | static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
|
---|
597 | {
|
---|
598 | switch ( action ) {
|
---|
599 | case DISABLE :
|
---|
600 | break;
|
---|
601 | case ENABLE :
|
---|
602 | break;
|
---|
603 | case FORCE :
|
---|
604 | break;
|
---|
605 | }
|
---|
606 | }
|
---|
607 |
|
---|
608 | /**************************************************************************
|
---|
609 | ETH_PROBE - Look for an adapter
|
---|
610 | **************************************************************************/
|
---|
611 | #ifdef INCLUDE_NS8390
|
---|
612 | static int eth_probe (struct dev *dev, struct pci_device *pci)
|
---|
613 | #else
|
---|
614 | static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)
|
---|
615 | #endif
|
---|
616 | {
|
---|
617 | struct nic *nic = (struct nic *)dev;
|
---|
618 | int i;
|
---|
619 | #ifdef INCLUDE_NS8390
|
---|
620 | unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };
|
---|
621 | unsigned short *probe_addrs = pci_probe_addrs;
|
---|
622 | #endif
|
---|
623 | eth_vendor = VENDOR_NONE;
|
---|
624 | eth_drain_receiver = 0;
|
---|
625 |
|
---|
626 | nic->irqno = 0;
|
---|
627 |
|
---|
628 | #ifdef INCLUDE_WD
|
---|
629 | {
|
---|
630 | /******************************************************************
|
---|
631 | Search for WD/SMC cards
|
---|
632 | ******************************************************************/
|
---|
633 | struct wd_board *brd;
|
---|
634 | unsigned short chksum;
|
---|
635 | unsigned char c;
|
---|
636 | for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
|
---|
637 | eth_asic_base += 0x20) {
|
---|
638 | chksum = 0;
|
---|
639 | for (i=8; i<16; i++)
|
---|
640 | chksum += inb(eth_asic_base+i);
|
---|
641 | /* Extra checks to avoid soundcard */
|
---|
642 | if ((chksum & 0xFF) == 0xFF &&
|
---|
643 | inb(eth_asic_base+8) != 0xFF &&
|
---|
644 | inb(eth_asic_base+9) != 0xFF)
|
---|
645 | break;
|
---|
646 | }
|
---|
647 | if (eth_asic_base > WD_HIGH_BASE)
|
---|
648 | return (0);
|
---|
649 | /* We've found a board */
|
---|
650 | eth_vendor = VENDOR_WD;
|
---|
651 | eth_nic_base = eth_asic_base + WD_NIC_ADDR;
|
---|
652 |
|
---|
653 | nic->ioaddr = eth_nic_base;
|
---|
654 |
|
---|
655 | c = inb(eth_asic_base+WD_BID); /* Get board id */
|
---|
656 | for (brd = wd_boards; brd->name; brd++)
|
---|
657 | if (brd->id == c) break;
|
---|
658 | if (!brd->name) {
|
---|
659 | printf("Unknown WD/SMC NIC type %hhX\n", c);
|
---|
660 | return (0); /* Unknown type */
|
---|
661 | }
|
---|
662 | eth_flags = brd->flags;
|
---|
663 | eth_memsize = brd->memsize;
|
---|
664 | eth_tx_start = 0;
|
---|
665 | eth_rx_start = D8390_TXBUF_SIZE;
|
---|
666 | if ((c == TYPE_WD8013EP) &&
|
---|
667 | (inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
|
---|
668 | eth_flags = FLAG_16BIT;
|
---|
669 | eth_memsize = MEM_16384;
|
---|
670 | }
|
---|
671 | if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
|
---|
672 | eth_bmem = (0x80000 |
|
---|
673 | ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
|
---|
674 | } else
|
---|
675 | eth_bmem = WD_DEFAULT_MEM;
|
---|
676 | if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
|
---|
677 | /* from Linux driver, 8416BT detects as 8216 sometimes */
|
---|
678 | unsigned int addr = inb(eth_asic_base + 0xb);
|
---|
679 | if (((addr >> 4) & 3) == 0) {
|
---|
680 | brd += 2;
|
---|
681 | eth_memsize = brd->memsize;
|
---|
682 | }
|
---|
683 | }
|
---|
684 | outb(0x80, eth_asic_base + WD_MSR); /* Reset */
|
---|
685 | for (i=0; i<ETH_ALEN; i++) {
|
---|
686 | nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
|
---|
687 | }
|
---|
688 | printf("\n%s base %#hx", brd->name, eth_asic_base);
|
---|
689 | if (eth_flags & FLAG_790) {
|
---|
690 | #ifdef WD_790_PIO
|
---|
691 | printf(", PIO mode, addr %!\n", nic->node_addr);
|
---|
692 | eth_bmem = 0;
|
---|
693 | eth_flags |= FLAG_PIO; /* force PIO mode */
|
---|
694 | outb(0, eth_asic_base+WD_MSR);
|
---|
695 | #else
|
---|
696 | printf(", memory %#x, addr %!\n", eth_bmem, nic->node_addr);
|
---|
697 | outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
|
---|
698 | outb((inb(eth_asic_base+0x04) |
|
---|
699 | 0x80), eth_asic_base+0x04);
|
---|
700 | outb(((unsigned)(eth_bmem >> 13) & 0x0F) |
|
---|
701 | ((unsigned)(eth_bmem >> 11) & 0x40) |
|
---|
702 | (inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
|
---|
703 | outb((inb(eth_asic_base+0x04) &
|
---|
704 | ~0x80), eth_asic_base+0x04);
|
---|
705 | #endif
|
---|
706 | } else {
|
---|
707 | printf(", memory %#x, addr %!\n", eth_bmem, nic->node_addr);
|
---|
708 | outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
|
---|
709 | }
|
---|
710 | if (eth_flags & FLAG_16BIT) {
|
---|
711 | if (eth_flags & FLAG_790) {
|
---|
712 | eth_laar = inb(eth_asic_base + WD_LAAR);
|
---|
713 | outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
|
---|
714 | } else {
|
---|
715 | outb((eth_laar =
|
---|
716 | WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
|
---|
717 | /*
|
---|
718 | The previous line used to be
|
---|
719 | WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
|
---|
720 | jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made
|
---|
721 | it work for WD8013s. This seems to work for my 8013 boards. I
|
---|
722 | don't know what is really happening. I wish I had data sheets
|
---|
723 | or more time to decode the Linux driver. - Ken
|
---|
724 | */
|
---|
725 | }
|
---|
726 | inb(0x84);
|
---|
727 | }
|
---|
728 | }
|
---|
729 | #endif
|
---|
730 | #ifdef INCLUDE_3C503
|
---|
731 | #ifdef T503_AUI
|
---|
732 | nic->flags = 1; /* aui */
|
---|
733 | #else
|
---|
734 | nic->flags = 0; /* no aui */
|
---|
735 | #endif
|
---|
736 | /******************************************************************
|
---|
737 | Search for 3Com 3c503 if no WD/SMC cards
|
---|
738 | ******************************************************************/
|
---|
739 | if (eth_vendor == VENDOR_NONE) {
|
---|
740 | int idx;
|
---|
741 | int iobase_reg, membase_reg;
|
---|
742 | static unsigned short base[] = {
|
---|
743 | 0x300, 0x310, 0x330, 0x350,
|
---|
744 | 0x250, 0x280, 0x2A0, 0x2E0, 0 };
|
---|
745 |
|
---|
746 | /* Loop through possible addresses checking each one */
|
---|
747 |
|
---|
748 | for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
|
---|
749 |
|
---|
750 | eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
|
---|
751 | /*
|
---|
752 | * Note that we use the same settings for both 8 and 16 bit cards:
|
---|
753 | * both have an 8K bank of memory at page 1 while only the 16 bit
|
---|
754 | * cards have a bank at page 0.
|
---|
755 | */
|
---|
756 | eth_memsize = MEM_16384;
|
---|
757 | eth_tx_start = 32;
|
---|
758 | eth_rx_start = 32 + D8390_TXBUF_SIZE;
|
---|
759 |
|
---|
760 | /* Check our base address. iobase and membase should */
|
---|
761 | /* both have a maximum of 1 bit set or be 0. */
|
---|
762 |
|
---|
763 | iobase_reg = inb(eth_asic_base + _3COM_BCFR);
|
---|
764 | membase_reg = inb(eth_asic_base + _3COM_PCFR);
|
---|
765 |
|
---|
766 | if ((iobase_reg & (iobase_reg - 1)) ||
|
---|
767 | (membase_reg & (membase_reg - 1)))
|
---|
768 | continue; /* nope */
|
---|
769 |
|
---|
770 | /* Now get the shared memory address */
|
---|
771 |
|
---|
772 | eth_flags = 0;
|
---|
773 |
|
---|
774 | switch (membase_reg) {
|
---|
775 | case _3COM_PCFR_DC000:
|
---|
776 | eth_bmem = 0xdc000;
|
---|
777 | break;
|
---|
778 | case _3COM_PCFR_D8000:
|
---|
779 | eth_bmem = 0xd8000;
|
---|
780 | break;
|
---|
781 | case _3COM_PCFR_CC000:
|
---|
782 | eth_bmem = 0xcc000;
|
---|
783 | break;
|
---|
784 | case _3COM_PCFR_C8000:
|
---|
785 | eth_bmem = 0xc8000;
|
---|
786 | break;
|
---|
787 | case _3COM_PCFR_PIO:
|
---|
788 | eth_flags |= FLAG_PIO;
|
---|
789 | eth_bmem = 0;
|
---|
790 | break;
|
---|
791 | default:
|
---|
792 | continue; /* nope */
|
---|
793 | }
|
---|
794 | break;
|
---|
795 | }
|
---|
796 |
|
---|
797 | if (base[idx] == 0) /* not found */
|
---|
798 | return (0);
|
---|
799 | #ifndef T503_SHMEM
|
---|
800 | eth_flags |= FLAG_PIO; /* force PIO mode */
|
---|
801 | eth_bmem = 0;
|
---|
802 | #endif
|
---|
803 | eth_vendor = VENDOR_3COM;
|
---|
804 |
|
---|
805 |
|
---|
806 | /* Need this to make ns8390_poll() happy. */
|
---|
807 |
|
---|
808 | eth_rmem = eth_bmem - 0x2000;
|
---|
809 |
|
---|
810 | /* Reset NIC and ASIC */
|
---|
811 |
|
---|
812 | outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
|
---|
813 | outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
|
---|
814 |
|
---|
815 | /* Get our ethernet address */
|
---|
816 |
|
---|
817 | outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
|
---|
818 | nic->ioaddr = eth_nic_base;
|
---|
819 | printf("\n3Com 3c503 base %#hx, ", eth_nic_base);
|
---|
820 | if (eth_flags & FLAG_PIO)
|
---|
821 | printf("PIO mode");
|
---|
822 | else
|
---|
823 | printf("memory %#x", eth_bmem);
|
---|
824 | for (i=0; i<ETH_ALEN; i++) {
|
---|
825 | nic->node_addr[i] = inb(eth_nic_base+i);
|
---|
826 | }
|
---|
827 | printf(", %s, addr %!\n", nic->flags ? "AUI" : "internal xcvr",
|
---|
828 | nic->node_addr);
|
---|
829 | outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
|
---|
830 | /*
|
---|
831 | * Initialize GA configuration register. Set bank and enable shared
|
---|
832 | * mem. We always use bank 1. Disable interrupts.
|
---|
833 | */
|
---|
834 | outb(_3COM_GACFR_RSEL |
|
---|
835 | _3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
|
---|
836 |
|
---|
837 | outb(0xff, eth_asic_base + _3COM_VPTR2);
|
---|
838 | outb(0xff, eth_asic_base + _3COM_VPTR1);
|
---|
839 | outb(0x00, eth_asic_base + _3COM_VPTR0);
|
---|
840 | /*
|
---|
841 | * Clear memory and verify that it worked (we use only 8K)
|
---|
842 | */
|
---|
843 |
|
---|
844 | if (!(eth_flags & FLAG_PIO)) {
|
---|
845 | memset(bus_to_virt(eth_bmem), 0, 0x2000);
|
---|
846 | for(i = 0; i < 0x2000; ++i)
|
---|
847 | if (*((char *)(bus_to_virt(eth_bmem+i)))) {
|
---|
848 | printf ("Failed to clear 3c503 shared mem.\n");
|
---|
849 | return (0);
|
---|
850 | }
|
---|
851 | }
|
---|
852 | /*
|
---|
853 | * Initialize GA page/start/stop registers.
|
---|
854 | */
|
---|
855 | outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
|
---|
856 | outb(eth_memsize, eth_asic_base + _3COM_PSPR);
|
---|
857 | }
|
---|
858 | #endif
|
---|
859 | #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
|
---|
860 | {
|
---|
861 | /******************************************************************
|
---|
862 | Search for NE1000/2000 if no WD/SMC or 3com cards
|
---|
863 | ******************************************************************/
|
---|
864 | unsigned char c;
|
---|
865 | if (eth_vendor == VENDOR_NONE) {
|
---|
866 | char romdata[16], testbuf[32];
|
---|
867 | int idx;
|
---|
868 | static char test[] = "NE*000 memory";
|
---|
869 | static unsigned short base[] = {
|
---|
870 | #ifdef NE_SCAN
|
---|
871 | NE_SCAN,
|
---|
872 | #endif
|
---|
873 | 0 };
|
---|
874 | /* if no addresses supplied, fall back on defaults */
|
---|
875 | if (probe_addrs == 0 || probe_addrs[0] == 0)
|
---|
876 | probe_addrs = base;
|
---|
877 | eth_bmem = 0; /* No shared memory */
|
---|
878 | for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
|
---|
879 | eth_flags = FLAG_PIO;
|
---|
880 | eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
|
---|
881 | eth_memsize = MEM_16384;
|
---|
882 | eth_tx_start = 32;
|
---|
883 | eth_rx_start = 32 + D8390_TXBUF_SIZE;
|
---|
884 | c = inb(eth_asic_base + NE_RESET);
|
---|
885 | outb(c, eth_asic_base + NE_RESET);
|
---|
886 | inb(0x84);
|
---|
887 | outb(D8390_COMMAND_STP |
|
---|
888 | D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
|
---|
889 | outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
|
---|
890 | outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
|
---|
891 | outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
|
---|
892 | outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
|
---|
893 | #ifdef NS8390_FORCE_16BIT
|
---|
894 | eth_flags |= FLAG_16BIT; /* force 16-bit mode */
|
---|
895 | #endif
|
---|
896 |
|
---|
897 | eth_pio_write(test, 8192, sizeof(test));
|
---|
898 | eth_pio_read(8192, testbuf, sizeof(test));
|
---|
899 | if (!memcmp(test, testbuf, sizeof(test)))
|
---|
900 | break;
|
---|
901 | eth_flags |= FLAG_16BIT;
|
---|
902 | eth_memsize = MEM_32768;
|
---|
903 | eth_tx_start = 64;
|
---|
904 | eth_rx_start = 64 + D8390_TXBUF_SIZE;
|
---|
905 | outb(D8390_DCR_WTS |
|
---|
906 | D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
|
---|
907 | outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
|
---|
908 | outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
|
---|
909 | eth_pio_write(test, 16384, sizeof(test));
|
---|
910 | eth_pio_read(16384, testbuf, sizeof(test));
|
---|
911 | if (!memcmp(testbuf, test, sizeof(test)))
|
---|
912 | break;
|
---|
913 | }
|
---|
914 | if (eth_nic_base == 0)
|
---|
915 | return (0);
|
---|
916 | if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
|
---|
917 | eth_flags |= FLAG_16BIT;
|
---|
918 | eth_vendor = VENDOR_NOVELL;
|
---|
919 | eth_pio_read(0, romdata, sizeof(romdata));
|
---|
920 | for (i=0; i<ETH_ALEN; i++) {
|
---|
921 | nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
|
---|
922 | }
|
---|
923 | nic->ioaddr = eth_nic_base;
|
---|
924 | printf("\nNE%c000 base %#hx, addr %!\n",
|
---|
925 | (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
|
---|
926 | nic->node_addr);
|
---|
927 | }
|
---|
928 | }
|
---|
929 | #endif
|
---|
930 | if (eth_vendor == VENDOR_NONE)
|
---|
931 | return(0);
|
---|
932 | if (eth_vendor != VENDOR_3COM)
|
---|
933 | eth_rmem = eth_bmem;
|
---|
934 | ns8390_reset(nic);
|
---|
935 |
|
---|
936 | dev->disable = ns8390_disable;
|
---|
937 | nic->poll = ns8390_poll;
|
---|
938 | nic->transmit = ns8390_transmit;
|
---|
939 | nic->irq = ns8390_irq;
|
---|
940 |
|
---|
941 | /* Based on PnP ISA map */
|
---|
942 | #ifdef INCLUDE_WD
|
---|
943 | dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
|
---|
944 | dev->devid.device_id = htons(0x812a);
|
---|
945 | #endif
|
---|
946 | #ifdef INCLUDE_3C503
|
---|
947 | dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
|
---|
948 | dev->devid.device_id = htons(0x80f3);
|
---|
949 | #endif
|
---|
950 | #ifdef INCLUDE_NE
|
---|
951 | dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
|
---|
952 | dev->devid.device_id = htons(0x80d6);
|
---|
953 | #endif
|
---|
954 | return 1;
|
---|
955 | }
|
---|
956 |
|
---|
957 | #ifdef INCLUDE_WD
|
---|
958 | static struct isa_driver wd_driver __isa_driver = {
|
---|
959 | .type = NIC_DRIVER,
|
---|
960 | .name = "WD",
|
---|
961 | .probe = wd_probe,
|
---|
962 | .ioaddrs = 0,
|
---|
963 | };
|
---|
964 | #endif
|
---|
965 |
|
---|
966 | #ifdef INCLUDE_3C503
|
---|
967 | static struct isa_driver t503_driver __isa_driver = {
|
---|
968 | .type = NIC_DRIVER,
|
---|
969 | .name = "3C503",
|
---|
970 | .probe = t503_probe,
|
---|
971 | .ioaddrs = 0,
|
---|
972 | };
|
---|
973 | #endif
|
---|
974 |
|
---|
975 | #ifdef INCLUDE_NE
|
---|
976 | static struct isa_driver ne_driver __isa_driver = {
|
---|
977 | .type = NIC_DRIVER,
|
---|
978 | .name = "NE*000",
|
---|
979 | .probe = ne_probe,
|
---|
980 | .ioaddrs = 0,
|
---|
981 | };
|
---|
982 | #endif
|
---|
983 |
|
---|
984 | #ifdef INCLUDE_NS8390
|
---|
985 | static struct pci_id nepci_nics[] = {
|
---|
986 | /* A few NE2000 PCI clones, list not exhaustive */
|
---|
987 | PCI_ROM(0x10ec, 0x8029, "rtl8029", "Realtek 8029"),
|
---|
988 | PCI_ROM(0x1186, 0x0300, "dlink-528", "D-Link DE-528"),
|
---|
989 | PCI_ROM(0x1050, 0x0940, "winbond940", "Winbond NE2000-PCI"), /* Winbond 86C940 / 89C940 */
|
---|
990 | PCI_ROM(0x1050, 0x5a5a, "winbond940f", "Winbond W89c940F"), /* Winbond 89C940F */
|
---|
991 | PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000"),
|
---|
992 | PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2"),
|
---|
993 | PCI_ROM(0x4a14, 0x5000, "nv5000sc", "NetVin NV5000SC"),
|
---|
994 | PCI_ROM(0x12c3, 0x0058, "holtek80232", "Holtek HT80232"),
|
---|
995 | PCI_ROM(0x12c3, 0x5598, "holtek80229", "Holtek HT80229"),
|
---|
996 | PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34"),
|
---|
997 | PCI_ROM(0x1106, 0x0926, "via86c926", "Via 86c926"),
|
---|
998 | };
|
---|
999 |
|
---|
1000 | static struct pci_driver nepci_driver __pci_driver = {
|
---|
1001 | .type = NIC_DRIVER,
|
---|
1002 | .name = "NE2000/PCI",
|
---|
1003 | .probe = nepci_probe,
|
---|
1004 | .ids = nepci_nics,
|
---|
1005 | .id_count = sizeof(nepci_nics)/sizeof(nepci_nics[0]),
|
---|
1006 | .class = 0,
|
---|
1007 | };
|
---|
1008 |
|
---|
1009 | #endif /* INCLUDE_NS8390 */
|
---|
1010 |
|
---|
1011 | /*
|
---|
1012 | * Local variables:
|
---|
1013 | * c-basic-offset: 8
|
---|
1014 | * End:
|
---|
1015 | */
|
---|
1016 |
|
---|