1 | /*
|
---|
2 | * eepro100.c -- This file implements the eepro100 driver for etherboot.
|
---|
3 | *
|
---|
4 | *
|
---|
5 | * Copyright (C) AW Computer Systems.
|
---|
6 | * written by R.E.Wolff -- [email protected]
|
---|
7 | *
|
---|
8 | *
|
---|
9 | * AW Computer Systems is contributing to the free software community
|
---|
10 | * by paying for this driver and then putting the result under GPL.
|
---|
11 | *
|
---|
12 | * If you need a Linux device driver, please contact BitWizard for a
|
---|
13 | * quote.
|
---|
14 | *
|
---|
15 | *
|
---|
16 | * This program is free software; you can redistribute it and/or
|
---|
17 | * modify it under the terms of the GNU General Public License as
|
---|
18 | * published by the Free Software Foundation; either version 2, or (at
|
---|
19 | * your option) any later version.
|
---|
20 | *
|
---|
21 | * This program is distributed in the hope that it will be useful, but
|
---|
22 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
24 | * General Public License for more details.
|
---|
25 | *
|
---|
26 | * You should have received a copy of the GNU General Public License
|
---|
27 | * along with this program; if not, write to the Free Software
|
---|
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
29 | *
|
---|
30 | *
|
---|
31 | * date version by what
|
---|
32 | * Written: May 29 1997 V0.10 REW Initial revision.
|
---|
33 | * changes: May 31 1997 V0.90 REW Works!
|
---|
34 | * Jun 1 1997 V0.91 REW Cleanup
|
---|
35 | * Jun 2 1997 V0.92 REW Add some code documentation
|
---|
36 | * Jul 25 1997 V1.00 REW Tested by AW to work in a PROM
|
---|
37 | * Cleanup for publication
|
---|
38 | * Dez 11 2004 V1.10 Kiszka Add RX ring buffer support
|
---|
39 | *
|
---|
40 | * This is the etherboot intel etherexpress Pro/100B driver.
|
---|
41 | *
|
---|
42 | * It was written from scratch, with Donald Beckers eepro100.c kernel
|
---|
43 | * driver as a guideline. Mostly the 82557 related definitions and the
|
---|
44 | * lower level routines have been cut-and-pasted into this source.
|
---|
45 | *
|
---|
46 | * The driver was finished before Intel got the NDA out of the closet.
|
---|
47 | * I still don't have the docs.
|
---|
48 | *
|
---|
49 | *
|
---|
50 | * Datasheet is now published and available from
|
---|
51 | * ftp://download.intel.com/design/network/manuals/8255X_OpenSDM.pdf
|
---|
52 | * - Michael Brown
|
---|
53 | * */
|
---|
54 |
|
---|
55 | /* Philosophy of this driver.
|
---|
56 | *
|
---|
57 | * Probing:
|
---|
58 | *
|
---|
59 | * Using the pci.c functions of the Etherboot code, the 82557 chip is detected.
|
---|
60 | * It is verified that the BIOS initialized everything properly and if
|
---|
61 | * something is missing it is done now.
|
---|
62 | *
|
---|
63 | *
|
---|
64 | * Initialization:
|
---|
65 | *
|
---|
66 | *
|
---|
67 | * The chip is then initialized to "know" its ethernet address, and to
|
---|
68 | * start recieving packets. The Linux driver has a whole transmit and
|
---|
69 | * recieve ring of buffers. This is neat if you need high performance:
|
---|
70 | * you can write the buffers asynchronously to the chip reading the
|
---|
71 | * buffers and transmitting them over the network. Performance is NOT
|
---|
72 | * an issue here. We can boot a 400k kernel in about two
|
---|
73 | * seconds. (Theory: 0.4 seconds). Booting a system is going to take
|
---|
74 | * about half a minute anyway, so getting 10 times closer to the
|
---|
75 | * theoretical limit is going to make a difference of a few percent. */
|
---|
76 | /* Not totally true: busy networks can cause packet drops due to RX
|
---|
77 | * buffer overflows. Fixed in V1.10 of this driver. [Kiszka] */
|
---|
78 | /*
|
---|
79 | *
|
---|
80 | * Transmitting and recieving.
|
---|
81 | *
|
---|
82 | * We have only one transmit descriptor. It has two buffer descriptors:
|
---|
83 | * one for the header, and the other for the data.
|
---|
84 | * We have multiple receive buffers (currently: 4). The chip is told to
|
---|
85 | * receive packets and suspend itself once it ran on the last free buffer.
|
---|
86 | * The recieve (poll) routine simply looks at the current recieve buffer,
|
---|
87 | * picks the packet if any, and releases this buffer again (classic ring
|
---|
88 | * buffer concept). This helps to avoid packet drops on busy networks.
|
---|
89 | *
|
---|
90 | * Caveats:
|
---|
91 | *
|
---|
92 | * The Etherboot framework moves the code to the 48k segment from
|
---|
93 | * 0x94000 to 0xa0000. There is just a little room between the end of
|
---|
94 | * this driver and the 0xa0000 address. If you compile in too many
|
---|
95 | * features, this will overflow.
|
---|
96 | * The number under "hex" in the output of size that scrolls by while
|
---|
97 | * compiling should be less than 8000. Maybe even the stack is up there,
|
---|
98 | * so that you need even more headroom.
|
---|
99 | */
|
---|
100 |
|
---|
101 | /* The etherboot authors seem to dislike the argument ordering in
|
---|
102 | * outb macros that Linux uses. I disklike the confusion that this
|
---|
103 | * has caused even more.... This file uses the Linux argument ordering. */
|
---|
104 | /* Sorry not us. It's inherited code from FreeBSD. [The authors] */
|
---|
105 |
|
---|
106 | #include "etherboot.h"
|
---|
107 | #include "nic.h"
|
---|
108 | #include "pci.h"
|
---|
109 | #include "timer.h"
|
---|
110 |
|
---|
111 | static int ioaddr;
|
---|
112 |
|
---|
113 | enum speedo_offsets {
|
---|
114 | SCBStatus = 0, SCBCmd = 2, /* Rx/Command Unit command and status. */
|
---|
115 | SCBPointer = 4, /* General purpose pointer. */
|
---|
116 | SCBPort = 8, /* Misc. commands and operands. */
|
---|
117 | SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
|
---|
118 | SCBCtrlMDI = 16, /* MDI interface control. */
|
---|
119 | SCBEarlyRx = 20, /* Early receive byte count. */
|
---|
120 | };
|
---|
121 |
|
---|
122 | enum SCBCmdBits {
|
---|
123 | SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
|
---|
124 | SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
|
---|
125 | SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
|
---|
126 | /* The rest are Rx and Tx commands. */
|
---|
127 | CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
|
---|
128 | CUCmdBase=0x0060, /* CU Base address (set to zero) . */
|
---|
129 | CUDumpStats=0x0070, /* Dump then reset stats counters. */
|
---|
130 | RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
|
---|
131 | RxResumeNoResources=0x0007,
|
---|
132 | };
|
---|
133 |
|
---|
134 | static int do_eeprom_cmd(int cmd, int cmd_len);
|
---|
135 | void hd(void *where, int n);
|
---|
136 |
|
---|
137 | /***********************************************************************/
|
---|
138 | /* I82557 related defines */
|
---|
139 | /***********************************************************************/
|
---|
140 |
|
---|
141 | /* Serial EEPROM section.
|
---|
142 | A "bit" grungy, but we work our way through bit-by-bit :->. */
|
---|
143 | /* EEPROM_Ctrl bits. */
|
---|
144 | #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
|
---|
145 | #define EE_CS 0x02 /* EEPROM chip select. */
|
---|
146 | #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
|
---|
147 | #define EE_DATA_READ 0x08 /* EEPROM chip data out. */
|
---|
148 | #define EE_WRITE_0 0x4802
|
---|
149 | #define EE_WRITE_1 0x4806
|
---|
150 | #define EE_ENB (0x4800 | EE_CS)
|
---|
151 |
|
---|
152 | /* The EEPROM commands include the alway-set leading bit. */
|
---|
153 | #define EE_READ_CMD 6
|
---|
154 |
|
---|
155 | /* The SCB accepts the following controls for the Tx and Rx units: */
|
---|
156 | #define CU_START 0x0010
|
---|
157 | #define CU_RESUME 0x0020
|
---|
158 | #define CU_STATSADDR 0x0040
|
---|
159 | #define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */
|
---|
160 | #define CU_CMD_BASE 0x0060 /* Base address to add to add CU commands. */
|
---|
161 | #define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */
|
---|
162 |
|
---|
163 | #define RX_START 0x0001
|
---|
164 | #define RX_RESUME 0x0002
|
---|
165 | #define RX_ABORT 0x0004
|
---|
166 | #define RX_ADDR_LOAD 0x0006
|
---|
167 | #define RX_RESUMENR 0x0007
|
---|
168 | #define INT_MASK 0x0100
|
---|
169 | #define DRVR_INT 0x0200 /* Driver generated interrupt. */
|
---|
170 |
|
---|
171 | enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
|
---|
172 | S80C24, PhyUndefined, DP83840A=10, };
|
---|
173 |
|
---|
174 | /* Commands that can be put in a command list entry. */
|
---|
175 | enum commands {
|
---|
176 | CmdNOp = 0,
|
---|
177 | CmdIASetup = 1,
|
---|
178 | CmdConfigure = 2,
|
---|
179 | CmdMulticastList = 3,
|
---|
180 | CmdTx = 4,
|
---|
181 | CmdTDR = 5,
|
---|
182 | CmdDump = 6,
|
---|
183 | CmdDiagnose = 7,
|
---|
184 |
|
---|
185 | /* And some extra flags: */
|
---|
186 | CmdSuspend = 0x4000, /* Suspend after completion. */
|
---|
187 | CmdIntr = 0x2000, /* Interrupt after completion. */
|
---|
188 | CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */
|
---|
189 | };
|
---|
190 |
|
---|
191 | /* How to wait for the command unit to accept a command.
|
---|
192 | Typically this takes 0 ticks. */
|
---|
193 | static inline void wait_for_cmd_done(int cmd_ioaddr)
|
---|
194 | {
|
---|
195 | int wait = 0;
|
---|
196 | int delayed_cmd;
|
---|
197 |
|
---|
198 | do
|
---|
199 | if (inb(cmd_ioaddr) == 0) return;
|
---|
200 | while(++wait <= 100);
|
---|
201 | delayed_cmd = inb(cmd_ioaddr);
|
---|
202 | do
|
---|
203 | if (inb(cmd_ioaddr) == 0) break;
|
---|
204 | while(++wait <= 10000);
|
---|
205 | printf("Command %2.2x was not immediately accepted, %d ticks!\n",
|
---|
206 | delayed_cmd, wait);
|
---|
207 | }
|
---|
208 |
|
---|
209 | /* Elements of the dump_statistics block. This block must be lword aligned. */
|
---|
210 | static struct speedo_stats {
|
---|
211 | u32 tx_good_frames;
|
---|
212 | u32 tx_coll16_errs;
|
---|
213 | u32 tx_late_colls;
|
---|
214 | u32 tx_underruns;
|
---|
215 | u32 tx_lost_carrier;
|
---|
216 | u32 tx_deferred;
|
---|
217 | u32 tx_one_colls;
|
---|
218 | u32 tx_multi_colls;
|
---|
219 | u32 tx_total_colls;
|
---|
220 | u32 rx_good_frames;
|
---|
221 | u32 rx_crc_errs;
|
---|
222 | u32 rx_align_errs;
|
---|
223 | u32 rx_resource_errs;
|
---|
224 | u32 rx_overrun_errs;
|
---|
225 | u32 rx_colls_errs;
|
---|
226 | u32 rx_runt_errs;
|
---|
227 | u32 done_marker;
|
---|
228 | } lstats;
|
---|
229 |
|
---|
230 | /* A speedo3 TX buffer descriptor with two buffers... */
|
---|
231 | static struct TxFD {
|
---|
232 | volatile s16 status;
|
---|
233 | s16 command;
|
---|
234 | u32 link; /* void * */
|
---|
235 | u32 tx_desc_addr; /* (almost) Always points to the tx_buf_addr element. */
|
---|
236 | s32 count; /* # of TBD (=2), Tx start thresh., etc. */
|
---|
237 | /* This constitutes two "TBD" entries: hdr and data */
|
---|
238 | u32 tx_buf_addr0; /* void *, header of frame to be transmitted. */
|
---|
239 | s32 tx_buf_size0; /* Length of Tx hdr. */
|
---|
240 | u32 tx_buf_addr1; /* void *, data to be transmitted. */
|
---|
241 | s32 tx_buf_size1; /* Length of Tx data. */
|
---|
242 | } txfd;
|
---|
243 |
|
---|
244 | struct RxFD { /* Receive frame descriptor. */
|
---|
245 | volatile s16 status;
|
---|
246 | s16 command;
|
---|
247 | u32 link; /* struct RxFD * */
|
---|
248 | u32 rx_buf_addr; /* void * */
|
---|
249 | u16 count;
|
---|
250 | u16 size;
|
---|
251 | char packet[1518];
|
---|
252 | };
|
---|
253 |
|
---|
254 | #define RXFD_COUNT 4
|
---|
255 | static struct RxFD rxfds[RXFD_COUNT];
|
---|
256 | static unsigned int rxfd = 0;
|
---|
257 |
|
---|
258 | static int congenb = 0; /* Enable congestion control in the DP83840. */
|
---|
259 | static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */
|
---|
260 | static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */
|
---|
261 | static int txdmacount = 0; /* Tx DMA burst length, 0-127, default 0. */
|
---|
262 | static int rxdmacount = 0; /* Rx DMA length, 0 means no preemption. */
|
---|
263 |
|
---|
264 | /* I don't understand a byte in this structure. It was copied from the
|
---|
265 | * Linux kernel initialization for the eepro100. -- REW */
|
---|
266 | static struct ConfCmd {
|
---|
267 | s16 status;
|
---|
268 | s16 command;
|
---|
269 | u32 link;
|
---|
270 | unsigned char data[22];
|
---|
271 | } confcmd = {
|
---|
272 | 0, 0, 0, /* filled in later */
|
---|
273 | {22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */
|
---|
274 | 0, 0x2E, 0, 0x60, 0,
|
---|
275 | 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */
|
---|
276 | 0x3f, 0x05, }
|
---|
277 | };
|
---|
278 |
|
---|
279 | /***********************************************************************/
|
---|
280 | /* Locally used functions */
|
---|
281 | /***********************************************************************/
|
---|
282 |
|
---|
283 | /* Support function: mdio_write
|
---|
284 | *
|
---|
285 | * This probably writes to the "physical media interface chip".
|
---|
286 | * -- REW
|
---|
287 | */
|
---|
288 |
|
---|
289 | static int mdio_write(int phy_id, int location, int value)
|
---|
290 | {
|
---|
291 | int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
|
---|
292 |
|
---|
293 | outl(0x04000000 | (location<<16) | (phy_id<<21) | value,
|
---|
294 | ioaddr + SCBCtrlMDI);
|
---|
295 | do {
|
---|
296 | udelay(16);
|
---|
297 |
|
---|
298 | val = inl(ioaddr + SCBCtrlMDI);
|
---|
299 | if (--boguscnt < 0) {
|
---|
300 | printf(" mdio_write() timed out with val = %X.\n", val);
|
---|
301 | break;
|
---|
302 | }
|
---|
303 | } while (! (val & 0x10000000));
|
---|
304 | return val & 0xffff;
|
---|
305 | }
|
---|
306 |
|
---|
307 | /* Support function: mdio_read
|
---|
308 | *
|
---|
309 | * This probably reads a register in the "physical media interface chip".
|
---|
310 | * -- REW
|
---|
311 | */
|
---|
312 | static int mdio_read(int phy_id, int location)
|
---|
313 | {
|
---|
314 | int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
|
---|
315 | outl(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
|
---|
316 | do {
|
---|
317 | udelay(16);
|
---|
318 |
|
---|
319 | val = inl(ioaddr + SCBCtrlMDI);
|
---|
320 |
|
---|
321 | if (--boguscnt < 0) {
|
---|
322 | printf( " mdio_read() timed out with val = %X.\n", val);
|
---|
323 | break;
|
---|
324 | }
|
---|
325 | } while (! (val & 0x10000000));
|
---|
326 | return val & 0xffff;
|
---|
327 | }
|
---|
328 |
|
---|
329 | /* The fixes for the code were kindly provided by Dragan Stancevic
|
---|
330 | <[email protected]> to strictly follow Intel specifications of EEPROM
|
---|
331 | access timing.
|
---|
332 | The publicly available sheet 64486302 (sec. 3.1) specifies 1us access
|
---|
333 | interval for serial EEPROM. However, it looks like that there is an
|
---|
334 | additional requirement dictating larger udelay's in the code below.
|
---|
335 | 2000/05/24 SAW */
|
---|
336 | static int do_eeprom_cmd(int cmd, int cmd_len)
|
---|
337 | {
|
---|
338 | unsigned retval = 0;
|
---|
339 | long ee_addr = ioaddr + SCBeeprom;
|
---|
340 |
|
---|
341 | outw(EE_ENB, ee_addr); udelay(2);
|
---|
342 | outw(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2);
|
---|
343 |
|
---|
344 | /* Shift the command bits out. */
|
---|
345 | do {
|
---|
346 | short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
|
---|
347 | outw(dataval, ee_addr); udelay(2);
|
---|
348 | outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);
|
---|
349 | retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
|
---|
350 | } while (--cmd_len >= 0);
|
---|
351 | outw(EE_ENB, ee_addr); udelay(2);
|
---|
352 |
|
---|
353 | /* Terminate the EEPROM access. */
|
---|
354 | outw(EE_ENB & ~EE_CS, ee_addr);
|
---|
355 | return retval;
|
---|
356 | }
|
---|
357 |
|
---|
358 | #if 0
|
---|
359 | static inline void whereami (const char *str)
|
---|
360 | {
|
---|
361 | printf ("%s\n", str);
|
---|
362 | sleep (2);
|
---|
363 | }
|
---|
364 | #else
|
---|
365 | #define whereami(s)
|
---|
366 | #endif
|
---|
367 |
|
---|
368 | static void eepro100_irq(struct nic *nic __unused, irq_action_t action)
|
---|
369 | {
|
---|
370 | uint16_t enabled_mask = ( SCBMaskCmdDone | SCBMaskCmdIdle |
|
---|
371 | SCBMaskEarlyRx | SCBMaskFlowCtl );
|
---|
372 |
|
---|
373 | switch ( action ) {
|
---|
374 | case DISABLE :
|
---|
375 | outw(SCBMaskAll, ioaddr + SCBCmd);
|
---|
376 | break;
|
---|
377 | case ENABLE :
|
---|
378 | outw(enabled_mask, ioaddr + SCBCmd);
|
---|
379 | break;
|
---|
380 | case FORCE :
|
---|
381 | outw(enabled_mask | SCBTriggerIntr, ioaddr + SCBCmd);
|
---|
382 | break;
|
---|
383 | }
|
---|
384 | }
|
---|
385 |
|
---|
386 | /* function: eepro100_transmit
|
---|
387 | * This transmits a packet.
|
---|
388 | *
|
---|
389 | * Arguments: char d[6]: destination ethernet address.
|
---|
390 | * unsigned short t: ethernet protocol type.
|
---|
391 | * unsigned short s: size of the data-part of the packet.
|
---|
392 | * char *p: the data for the packet.
|
---|
393 | * returns: void.
|
---|
394 | */
|
---|
395 |
|
---|
396 | static void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
|
---|
397 | {
|
---|
398 | struct eth_hdr {
|
---|
399 | unsigned char dst_addr[ETH_ALEN];
|
---|
400 | unsigned char src_addr[ETH_ALEN];
|
---|
401 | unsigned short type;
|
---|
402 | } hdr;
|
---|
403 | unsigned short status;
|
---|
404 | int s1, s2;
|
---|
405 |
|
---|
406 | status = inw(ioaddr + SCBStatus);
|
---|
407 | /* Acknowledge all of the current interrupt sources ASAP. */
|
---|
408 | outw(status & 0xfc00, ioaddr + SCBStatus);
|
---|
409 |
|
---|
410 | #ifdef DEBUG
|
---|
411 | printf ("transmitting type %hX packet (%d bytes). status = %hX, cmd=%hX\n",
|
---|
412 | t, s, status, inw (ioaddr + SCBCmd));
|
---|
413 | #endif
|
---|
414 |
|
---|
415 | memcpy (&hdr.dst_addr, d, ETH_ALEN);
|
---|
416 | memcpy (&hdr.src_addr, nic->node_addr, ETH_ALEN);
|
---|
417 |
|
---|
418 | hdr.type = htons (t);
|
---|
419 |
|
---|
420 | txfd.status = 0;
|
---|
421 | txfd.command = CmdSuspend | CmdTx | CmdTxFlex;
|
---|
422 | txfd.link = virt_to_bus (&txfd);
|
---|
423 | txfd.count = 0x02208000;
|
---|
424 | txfd.tx_desc_addr = virt_to_bus(&txfd.tx_buf_addr0);
|
---|
425 |
|
---|
426 | txfd.tx_buf_addr0 = virt_to_bus (&hdr);
|
---|
427 | txfd.tx_buf_size0 = sizeof (hdr);
|
---|
428 |
|
---|
429 | txfd.tx_buf_addr1 = virt_to_bus (p);
|
---|
430 | txfd.tx_buf_size1 = s;
|
---|
431 |
|
---|
432 | #ifdef DEBUG
|
---|
433 | printf ("txfd: \n");
|
---|
434 | hd (&txfd, sizeof (txfd));
|
---|
435 | #endif
|
---|
436 |
|
---|
437 | outl(virt_to_bus(&txfd), ioaddr + SCBPointer);
|
---|
438 | outb(CU_START, ioaddr + SCBCmd);
|
---|
439 | wait_for_cmd_done(ioaddr + SCBCmd);
|
---|
440 |
|
---|
441 | s1 = inw (ioaddr + SCBStatus);
|
---|
442 | load_timer2(10*TICKS_PER_MS); /* timeout 10 ms for transmit */
|
---|
443 | while (!txfd.status && timer2_running())
|
---|
444 | /* Wait */;
|
---|
445 | s2 = inw (ioaddr + SCBStatus);
|
---|
446 |
|
---|
447 | #ifdef DEBUG
|
---|
448 | printf ("s1 = %hX, s2 = %hX.\n", s1, s2);
|
---|
449 | #endif
|
---|
450 | }
|
---|
451 |
|
---|
452 | /*
|
---|
453 | * Sometimes the receiver stops making progress. This routine knows how to
|
---|
454 | * get it going again, without losing packets or being otherwise nasty like
|
---|
455 | * a chip reset would be. Previously the driver had a whole sequence
|
---|
456 | * of if RxSuspended, if it's no buffers do one thing, if it's no resources,
|
---|
457 | * do another, etc. But those things don't really matter. Separate logic
|
---|
458 | * in the ISR provides for allocating buffers--the other half of operation
|
---|
459 | * is just making sure the receiver is active. speedo_rx_soft_reset does that.
|
---|
460 | * This problem with the old, more involved algorithm is shown up under
|
---|
461 | * ping floods on the order of 60K packets/second on a 100Mbps fdx network.
|
---|
462 | */
|
---|
463 | static void
|
---|
464 | speedo_rx_soft_reset(void)
|
---|
465 | {
|
---|
466 | int i;
|
---|
467 |
|
---|
468 |
|
---|
469 | #ifdef DEBUG
|
---|
470 | printf("reset\n");
|
---|
471 | #endif
|
---|
472 | wait_for_cmd_done(ioaddr + SCBCmd);
|
---|
473 | /*
|
---|
474 | * Put the hardware into a known state.
|
---|
475 | */
|
---|
476 | outb(RX_ABORT, ioaddr + SCBCmd);
|
---|
477 |
|
---|
478 | for (i = 0; i < RXFD_COUNT; i++) {
|
---|
479 | rxfds[i].status = 0;
|
---|
480 | rxfds[i].rx_buf_addr = 0xffffffff;
|
---|
481 | rxfds[i].count = 0;
|
---|
482 | rxfds[i].size = 1528;
|
---|
483 | }
|
---|
484 |
|
---|
485 | wait_for_cmd_done(ioaddr + SCBCmd);
|
---|
486 |
|
---|
487 | outl(virt_to_bus(&rxfds[rxfd]), ioaddr + SCBPointer);
|
---|
488 | outb(RX_START, ioaddr + SCBCmd);
|
---|
489 | }
|
---|
490 |
|
---|
491 | /* function: eepro100_poll / eth_poll
|
---|
492 | * This receives a packet from the network.
|
---|
493 | *
|
---|
494 | * Arguments: none
|
---|
495 | *
|
---|
496 | * returns: 1 if a packet was received.
|
---|
497 | * 0 if no packet was received.
|
---|
498 | * side effects:
|
---|
499 | * returns the packet in the array nic->packet.
|
---|
500 | * returns the length of the packet in nic->packetlen.
|
---|
501 | */
|
---|
502 |
|
---|
503 | static int eepro100_poll(struct nic *nic, int retrieve)
|
---|
504 | {
|
---|
505 | if (rxfds[rxfd].status) {
|
---|
506 | if (!retrieve)
|
---|
507 | return 1;
|
---|
508 | #ifdef DEBUG
|
---|
509 | printf("Got a packet: Len = %d, rxfd = %d.\n",
|
---|
510 | rxfds[rxfd].count & 0x3fff, rxfd);
|
---|
511 | #endif
|
---|
512 | /* First save the data from the rxfd */
|
---|
513 | nic->packetlen = rxfds[rxfd].count & 0x3fff;
|
---|
514 | memcpy(nic->packet, rxfds[rxfd].packet, nic->packetlen);
|
---|
515 |
|
---|
516 | rxfds[rxfd].status = 0;
|
---|
517 | rxfds[rxfd].command = 0xc000;
|
---|
518 | rxfds[rxfd].rx_buf_addr = 0xFFFFFFFF;
|
---|
519 | rxfds[rxfd].count = 0;
|
---|
520 | rxfds[rxfd].size = 1528;
|
---|
521 | rxfds[(rxfd-1) % RXFD_COUNT].command = 0x0000;
|
---|
522 | rxfd = (rxfd+1) % RXFD_COUNT;
|
---|
523 |
|
---|
524 | #ifdef DEBUG
|
---|
525 | hd (nic->packet, 0x30);
|
---|
526 | #endif
|
---|
527 |
|
---|
528 | /* Acknowledge all conceivable interrupts */
|
---|
529 | outw(0xff00, ioaddr + SCBStatus);
|
---|
530 |
|
---|
531 | return 1;
|
---|
532 | }
|
---|
533 |
|
---|
534 | /*
|
---|
535 | * The chip may have suspended reception for various reasons.
|
---|
536 | * Check for that, and re-prime it should this be the case.
|
---|
537 | */
|
---|
538 | switch ((inw(ioaddr + SCBStatus) >> 2) & 0xf) {
|
---|
539 | case 0: /* Idle */
|
---|
540 | break;
|
---|
541 | case 1: /* Suspended */
|
---|
542 | case 2: /* No resources (RxFDs) */
|
---|
543 | case 9: /* Suspended with no more RBDs */
|
---|
544 | case 10: /* No resources due to no RBDs */
|
---|
545 | case 12: /* Ready with no RBDs */
|
---|
546 | speedo_rx_soft_reset();
|
---|
547 | break;
|
---|
548 | default:
|
---|
549 | /* reserved values */
|
---|
550 | break;
|
---|
551 | }
|
---|
552 | return 0;
|
---|
553 | }
|
---|
554 |
|
---|
555 | /* function: eepro100_disable
|
---|
556 | * resets the card. This is used to allow Etherboot or Linux
|
---|
557 | * to probe the card again from a "virginal" state....
|
---|
558 | * Arguments: none
|
---|
559 | *
|
---|
560 | * returns: void.
|
---|
561 | */
|
---|
562 | static void eepro100_disable(struct dev *dev __unused)
|
---|
563 | {
|
---|
564 | /* from eepro100_reset */
|
---|
565 | outl(0, ioaddr + SCBPort);
|
---|
566 | /* from eepro100_disable */
|
---|
567 | /* See if this PartialReset solves the problem with interfering with
|
---|
568 | kernel operation after Etherboot hands over. - Ken 20001102 */
|
---|
569 | outl(2, ioaddr + SCBPort);
|
---|
570 |
|
---|
571 | /* The following is from the Intel e100 driver.
|
---|
572 | * This hopefully solves the problem with hanging hard DOS images. */
|
---|
573 |
|
---|
574 | /* wait for the reset to take effect */
|
---|
575 | udelay(20);
|
---|
576 |
|
---|
577 | /* Mask off our interrupt line -- it is unmasked after reset */
|
---|
578 | {
|
---|
579 | u16 intr_status;
|
---|
580 | /* Disable interrupts on our PCI board by setting the mask bit */
|
---|
581 | outw(INT_MASK, ioaddr + SCBCmd);
|
---|
582 | intr_status = inw(ioaddr + SCBStatus);
|
---|
583 | /* ack and clear intrs */
|
---|
584 | outw(intr_status, ioaddr + SCBStatus);
|
---|
585 | inw(ioaddr + SCBStatus);
|
---|
586 | }
|
---|
587 | }
|
---|
588 |
|
---|
589 | /* exported function: eepro100_probe / eth_probe
|
---|
590 | * initializes a card
|
---|
591 | *
|
---|
592 | * side effects:
|
---|
593 | * leaves the ioaddress of the 82557 chip in the variable ioaddr.
|
---|
594 | * leaves the 82557 initialized, and ready to recieve packets.
|
---|
595 | */
|
---|
596 |
|
---|
597 | static int eepro100_probe(struct dev *dev, struct pci_device *p)
|
---|
598 | {
|
---|
599 | struct nic *nic = (struct nic *)dev;
|
---|
600 | unsigned short sum = 0;
|
---|
601 | int i;
|
---|
602 | int read_cmd, ee_size;
|
---|
603 | int options;
|
---|
604 | int rx_mode;
|
---|
605 |
|
---|
606 | /* we cache only the first few words of the EEPROM data
|
---|
607 | be careful not to access beyond this array */
|
---|
608 | unsigned short eeprom[16];
|
---|
609 |
|
---|
610 | if (p->ioaddr == 0)
|
---|
611 | return 0;
|
---|
612 | ioaddr = p->ioaddr & ~3; /* Mask the bit that says "this is an io addr" */
|
---|
613 | nic->ioaddr = ioaddr;
|
---|
614 |
|
---|
615 | adjust_pci_device(p);
|
---|
616 |
|
---|
617 | /* Copy IRQ from PCI information */
|
---|
618 | nic->irqno = p->irq;
|
---|
619 |
|
---|
620 | if ((do_eeprom_cmd(EE_READ_CMD << 24, 27) & 0xffe0000)
|
---|
621 | == 0xffe0000) {
|
---|
622 | ee_size = 0x100;
|
---|
623 | read_cmd = EE_READ_CMD << 24;
|
---|
624 | } else {
|
---|
625 | ee_size = 0x40;
|
---|
626 | read_cmd = EE_READ_CMD << 22;
|
---|
627 | }
|
---|
628 |
|
---|
629 | for (i = 0, sum = 0; i < ee_size; i++) {
|
---|
630 | unsigned short value = do_eeprom_cmd(read_cmd | (i << 16), 27);
|
---|
631 | if (i < (int)(sizeof(eeprom)/sizeof(eeprom[0])))
|
---|
632 | eeprom[i] = value;
|
---|
633 | sum += value;
|
---|
634 | }
|
---|
635 |
|
---|
636 | for (i=0;i<ETH_ALEN;i++) {
|
---|
637 | nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
|
---|
638 | }
|
---|
639 | printf ("Ethernet addr: %!\n", nic->node_addr);
|
---|
640 |
|
---|
641 | if (sum != 0xBABA)
|
---|
642 | printf("eepro100: Invalid EEPROM checksum %#hX, "
|
---|
643 | "check settings before activating this device!\n", sum);
|
---|
644 | outl(0, ioaddr + SCBPort);
|
---|
645 | udelay (10000);
|
---|
646 | whereami ("Got eeprom.");
|
---|
647 |
|
---|
648 | /* Base = 0, disable all interrupts */
|
---|
649 | outl(0, ioaddr + SCBPointer);
|
---|
650 | outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd);
|
---|
651 | wait_for_cmd_done(ioaddr + SCBCmd);
|
---|
652 | whereami ("set rx base addr.");
|
---|
653 |
|
---|
654 | outl(virt_to_bus(&lstats), ioaddr + SCBPointer);
|
---|
655 | outb(CU_STATSADDR, ioaddr + SCBCmd);
|
---|
656 | wait_for_cmd_done(ioaddr + SCBCmd);
|
---|
657 | whereami ("set stats addr.");
|
---|
658 |
|
---|
659 | /* INIT RX stuff. */
|
---|
660 | for (i = 0; i < RXFD_COUNT; i++) {
|
---|
661 | rxfds[i].status = 0x0000;
|
---|
662 | rxfds[i].command = 0x0000;
|
---|
663 | rxfds[i].rx_buf_addr = 0xFFFFFFFF;
|
---|
664 | rxfds[i].count = 0;
|
---|
665 | rxfds[i].size = 1528;
|
---|
666 | rxfds[i].link = virt_to_bus(&rxfds[i+1]);
|
---|
667 | }
|
---|
668 |
|
---|
669 | rxfds[RXFD_COUNT-1].status = 0x0000;
|
---|
670 | rxfds[RXFD_COUNT-1].command = 0xC000;
|
---|
671 | rxfds[RXFD_COUNT-1].link = virt_to_bus(&rxfds[0]);
|
---|
672 |
|
---|
673 | outl(virt_to_bus(&rxfds[0]), ioaddr + SCBPointer);
|
---|
674 | outb(RX_START, ioaddr + SCBCmd);
|
---|
675 | wait_for_cmd_done(ioaddr + SCBCmd);
|
---|
676 |
|
---|
677 | whereami ("started RX process.");
|
---|
678 |
|
---|
679 | /* INIT TX stuff. */
|
---|
680 |
|
---|
681 | /* Base = 0 */
|
---|
682 | outl(0, ioaddr + SCBPointer);
|
---|
683 | outb(CU_CMD_BASE, ioaddr + SCBCmd);
|
---|
684 | wait_for_cmd_done(ioaddr + SCBCmd);
|
---|
685 |
|
---|
686 | whereami ("set TX base addr.");
|
---|
687 |
|
---|
688 | txfd.command = (CmdIASetup);
|
---|
689 | txfd.status = 0x0000;
|
---|
690 | txfd.link = virt_to_bus (&confcmd);
|
---|
691 |
|
---|
692 | {
|
---|
693 | char *t = (char *)&txfd.tx_desc_addr;
|
---|
694 |
|
---|
695 | for (i=0;i<ETH_ALEN;i++)
|
---|
696 | t[i] = nic->node_addr[i];
|
---|
697 | }
|
---|
698 |
|
---|
699 | #ifdef DEBUG
|
---|
700 | printf ("Setup_eaddr:\n");
|
---|
701 | hd (&txfd, 0x20);
|
---|
702 | #endif
|
---|
703 | /* options = 0x40; */ /* 10mbps half duplex... */
|
---|
704 | options = 0x00; /* Autosense */
|
---|
705 |
|
---|
706 | #ifdef PROMISC
|
---|
707 | rx_mode = 3;
|
---|
708 | #elif ALLMULTI
|
---|
709 | rx_mode = 1;
|
---|
710 | #else
|
---|
711 | rx_mode = 0;
|
---|
712 | #endif
|
---|
713 |
|
---|
714 | if ( ((eeprom[6]>>8) & 0x3f) == DP83840
|
---|
715 | || ((eeprom[6]>>8) & 0x3f) == DP83840A) {
|
---|
716 | int mdi_reg23 = mdio_read(eeprom[6] & 0x1f, 23) | 0x0422;
|
---|
717 | if (congenb)
|
---|
718 | mdi_reg23 |= 0x0100;
|
---|
719 | printf(" DP83840 specific setup, setting register 23 to %hX.\n",
|
---|
720 | mdi_reg23);
|
---|
721 | mdio_write(eeprom[6] & 0x1f, 23, mdi_reg23);
|
---|
722 | }
|
---|
723 | whereami ("Done DP8340 special setup.");
|
---|
724 | if (options != 0) {
|
---|
725 | mdio_write(eeprom[6] & 0x1f, 0,
|
---|
726 | ((options & 0x20) ? 0x2000 : 0) | /* 100mbps? */
|
---|
727 | ((options & 0x10) ? 0x0100 : 0)); /* Full duplex? */
|
---|
728 | whereami ("set mdio_register.");
|
---|
729 | }
|
---|
730 |
|
---|
731 | confcmd.command = CmdSuspend | CmdConfigure;
|
---|
732 | confcmd.status = 0x0000;
|
---|
733 | confcmd.link = virt_to_bus (&txfd);
|
---|
734 | confcmd.data[1] = (txfifo << 4) | rxfifo;
|
---|
735 | confcmd.data[4] = rxdmacount;
|
---|
736 | confcmd.data[5] = txdmacount + 0x80;
|
---|
737 | confcmd.data[15] = (rx_mode & 2) ? 0x49: 0x48;
|
---|
738 | confcmd.data[19] = (options & 0x10) ? 0xC0 : 0x80;
|
---|
739 | confcmd.data[21] = (rx_mode & 1) ? 0x0D: 0x05;
|
---|
740 |
|
---|
741 | outl(virt_to_bus(&txfd), ioaddr + SCBPointer);
|
---|
742 | outb(CU_START, ioaddr + SCBCmd);
|
---|
743 | wait_for_cmd_done(ioaddr + SCBCmd);
|
---|
744 |
|
---|
745 | whereami ("started TX thingy (config, iasetup).");
|
---|
746 |
|
---|
747 | load_timer2(10*TICKS_PER_MS);
|
---|
748 | while (!txfd.status && timer2_running())
|
---|
749 | /* Wait */;
|
---|
750 |
|
---|
751 | /* Read the status register once to disgard stale data */
|
---|
752 | mdio_read(eeprom[6] & 0x1f, 1);
|
---|
753 | /* Check to see if the network cable is plugged in.
|
---|
754 | * This allows for faster failure if there is nothing
|
---|
755 | * we can do.
|
---|
756 | */
|
---|
757 | if (!(mdio_read(eeprom[6] & 0x1f, 1) & (1 << 2))) {
|
---|
758 | printf("Valid link not established\n");
|
---|
759 | eepro100_disable(dev);
|
---|
760 | return 0;
|
---|
761 | }
|
---|
762 |
|
---|
763 | dev->disable = eepro100_disable;
|
---|
764 | nic->poll = eepro100_poll;
|
---|
765 | nic->transmit = eepro100_transmit;
|
---|
766 | nic->irq = eepro100_irq;
|
---|
767 | return 1;
|
---|
768 | }
|
---|
769 |
|
---|
770 | /*********************************************************************/
|
---|
771 |
|
---|
772 | #ifdef DEBUG
|
---|
773 |
|
---|
774 | /* Hexdump a number of bytes from memory... */
|
---|
775 | void hd (void *where, int n)
|
---|
776 | {
|
---|
777 | int i;
|
---|
778 |
|
---|
779 | while (n > 0) {
|
---|
780 | printf ("%X ", where);
|
---|
781 | for (i=0;i < ( (n>16)?16:n);i++)
|
---|
782 | printf (" %hhX", ((char *)where)[i]);
|
---|
783 | printf ("\n");
|
---|
784 | n -= 16;
|
---|
785 | where += 16;
|
---|
786 | }
|
---|
787 | }
|
---|
788 | #endif
|
---|
789 |
|
---|
790 | static struct pci_id eepro100_nics[] = {
|
---|
791 | PCI_ROM(0x8086, 0x1029, "id1029", "Intel EtherExpressPro100 ID1029"),
|
---|
792 | PCI_ROM(0x8086, 0x1030, "id1030", "Intel EtherExpressPro100 ID1030"),
|
---|
793 | PCI_ROM(0x8086, 0x1031, "82801cam", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
|
---|
794 | PCI_ROM(0x8086, 0x1032, "eepro100-1032", "Intel PRO/100 VE Network Connection"),
|
---|
795 | PCI_ROM(0x8086, 0x1033, "eepro100-1033", "Intel PRO/100 VM Network Connection"),
|
---|
796 | PCI_ROM(0x8086, 0x1034, "eepro100-1034", "Intel PRO/100 VM Network Connection"),
|
---|
797 | PCI_ROM(0x8086, 0x1035, "eepro100-1035", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
|
---|
798 | PCI_ROM(0x8086, 0x1036, "eepro100-1036", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
|
---|
799 | PCI_ROM(0x8086, 0x1037, "eepro100-1037", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
|
---|
800 | PCI_ROM(0x8086, 0x1038, "id1038", "Intel PRO/100 VM Network Connection"),
|
---|
801 | PCI_ROM(0x8086, 0x1039, "82562et", "Intel PRO100 VE 82562ET"),
|
---|
802 | PCI_ROM(0x8086, 0x103a, "id103a", "Intel Corporation 82559 InBusiness 10/100"),
|
---|
803 | PCI_ROM(0x8086, 0x103b, "82562etb", "Intel PRO100 VE 82562ETB"),
|
---|
804 | PCI_ROM(0x8086, 0x103c, "eepro100-103c", "Intel PRO/100 VM Network Connection"),
|
---|
805 | PCI_ROM(0x8086, 0x103d, "eepro100-103d", "Intel PRO/100 VE Network Connection"),
|
---|
806 | PCI_ROM(0x8086, 0x103e, "eepro100-103e", "Intel PRO/100 VM Network Connection"),
|
---|
807 | PCI_ROM(0x8086, 0x1051, "prove", "Intel PRO/100 VE Network Connection"),
|
---|
808 | PCI_ROM(0x8086, 0x1059, "82551qm", "Intel PRO/100 M Mobile Connection"),
|
---|
809 | PCI_ROM(0x8086, 0x1209, "82559er", "Intel EtherExpressPro100 82559ER"),
|
---|
810 | PCI_ROM(0x8086, 0x1227, "82865", "Intel 82865 EtherExpress PRO/100A"),
|
---|
811 | PCI_ROM(0x8086, 0x1228, "82556", "Intel 82556 EtherExpress PRO/100 Smart"),
|
---|
812 | PCI_ROM(0x8086, 0x1229, "eepro100", "Intel EtherExpressPro100"),
|
---|
813 | PCI_ROM(0x8086, 0x2449, "82562em", "Intel EtherExpressPro100 82562EM"),
|
---|
814 | PCI_ROM(0x8086, 0x2459, "82562-1", "Intel 82562 based Fast Ethernet Connection"),
|
---|
815 | PCI_ROM(0x8086, 0x245d, "82562-2", "Intel 82562 based Fast Ethernet Connection"),
|
---|
816 | PCI_ROM(0x8086, 0x1050, "82562ez", "Intel 82562EZ Network Connection"),
|
---|
817 | PCI_ROM(0x8086, 0x1051, "eepro100-1051", "Intel 82801EB/ER (ICH5/ICH5R) Chipset Ethernet Controller"),
|
---|
818 | PCI_ROM(0x8086, 0x5200, "eepro100-5200", "Intel EtherExpress PRO/100 Intelligent Server"),
|
---|
819 | PCI_ROM(0x8086, 0x5201, "eepro100-5201", "Intel EtherExpress PRO/100 Intelligent Server"),
|
---|
820 | };
|
---|
821 |
|
---|
822 | /* Cards with device ids 0x1030 to 0x103F, 0x2449, 0x2459 or 0x245D might need
|
---|
823 | * a workaround for hardware bug on 10 mbit half duplex (see linux driver eepro100.c)
|
---|
824 | * 2003/03/17 gbaum */
|
---|
825 |
|
---|
826 |
|
---|
827 | static struct pci_driver eepro100_driver __pci_driver = {
|
---|
828 | .type = NIC_DRIVER,
|
---|
829 | .name = "EEPRO100",
|
---|
830 | .probe = eepro100_probe,
|
---|
831 | .ids = eepro100_nics,
|
---|
832 | .id_count = sizeof(eepro100_nics)/sizeof(eepro100_nics[0]),
|
---|
833 | .class = 0
|
---|
834 | };
|
---|