1 |
1626 |
jcastillo |
/* 3c515.c: A 3Com ISA EtherLink XL "Corkscrew" ethernet driver for linux. */
|
2 |
|
|
/*
|
3 |
|
|
Written 1997-1998 by Donald Becker.
|
4 |
|
|
|
5 |
|
|
This software may be used and distributed according to the terms
|
6 |
|
|
of the GNU Public License, incorporated herein by reference.
|
7 |
|
|
|
8 |
|
|
This driver is for the 3Com ISA EtherLink XL "Corkscrew" 3c515 ethercard.
|
9 |
|
|
|
10 |
|
|
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
|
11 |
|
|
Center of Excellence in Space Data and Information Sciences
|
12 |
|
|
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
|
13 |
|
|
*/
|
14 |
|
|
|
15 |
|
|
static char *version = "3c515.c:v0.99 4/7/98 becker@cesdis.gsfc.nasa.gov\n";
|
16 |
|
|
#define CORKSCREW 1
|
17 |
|
|
|
18 |
|
|
/* "Knobs" that adjust features and parameters. */
|
19 |
|
|
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
|
20 |
|
|
Setting to > 1512 effectively disables this feature. */
|
21 |
|
|
static const int rx_copybreak = 200;
|
22 |
|
|
/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
|
23 |
|
|
static const int mtu = 1500;
|
24 |
|
|
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
|
25 |
|
|
static int max_interrupt_work = 20;
|
26 |
|
|
|
27 |
|
|
/* Enable the automatic media selection code -- usually set. */
|
28 |
|
|
#define AUTOMEDIA 1
|
29 |
|
|
|
30 |
|
|
/* Allow the use of fragment bus master transfers instead of only
|
31 |
|
|
programmed-I/O for Vortex cards. Full-bus-master transfers are always
|
32 |
|
|
enabled by default on Boomerang cards. If VORTEX_BUS_MASTER is defined,
|
33 |
|
|
the feature may be turned on using 'options'. */
|
34 |
|
|
#define VORTEX_BUS_MASTER
|
35 |
|
|
|
36 |
|
|
/* A few values that may be tweaked. */
|
37 |
|
|
/* Keep the ring sizes a power of two for efficiency. */
|
38 |
|
|
#define TX_RING_SIZE 16
|
39 |
|
|
#define RX_RING_SIZE 16
|
40 |
|
|
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
|
41 |
|
|
|
42 |
|
|
#ifdef MODULE
|
43 |
|
|
#ifdef MODVERSIONS
|
44 |
|
|
#include <linux/modversions.h>
|
45 |
|
|
#endif
|
46 |
|
|
#include <linux/module.h>
|
47 |
|
|
#include <linux/version.h>
|
48 |
|
|
#else
|
49 |
|
|
#define MOD_INC_USE_COUNT
|
50 |
|
|
#define MOD_DEC_USE_COUNT
|
51 |
|
|
#endif
|
52 |
|
|
|
53 |
|
|
#include <linux/kernel.h>
|
54 |
|
|
#include <linux/sched.h>
|
55 |
|
|
#include <linux/string.h>
|
56 |
|
|
#include <linux/ptrace.h>
|
57 |
|
|
#include <linux/errno.h>
|
58 |
|
|
#include <linux/in.h>
|
59 |
|
|
#include <linux/ioport.h>
|
60 |
|
|
#include <linux/malloc.h>
|
61 |
|
|
#include <linux/interrupt.h>
|
62 |
|
|
#include <linux/pci.h>
|
63 |
|
|
#include <linux/bios32.h>
|
64 |
|
|
#include <linux/timer.h>
|
65 |
|
|
#include <asm/bitops.h>
|
66 |
|
|
#include <asm/io.h>
|
67 |
|
|
#include <asm/dma.h>
|
68 |
|
|
|
69 |
|
|
#include <linux/netdevice.h>
|
70 |
|
|
#include <linux/etherdevice.h>
|
71 |
|
|
#include <linux/skbuff.h>
|
72 |
|
|
#if (LINUX_VERSION_CODE >= 0x10344)
|
73 |
|
|
#define NEW_MULTICAST
|
74 |
|
|
#include <linux/delay.h>
|
75 |
|
|
#else
|
76 |
|
|
#define udelay(microsec) do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
|
77 |
|
|
#endif
|
78 |
|
|
|
79 |
|
|
/* Kernel version compatibility functions. */
|
80 |
|
|
#define RUN_AT(x) (jiffies + (x))
|
81 |
|
|
#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
|
82 |
|
|
|
83 |
|
|
#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
|
84 |
|
|
#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
|
85 |
|
|
#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
|
86 |
|
|
|
87 |
|
|
#if (LINUX_VERSION_CODE < 0x20123)
|
88 |
|
|
#define test_and_set_bit(val, addr) set_bit(val, addr)
|
89 |
|
|
#elif defined(MODULE)
|
90 |
|
|
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
|
91 |
|
|
MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver");
|
92 |
|
|
MODULE_PARM(debug, "i");
|
93 |
|
|
MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
|
94 |
|
|
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
|
95 |
|
|
MODULE_PARM(rx_copybreak, "i");
|
96 |
|
|
MODULE_PARM(max_interrupt_work, "i");
|
97 |
|
|
#endif
|
98 |
|
|
|
99 |
|
|
/* "Knobs" for adjusting internal parameters. */
|
100 |
|
|
/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
|
101 |
|
|
#define DRIVER_DEBUG 1
|
102 |
|
|
/* Some values here only for performance evaluation and path-coverage
|
103 |
|
|
debugging. */
|
104 |
|
|
static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0;
|
105 |
|
|
|
106 |
|
|
/* Number of times to check to see if the Tx FIFO has space, used in some
|
107 |
|
|
limited cases. */
|
108 |
|
|
#define WAIT_TX_AVAIL 200
|
109 |
|
|
|
110 |
|
|
/* Operational parameter that usually are not changed. */
|
111 |
|
|
#define TX_TIMEOUT 40 /* Time in jiffies before concluding Tx hung */
|
112 |
|
|
|
113 |
|
|
/* The size here is somewhat misleading: the Corkscrew also uses the ISA
|
114 |
|
|
aliased registers at <base>+0x400.
|
115 |
|
|
*/
|
116 |
|
|
#define CORKSCREW_TOTAL_SIZE 0x20
|
117 |
|
|
|
118 |
|
|
#ifdef HAVE_DEVLIST
|
119 |
|
|
struct netdev_entry tc515_drv =
|
120 |
|
|
{"3c515", tc515_probe, CORKSCREW_TOTAL_SIZE, NULL};
|
121 |
|
|
#endif
|
122 |
|
|
|
123 |
|
|
#ifdef DRIVER_DEBUG
|
124 |
|
|
int vortex_debug = DRIVER_DEBUG;
|
125 |
|
|
#else
|
126 |
|
|
int vortex_debug = 1;
|
127 |
|
|
#endif
|
128 |
|
|
|
129 |
|
|
#define CORKSCREW_ID 10
|
130 |
|
|
|
131 |
|
|
/*
|
132 |
|
|
Theory of Operation
|
133 |
|
|
|
134 |
|
|
I. Board Compatibility
|
135 |
|
|
|
136 |
|
|
This device driver is designed for the 3Com 3c515 ISA Fast EtherLink XL,
|
137 |
|
|
3Com's ISA bus adapter for Fast Ethernet. Due to the unique I/O port layout,
|
138 |
|
|
it's not practical to integrate this driver with the other EtherLink drivers.
|
139 |
|
|
|
140 |
|
|
II. Board-specific settings
|
141 |
|
|
|
142 |
|
|
The Corkscrew has an EEPROM for configuration, but no special settings are
|
143 |
|
|
needed for Linux.
|
144 |
|
|
|
145 |
|
|
III. Driver operation
|
146 |
|
|
|
147 |
|
|
The 3c515 series use an interface that's very similar to the 3c900 "Boomerang"
|
148 |
|
|
PCI cards, with the bus master interface extensively modified to work with
|
149 |
|
|
the ISA bus.
|
150 |
|
|
|
151 |
|
|
The card is capable of full-bus-master transfers with separate
|
152 |
|
|
lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
|
153 |
|
|
DEC Tulip and Intel Speedo3.
|
154 |
|
|
|
155 |
|
|
This driver uses a "RX_COPYBREAK" scheme rather than a fixed intermediate
|
156 |
|
|
receive buffer. This scheme allocates full-sized skbuffs as receive
|
157 |
|
|
buffers. The value RX_COPYBREAK is used as the copying breakpoint: it is
|
158 |
|
|
chosen to trade-off the memory wasted by passing the full-sized skbuff to
|
159 |
|
|
the queue layer for all frames vs. the copying cost of copying a frame to a
|
160 |
|
|
correctly-sized skbuff.
|
161 |
|
|
|
162 |
|
|
|
163 |
|
|
IIIC. Synchronization
|
164 |
|
|
The driver runs as two independent, single-threaded flows of control. One
|
165 |
|
|
is the send-packet routine, which enforces single-threaded use by the
|
166 |
|
|
dev->tbusy flag. The other thread is the interrupt handler, which is single
|
167 |
|
|
threaded by the hardware and other software.
|
168 |
|
|
|
169 |
|
|
IV. Notes
|
170 |
|
|
|
171 |
|
|
Thanks to Terry Murphy of 3Com for providing documentation and a development
|
172 |
|
|
board.
|
173 |
|
|
|
174 |
|
|
The names "Vortex", "Boomerang" and "Corkscrew" are the internal 3Com
|
175 |
|
|
project names. I use these names to eliminate confusion -- 3Com product
|
176 |
|
|
numbers and names are very similar and often confused.
|
177 |
|
|
|
178 |
|
|
The new chips support both ethernet (1.5K) and FDDI (4.5K) frame sizes!
|
179 |
|
|
This driver only supports ethernet frames because of the recent MTU limit
|
180 |
|
|
of 1.5K, but the changes to support 4.5K are minimal.
|
181 |
|
|
*/
|
182 |
|
|
|
183 |
|
|
/* Operational definitions.
|
184 |
|
|
These are not used by other compilation units and thus are not
|
185 |
|
|
exported in a ".h" file.
|
186 |
|
|
|
187 |
|
|
First the windows. There are eight register windows, with the command
|
188 |
|
|
and status registers available in each.
|
189 |
|
|
*/
|
190 |
|
|
#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
|
191 |
|
|
#define EL3_CMD 0x0e
|
192 |
|
|
#define EL3_STATUS 0x0e
|
193 |
|
|
|
194 |
|
|
/* The top five bits written to EL3_CMD are a command, the lower
|
195 |
|
|
11 bits are the parameter, if applicable.
|
196 |
|
|
Note that 11 parameters bits was fine for ethernet, but the new chips
|
197 |
|
|
can handle FDDI length frames (~4500 octets) and now parameters count
|
198 |
|
|
32-bit 'Dwords' rather than octets. */
|
199 |
|
|
|
200 |
|
|
enum vortex_cmd {
|
201 |
|
|
TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
|
202 |
|
|
RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11,
|
203 |
|
|
UpStall = 6<<11, UpUnstall = (6<<11)+1,
|
204 |
|
|
DownStall = (6<<11)+2, DownUnstall = (6<<11)+3,
|
205 |
|
|
RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
|
206 |
|
|
FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
|
207 |
|
|
SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
|
208 |
|
|
SetTxThreshold = 18<<11, SetTxStart = 19<<11,
|
209 |
|
|
StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11,
|
210 |
|
|
StatsDisable = 22<<11, StopCoax = 23<<11,};
|
211 |
|
|
|
212 |
|
|
/* The SetRxFilter command accepts the following classes: */
|
213 |
|
|
enum RxFilter {
|
214 |
|
|
RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
|
215 |
|
|
|
216 |
|
|
/* Bits in the general status register. */
|
217 |
|
|
enum vortex_status {
|
218 |
|
|
IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
|
219 |
|
|
TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
|
220 |
|
|
IntReq = 0x0040, StatsFull = 0x0080,
|
221 |
|
|
DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10,
|
222 |
|
|
DMAInProgress = 1<<11, /* DMA controller is still busy.*/
|
223 |
|
|
CmdInProgress = 1<<12, /* EL3_CMD is still busy.*/
|
224 |
|
|
};
|
225 |
|
|
|
226 |
|
|
/* Register window 1 offsets, the window used in normal operation.
|
227 |
|
|
On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */
|
228 |
|
|
enum Window1 {
|
229 |
|
|
TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
|
230 |
|
|
RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B,
|
231 |
|
|
TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */
|
232 |
|
|
};
|
233 |
|
|
enum Window0 {
|
234 |
|
|
Wn0IRQ = 0x08,
|
235 |
|
|
#if defined(CORKSCREW)
|
236 |
|
|
Wn0EepromCmd = 0x200A, /* Corkscrew EEPROM command register. */
|
237 |
|
|
Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */
|
238 |
|
|
#else
|
239 |
|
|
Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */
|
240 |
|
|
Wn0EepromData = 12, /* Window 0: EEPROM results register. */
|
241 |
|
|
#endif
|
242 |
|
|
};
|
243 |
|
|
enum Win0_EEPROM_bits {
|
244 |
|
|
EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
|
245 |
|
|
EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */
|
246 |
|
|
EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */
|
247 |
|
|
};
|
248 |
|
|
/* EEPROM locations. */
|
249 |
|
|
enum eeprom_offset {
|
250 |
|
|
PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3,
|
251 |
|
|
EtherLink3ID=7, };
|
252 |
|
|
|
253 |
|
|
enum Window3 { /* Window 3: MAC/config bits. */
|
254 |
|
|
Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
|
255 |
|
|
};
|
256 |
|
|
union wn3_config {
|
257 |
|
|
int i;
|
258 |
|
|
struct w3_config_fields {
|
259 |
|
|
unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
|
260 |
|
|
int pad8:8;
|
261 |
|
|
unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1;
|
262 |
|
|
int pad24:7;
|
263 |
|
|
} u;
|
264 |
|
|
};
|
265 |
|
|
|
266 |
|
|
enum Window4 {
|
267 |
|
|
Wn4_NetDiag = 6, Wn4_Media = 10, /* Window 4: Xcvr/media bits. */
|
268 |
|
|
};
|
269 |
|
|
enum Win4_Media_bits {
|
270 |
|
|
Media_SQE = 0x0008, /* Enable SQE error counting for AUI. */
|
271 |
|
|
Media_10TP = 0x00C0, /* Enable link beat and jabber for 10baseT. */
|
272 |
|
|
Media_Lnk = 0x0080, /* Enable just link beat for 100TX/100FX. */
|
273 |
|
|
Media_LnkBeat = 0x0800,
|
274 |
|
|
};
|
275 |
|
|
enum Window7 { /* Window 7: Bus Master control. */
|
276 |
|
|
Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
|
277 |
|
|
};
|
278 |
|
|
/* Boomerang-style bus master control registers. Note ISA aliases! */
|
279 |
|
|
enum MasterCtrl {
|
280 |
|
|
PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen = 0x40c,
|
281 |
|
|
TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
|
282 |
|
|
};
|
283 |
|
|
|
284 |
|
|
/* The Rx and Tx descriptor lists.
|
285 |
|
|
Caution Alpha hackers: these types are 32 bits! Note also the 8 byte
|
286 |
|
|
alignment contraint on tx_ring[] and rx_ring[]. */
|
287 |
|
|
struct boom_rx_desc {
|
288 |
|
|
u32 next;
|
289 |
|
|
s32 status;
|
290 |
|
|
u32 addr;
|
291 |
|
|
s32 length;
|
292 |
|
|
};
|
293 |
|
|
/* Values for the Rx status entry. */
|
294 |
|
|
enum rx_desc_status {
|
295 |
|
|
RxDComplete=0x00008000, RxDError=0x4000,
|
296 |
|
|
/* See boomerang_rx() for actual error bits */
|
297 |
|
|
};
|
298 |
|
|
|
299 |
|
|
struct boom_tx_desc {
|
300 |
|
|
u32 next;
|
301 |
|
|
s32 status;
|
302 |
|
|
u32 addr;
|
303 |
|
|
s32 length;
|
304 |
|
|
};
|
305 |
|
|
|
306 |
|
|
struct vortex_private {
|
307 |
|
|
char devname[8]; /* "ethN" string, also for kernel debug. */
|
308 |
|
|
const char *product_name;
|
309 |
|
|
struct device *next_module;
|
310 |
|
|
/* The Rx and Tx rings are here to keep them quad-word-aligned. */
|
311 |
|
|
struct boom_rx_desc rx_ring[RX_RING_SIZE];
|
312 |
|
|
struct boom_tx_desc tx_ring[TX_RING_SIZE];
|
313 |
|
|
/* The addresses of transmit- and receive-in-place skbuffs. */
|
314 |
|
|
struct sk_buff* rx_skbuff[RX_RING_SIZE];
|
315 |
|
|
struct sk_buff* tx_skbuff[TX_RING_SIZE];
|
316 |
|
|
unsigned int cur_rx, cur_tx; /* The next free ring entry */
|
317 |
|
|
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
|
318 |
|
|
struct enet_statistics stats;
|
319 |
|
|
struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */
|
320 |
|
|
struct timer_list timer; /* Media selection timer. */
|
321 |
|
|
int capabilities; /* Adapter capabilities word. */
|
322 |
|
|
int options; /* User-settable misc. driver options. */
|
323 |
|
|
int last_rx_packets; /* For media autoselection. */
|
324 |
|
|
unsigned int available_media:8, /* From Wn3_Options */
|
325 |
|
|
media_override:3, /* Passed-in media type. */
|
326 |
|
|
default_media:3, /* Read from the EEPROM. */
|
327 |
|
|
full_duplex:1, autoselect:1,
|
328 |
|
|
bus_master:1, /* Vortex can only do a fragment bus-m. */
|
329 |
|
|
full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang */
|
330 |
|
|
tx_full:1;
|
331 |
|
|
};
|
332 |
|
|
|
333 |
|
|
/* The action to take with a media selection timer tick.
|
334 |
|
|
Note that we deviate from the 3Com order by checking 10base2 before AUI.
|
335 |
|
|
*/
|
336 |
|
|
enum xcvr_types {
|
337 |
|
|
XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
|
338 |
|
|
XCVR_100baseFx, XCVR_MII=6, XCVR_Default=8,
|
339 |
|
|
};
|
340 |
|
|
|
341 |
|
|
static struct media_table {
|
342 |
|
|
char *name;
|
343 |
|
|
unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */
|
344 |
|
|
mask:8, /* The transceiver-present bit in Wn3_Config.*/
|
345 |
|
|
next:8; /* The media type to try next. */
|
346 |
|
|
short wait; /* Time before we check media status. */
|
347 |
|
|
} media_tbl[] = {
|
348 |
|
|
{ "10baseT", Media_10TP,0x08, XCVR_10base2, (14*HZ)/10},
|
349 |
|
|
{ "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10},
|
350 |
|
|
{ "undefined", 0, 0x80, XCVR_10baseT, 10000},
|
351 |
|
|
{ "10base2", 0, 0x10, XCVR_AUI, (1*HZ)/10},
|
352 |
|
|
{ "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10},
|
353 |
|
|
{ "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14*HZ)/10},
|
354 |
|
|
{ "MII", 0, 0x40, XCVR_10baseT, 3*HZ },
|
355 |
|
|
{ "undefined", 0, 0x01, XCVR_10baseT, 10000},
|
356 |
|
|
{ "Default", 0, 0xFF, XCVR_10baseT, 10000},
|
357 |
|
|
};
|
358 |
|
|
|
359 |
|
|
static int vortex_scan(struct device *dev);
|
360 |
|
|
static struct device *vortex_found_device(struct device *dev, int ioaddr,
|
361 |
|
|
int irq, int product_index,
|
362 |
|
|
int options);
|
363 |
|
|
static int vortex_probe1(struct device *dev);
|
364 |
|
|
static int vortex_open(struct device *dev);
|
365 |
|
|
static void vortex_timer(unsigned long arg);
|
366 |
|
|
static int vortex_start_xmit(struct sk_buff *skb, struct device *dev);
|
367 |
|
|
static int vortex_rx(struct device *dev);
|
368 |
|
|
static int boomerang_rx(struct device *dev);
|
369 |
|
|
static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs);
|
370 |
|
|
static int vortex_close(struct device *dev);
|
371 |
|
|
static void update_stats(int addr, struct device *dev);
|
372 |
|
|
static struct enet_statistics *vortex_get_stats(struct device *dev);
|
373 |
|
|
static void set_rx_mode(struct device *dev);
|
374 |
|
|
|
375 |
|
|
|
376 |
|
|
/* Unlike the other PCI cards the 59x cards don't need a large contiguous
|
377 |
|
|
memory region, so making the driver a loadable module is feasible.
|
378 |
|
|
|
379 |
|
|
Unfortunately maximizing the shared code between the integrated and
|
380 |
|
|
module version of the driver results in a complicated set of initialization
|
381 |
|
|
procedures.
|
382 |
|
|
init_module() -- modules / tc59x_init() -- built-in
|
383 |
|
|
The wrappers for vortex_scan()
|
384 |
|
|
vortex_scan() The common routine that scans for PCI and EISA cards
|
385 |
|
|
vortex_found_device() Allocate a device structure when we find a card.
|
386 |
|
|
Different versions exist for modules and built-in.
|
387 |
|
|
vortex_probe1() Fill in the device structure -- this is separated
|
388 |
|
|
so that the modules code can put it in dev->init.
|
389 |
|
|
*/
|
390 |
|
|
/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
|
391 |
|
|
/* Note: this is the only limit on the number of cards supported!! */
|
392 |
|
|
static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,};
|
393 |
|
|
|
394 |
|
|
#ifdef MODULE
|
395 |
|
|
static int debug = -1;
|
396 |
|
|
/* A list of all installed Vortex devices, for removing the driver module. */
|
397 |
|
|
static struct device *root_vortex_dev = NULL;
|
398 |
|
|
|
399 |
|
|
int
|
400 |
|
|
init_module(void)
|
401 |
|
|
{
|
402 |
|
|
int cards_found;
|
403 |
|
|
|
404 |
|
|
if (debug >= 0)
|
405 |
|
|
vortex_debug = debug;
|
406 |
|
|
if (vortex_debug)
|
407 |
|
|
printk(version);
|
408 |
|
|
|
409 |
|
|
root_vortex_dev = NULL;
|
410 |
|
|
cards_found = vortex_scan(0);
|
411 |
|
|
return cards_found ? 0 : -ENODEV;
|
412 |
|
|
}
|
413 |
|
|
|
414 |
|
|
#else
|
415 |
|
|
int tc515_probe(struct device *dev)
|
416 |
|
|
{
|
417 |
|
|
int cards_found = 0;
|
418 |
|
|
|
419 |
|
|
cards_found = vortex_scan(dev);
|
420 |
|
|
|
421 |
|
|
if (vortex_debug > 0 && cards_found)
|
422 |
|
|
printk(version);
|
423 |
|
|
|
424 |
|
|
return cards_found ? 0 : -ENODEV;
|
425 |
|
|
}
|
426 |
|
|
#endif /* not MODULE */
|
427 |
|
|
|
428 |
|
|
static int vortex_scan(struct device *dev)
|
429 |
|
|
{
|
430 |
|
|
int cards_found = 0;
|
431 |
|
|
static int ioaddr = 0x100;
|
432 |
|
|
|
433 |
|
|
/* Check all locations on the ISA bus -- evil! */
|
434 |
|
|
for (; ioaddr < 0x400; ioaddr += 0x20) {
|
435 |
|
|
int irq;
|
436 |
|
|
if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE))
|
437 |
|
|
continue;
|
438 |
|
|
/* Check the resource configuration for a matching ioaddr. */
|
439 |
|
|
if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0))
|
440 |
|
|
continue;
|
441 |
|
|
/* Verify by reading the device ID from the EEPROM. */
|
442 |
|
|
{
|
443 |
|
|
int timer;
|
444 |
|
|
outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
|
445 |
|
|
/* Pause for at least 162 us. for the read to take place. */
|
446 |
|
|
for (timer = 4; timer >= 0; timer--) {
|
447 |
|
|
udelay(162);
|
448 |
|
|
if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
|
449 |
|
|
break;
|
450 |
|
|
}
|
451 |
|
|
if (inw(ioaddr + Wn0EepromData) != 0x6d50)
|
452 |
|
|
continue;
|
453 |
|
|
}
|
454 |
|
|
printk("3c515 Resource configuraiton register %#4.4x, DCR %4.4x.\n",
|
455 |
|
|
inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
|
456 |
|
|
irq = inw(ioaddr + 0x2002) & 15;
|
457 |
|
|
vortex_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev && dev->mem_start
|
458 |
|
|
? dev->mem_start : options[cards_found]);
|
459 |
|
|
dev = 0;
|
460 |
|
|
cards_found++;
|
461 |
|
|
}
|
462 |
|
|
|
463 |
|
|
if (vortex_debug)
|
464 |
|
|
printk("%d 3c515 cards found.\n", cards_found);
|
465 |
|
|
return cards_found;
|
466 |
|
|
}
|
467 |
|
|
|
468 |
|
|
static struct device *vortex_found_device(struct device *dev, int ioaddr,
|
469 |
|
|
int irq, int product_index,
|
470 |
|
|
int options)
|
471 |
|
|
{
|
472 |
|
|
struct vortex_private *vp;
|
473 |
|
|
|
474 |
|
|
#ifdef MODULE
|
475 |
|
|
/* Allocate and fill new device structure. */
|
476 |
|
|
int dev_size = sizeof(struct device) +
|
477 |
|
|
sizeof(struct vortex_private) + 15; /* Pad for alignment */
|
478 |
|
|
|
479 |
|
|
dev = (struct device *) kmalloc(dev_size, GFP_KERNEL);
|
480 |
|
|
memset(dev, 0, dev_size);
|
481 |
|
|
/* Align the Rx and Tx ring entries. */
|
482 |
|
|
dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
|
483 |
|
|
vp = (struct vortex_private *)dev->priv;
|
484 |
|
|
dev->name = vp->devname; /* An empty string. */
|
485 |
|
|
dev->base_addr = ioaddr;
|
486 |
|
|
dev->irq = irq;
|
487 |
|
|
dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
|
488 |
|
|
dev->init = vortex_probe1;
|
489 |
|
|
vp->product_name = "3c515";
|
490 |
|
|
vp->options = options;
|
491 |
|
|
if (options >= 0) {
|
492 |
|
|
vp->media_override = ((options & 7) == 2) ? 0 : options & 7;
|
493 |
|
|
vp->full_duplex = (options & 8) ? 1 : 0;
|
494 |
|
|
vp->bus_master = (options & 16) ? 1 : 0;
|
495 |
|
|
} else {
|
496 |
|
|
vp->media_override = 7;
|
497 |
|
|
vp->full_duplex = 0;
|
498 |
|
|
vp->bus_master = 0;
|
499 |
|
|
}
|
500 |
|
|
ether_setup(dev);
|
501 |
|
|
vp->next_module = root_vortex_dev;
|
502 |
|
|
root_vortex_dev = dev;
|
503 |
|
|
if (register_netdev(dev) != 0)
|
504 |
|
|
return 0;
|
505 |
|
|
#else /* not a MODULE */
|
506 |
|
|
if (dev) {
|
507 |
|
|
/* Caution: quad-word alignment required for rings! */
|
508 |
|
|
dev->priv = kmalloc(sizeof (struct vortex_private), GFP_KERNEL);
|
509 |
|
|
memset(dev->priv, 0, sizeof (struct vortex_private));
|
510 |
|
|
}
|
511 |
|
|
dev = init_etherdev(dev, sizeof(struct vortex_private));
|
512 |
|
|
dev->base_addr = ioaddr;
|
513 |
|
|
dev->irq = irq;
|
514 |
|
|
dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
|
515 |
|
|
vp = (struct vortex_private *)dev->priv;
|
516 |
|
|
vp->product_name = "3c515";
|
517 |
|
|
vp->options = options;
|
518 |
|
|
if (options >= 0) {
|
519 |
|
|
vp->media_override = ((options & 7) == 2) ? 0 : options & 7;
|
520 |
|
|
vp->full_duplex = (options & 8) ? 1 : 0;
|
521 |
|
|
vp->bus_master = (options & 16) ? 1 : 0;
|
522 |
|
|
} else {
|
523 |
|
|
vp->media_override = 7;
|
524 |
|
|
vp->full_duplex = 0;
|
525 |
|
|
vp->bus_master = 0;
|
526 |
|
|
}
|
527 |
|
|
|
528 |
|
|
vortex_probe1(dev);
|
529 |
|
|
#endif /* MODULE */
|
530 |
|
|
return dev;
|
531 |
|
|
}
|
532 |
|
|
|
533 |
|
|
static int vortex_probe1(struct device *dev)
|
534 |
|
|
{
|
535 |
|
|
int ioaddr = dev->base_addr;
|
536 |
|
|
struct vortex_private *vp = (struct vortex_private *)dev->priv;
|
537 |
|
|
unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
|
538 |
|
|
int i;
|
539 |
|
|
|
540 |
|
|
printk("%s: 3Com %s at %#3x,", dev->name,
|
541 |
|
|
vp->product_name, ioaddr);
|
542 |
|
|
|
543 |
|
|
/* Read the station address from the EEPROM. */
|
544 |
|
|
EL3WINDOW(0);
|
545 |
|
|
for (i = 0; i < 0x18; i++) {
|
546 |
|
|
short *phys_addr = (short *)dev->dev_addr;
|
547 |
|
|
int timer;
|
548 |
|
|
outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
|
549 |
|
|
/* Pause for at least 162 us. for the read to take place. */
|
550 |
|
|
for (timer = 4; timer >= 0; timer--) {
|
551 |
|
|
udelay(162);
|
552 |
|
|
if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
|
553 |
|
|
break;
|
554 |
|
|
}
|
555 |
|
|
eeprom[i] = inw(ioaddr + Wn0EepromData);
|
556 |
|
|
checksum ^= eeprom[i];
|
557 |
|
|
if (i < 3)
|
558 |
|
|
phys_addr[i] = htons(eeprom[i]);
|
559 |
|
|
}
|
560 |
|
|
checksum = (checksum ^ (checksum >> 8)) & 0xff;
|
561 |
|
|
if (checksum != 0x00)
|
562 |
|
|
printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
|
563 |
|
|
for (i = 0; i < 6; i++)
|
564 |
|
|
printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
|
565 |
|
|
if (eeprom[16] == 0x11c7) { /* Corkscrew */
|
566 |
|
|
if (request_dma(dev->dma, "3c515")) {
|
567 |
|
|
printk(", DMA %d allocation failed", dev->dma);
|
568 |
|
|
dev->dma = 0;
|
569 |
|
|
} else
|
570 |
|
|
printk(", DMA %d", dev->dma);
|
571 |
|
|
}
|
572 |
|
|
printk(", IRQ %d\n", dev->irq);
|
573 |
|
|
/* Tell them about an invalid IRQ. */
|
574 |
|
|
if (vortex_debug && (dev->irq <= 0 || dev->irq > 15))
|
575 |
|
|
printk(" *** Warning: this IRQ is unlikely to work! ***\n");
|
576 |
|
|
|
577 |
|
|
{
|
578 |
|
|
char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
|
579 |
|
|
union wn3_config config;
|
580 |
|
|
EL3WINDOW(3);
|
581 |
|
|
vp->available_media = inw(ioaddr + Wn3_Options);
|
582 |
|
|
config.i = inl(ioaddr + Wn3_Config);
|
583 |
|
|
if (vortex_debug > 1)
|
584 |
|
|
printk(" Internal config register is %4.4x, transceivers %#x.\n",
|
585 |
|
|
config.i, inw(ioaddr + Wn3_Options));
|
586 |
|
|
printk(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
|
587 |
|
|
8 << config.u.ram_size,
|
588 |
|
|
config.u.ram_width ? "word" : "byte",
|
589 |
|
|
ram_split[config.u.ram_split],
|
590 |
|
|
config.u.autoselect ? "autoselect/" : "",
|
591 |
|
|
media_tbl[config.u.xcvr].name);
|
592 |
|
|
dev->if_port = config.u.xcvr;
|
593 |
|
|
vp->default_media = config.u.xcvr;
|
594 |
|
|
vp->autoselect = config.u.autoselect;
|
595 |
|
|
}
|
596 |
|
|
if (vp->media_override != 7) {
|
597 |
|
|
printk(" Media override to transceiver type %d (%s).\n",
|
598 |
|
|
vp->media_override, media_tbl[vp->media_override].name);
|
599 |
|
|
dev->if_port = vp->media_override;
|
600 |
|
|
}
|
601 |
|
|
|
602 |
|
|
vp->capabilities = eeprom[16];
|
603 |
|
|
vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
|
604 |
|
|
/* Rx is broken at 10mbps, so we always disable it. */
|
605 |
|
|
/* vp->full_bus_master_rx = 0;*/
|
606 |
|
|
vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
|
607 |
|
|
|
608 |
|
|
/* We do a request_region() to register /proc/ioports info. */
|
609 |
|
|
request_region(ioaddr, CORKSCREW_TOTAL_SIZE, vp->product_name);
|
610 |
|
|
|
611 |
|
|
/* The 3c59x-specific entries in the device structure. */
|
612 |
|
|
dev->open = &vortex_open;
|
613 |
|
|
dev->hard_start_xmit = &vortex_start_xmit;
|
614 |
|
|
dev->stop = &vortex_close;
|
615 |
|
|
dev->get_stats = &vortex_get_stats;
|
616 |
|
|
dev->set_multicast_list = &set_rx_mode;
|
617 |
|
|
|
618 |
|
|
return 0;
|
619 |
|
|
}
|
620 |
|
|
|
621 |
|
|
|
622 |
|
|
static int
|
623 |
|
|
vortex_open(struct device *dev)
|
624 |
|
|
{
|
625 |
|
|
int ioaddr = dev->base_addr;
|
626 |
|
|
struct vortex_private *vp = (struct vortex_private *)dev->priv;
|
627 |
|
|
union wn3_config config;
|
628 |
|
|
int i;
|
629 |
|
|
|
630 |
|
|
/* Before initializing select the active media port. */
|
631 |
|
|
EL3WINDOW(3);
|
632 |
|
|
if (vp->full_duplex)
|
633 |
|
|
outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */
|
634 |
|
|
config.i = inl(ioaddr + Wn3_Config);
|
635 |
|
|
|
636 |
|
|
if (vp->media_override != 7) {
|
637 |
|
|
if (vortex_debug > 1)
|
638 |
|
|
printk("%s: Media override to transceiver %d (%s).\n",
|
639 |
|
|
dev->name, vp->media_override,
|
640 |
|
|
media_tbl[vp->media_override].name);
|
641 |
|
|
dev->if_port = vp->media_override;
|
642 |
|
|
} else if (vp->autoselect) {
|
643 |
|
|
/* Find first available media type, starting with 100baseTx. */
|
644 |
|
|
dev->if_port = 4;
|
645 |
|
|
while (! (vp->available_media & media_tbl[dev->if_port].mask))
|
646 |
|
|
dev->if_port = media_tbl[dev->if_port].next;
|
647 |
|
|
|
648 |
|
|
if (vortex_debug > 1)
|
649 |
|
|
printk("%s: Initial media type %s.\n",
|
650 |
|
|
dev->name, media_tbl[dev->if_port].name);
|
651 |
|
|
|
652 |
|
|
init_timer(&vp->timer);
|
653 |
|
|
vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
|
654 |
|
|
vp->timer.data = (unsigned long)dev;
|
655 |
|
|
vp->timer.function = &vortex_timer; /* timer handler */
|
656 |
|
|
add_timer(&vp->timer);
|
657 |
|
|
} else
|
658 |
|
|
dev->if_port = vp->default_media;
|
659 |
|
|
|
660 |
|
|
config.u.xcvr = dev->if_port;
|
661 |
|
|
outl(config.i, ioaddr + Wn3_Config);
|
662 |
|
|
|
663 |
|
|
if (vortex_debug > 1) {
|
664 |
|
|
printk("%s: vortex_open() InternalConfig %8.8x.\n",
|
665 |
|
|
dev->name, config.i);
|
666 |
|
|
}
|
667 |
|
|
|
668 |
|
|
outw(TxReset, ioaddr + EL3_CMD);
|
669 |
|
|
for (i = 20; i >= 0 ; i--)
|
670 |
|
|
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
|
671 |
|
|
break;
|
672 |
|
|
|
673 |
|
|
outw(RxReset, ioaddr + EL3_CMD);
|
674 |
|
|
/* Wait a few ticks for the RxReset command to complete. */
|
675 |
|
|
for (i = 20; i >= 0 ; i--)
|
676 |
|
|
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
|
677 |
|
|
break;
|
678 |
|
|
|
679 |
|
|
outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
|
680 |
|
|
|
681 |
|
|
/* Use the now-standard shared IRQ implementation. */
|
682 |
|
|
if (vp->capabilities == 0x11c7) {
|
683 |
|
|
/* Corkscrew: Cannot share ISA resources. */
|
684 |
|
|
if (dev->irq == 0
|
685 |
|
|
|| dev->dma == 0
|
686 |
|
|
|| request_irq(dev->irq, &vortex_interrupt, 0,
|
687 |
|
|
vp->product_name, dev))
|
688 |
|
|
return -EAGAIN;
|
689 |
|
|
enable_dma(dev->dma);
|
690 |
|
|
set_dma_mode(dev->dma, DMA_MODE_CASCADE);
|
691 |
|
|
} else if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ,
|
692 |
|
|
vp->product_name, dev)) {
|
693 |
|
|
return -EAGAIN;
|
694 |
|
|
}
|
695 |
|
|
|
696 |
|
|
if (vortex_debug > 1) {
|
697 |
|
|
EL3WINDOW(4);
|
698 |
|
|
printk("%s: vortex_open() irq %d media status %4.4x.\n",
|
699 |
|
|
dev->name, dev->irq, inw(ioaddr + Wn4_Media));
|
700 |
|
|
}
|
701 |
|
|
|
702 |
|
|
/* Set the station address and mask in window 2 each time opened. */
|
703 |
|
|
EL3WINDOW(2);
|
704 |
|
|
for (i = 0; i < 6; i++)
|
705 |
|
|
outb(dev->dev_addr[i], ioaddr + i);
|
706 |
|
|
for (; i < 12; i+=2)
|
707 |
|
|
outw(0, ioaddr + i);
|
708 |
|
|
|
709 |
|
|
if (dev->if_port == 3)
|
710 |
|
|
/* Start the thinnet transceiver. We should really wait 50ms...*/
|
711 |
|
|
outw(StartCoax, ioaddr + EL3_CMD);
|
712 |
|
|
EL3WINDOW(4);
|
713 |
|
|
outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
|
714 |
|
|
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
|
715 |
|
|
|
716 |
|
|
/* Switch to the stats window, and clear all stats by reading. */
|
717 |
|
|
outw(StatsDisable, ioaddr + EL3_CMD);
|
718 |
|
|
EL3WINDOW(6);
|
719 |
|
|
for (i = 0; i < 10; i++)
|
720 |
|
|
inb(ioaddr + i);
|
721 |
|
|
inw(ioaddr + 10);
|
722 |
|
|
inw(ioaddr + 12);
|
723 |
|
|
/* New: On the Vortex we must also clear the BadSSD counter. */
|
724 |
|
|
EL3WINDOW(4);
|
725 |
|
|
inb(ioaddr + 12);
|
726 |
|
|
/* ..and on the Boomerang we enable the extra statistics bits. */
|
727 |
|
|
outw(0x0040, ioaddr + Wn4_NetDiag);
|
728 |
|
|
|
729 |
|
|
/* Switch to register set 7 for normal use. */
|
730 |
|
|
EL3WINDOW(7);
|
731 |
|
|
|
732 |
|
|
if (vp->full_bus_master_rx) { /* Boomerang bus master. */
|
733 |
|
|
vp->cur_rx = vp->dirty_rx = 0;
|
734 |
|
|
if (vortex_debug > 2)
|
735 |
|
|
printk("%s: Filling in the Rx ring.\n", dev->name);
|
736 |
|
|
for (i = 0; i < RX_RING_SIZE; i++) {
|
737 |
|
|
struct sk_buff *skb;
|
738 |
|
|
if (i < (RX_RING_SIZE - 1))
|
739 |
|
|
vp->rx_ring[i].next = virt_to_bus(&vp->rx_ring[i+1]);
|
740 |
|
|
else
|
741 |
|
|
vp->rx_ring[i].next = 0;
|
742 |
|
|
vp->rx_ring[i].status = 0; /* Clear complete bit. */
|
743 |
|
|
vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000;
|
744 |
|
|
skb = dev_alloc_skb(PKT_BUF_SZ);
|
745 |
|
|
vp->rx_skbuff[i] = skb;
|
746 |
|
|
if (skb == NULL)
|
747 |
|
|
break; /* Bad news! */
|
748 |
|
|
skb->dev = dev; /* Mark as being used by this device. */
|
749 |
|
|
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
|
750 |
|
|
vp->rx_ring[i].addr = virt_to_bus(skb->tail);
|
751 |
|
|
}
|
752 |
|
|
vp->rx_ring[i-1].next = virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */
|
753 |
|
|
outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
|
754 |
|
|
}
|
755 |
|
|
if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
|
756 |
|
|
vp->cur_tx = vp->dirty_tx = 0;
|
757 |
|
|
outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
|
758 |
|
|
/* Clear the Tx ring. */
|
759 |
|
|
for (i = 0; i < TX_RING_SIZE; i++)
|
760 |
|
|
vp->tx_skbuff[i] = 0;
|
761 |
|
|
outl(0, ioaddr + DownListPtr);
|
762 |
|
|
}
|
763 |
|
|
/* Set reciever mode: presumably accept b-case and phys addr only. */
|
764 |
|
|
set_rx_mode(dev);
|
765 |
|
|
outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
|
766 |
|
|
|
767 |
|
|
dev->tbusy = 0;
|
768 |
|
|
dev->interrupt = 0;
|
769 |
|
|
dev->start = 1;
|
770 |
|
|
|
771 |
|
|
outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
|
772 |
|
|
outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
|
773 |
|
|
/* Allow status bits to be seen. */
|
774 |
|
|
outw(SetStatusEnb | AdapterFailure|IntReq|StatsFull |
|
775 |
|
|
(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
|
776 |
|
|
(vp->full_bus_master_rx ? UpComplete : RxComplete) |
|
777 |
|
|
(vp->bus_master ? DMADone : 0),
|
778 |
|
|
ioaddr + EL3_CMD);
|
779 |
|
|
/* Ack all pending events, and set active indicator mask. */
|
780 |
|
|
outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
|
781 |
|
|
ioaddr + EL3_CMD);
|
782 |
|
|
outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
|
783 |
|
|
| (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
|
784 |
|
|
ioaddr + EL3_CMD);
|
785 |
|
|
|
786 |
|
|
MOD_INC_USE_COUNT;
|
787 |
|
|
|
788 |
|
|
return 0;
|
789 |
|
|
}
|
790 |
|
|
|
791 |
|
|
static void vortex_timer(unsigned long data)
|
792 |
|
|
{
|
793 |
|
|
#ifdef AUTOMEDIA
|
794 |
|
|
struct device *dev = (struct device *)data;
|
795 |
|
|
struct vortex_private *vp = (struct vortex_private *)dev->priv;
|
796 |
|
|
int ioaddr = dev->base_addr;
|
797 |
|
|
unsigned long flags;
|
798 |
|
|
int ok = 0;
|
799 |
|
|
|
800 |
|
|
if (vortex_debug > 1)
|
801 |
|
|
printk("%s: Media selection timer tick happened, %s.\n",
|
802 |
|
|
dev->name, media_tbl[dev->if_port].name);
|
803 |
|
|
|
804 |
|
|
save_flags(flags); cli(); {
|
805 |
|
|
int old_window = inw(ioaddr + EL3_CMD) >> 13;
|
806 |
|
|
int media_status;
|
807 |
|
|
EL3WINDOW(4);
|
808 |
|
|
media_status = inw(ioaddr + Wn4_Media);
|
809 |
|
|
switch (dev->if_port) {
|
810 |
|
|
case 0: case 4: case 5: /* 10baseT, 100baseTX, 100baseFX */
|
811 |
|
|
if (media_status & Media_LnkBeat) {
|
812 |
|
|
ok = 1;
|
813 |
|
|
if (vortex_debug > 1)
|
814 |
|
|
printk("%s: Media %s has link beat, %x.\n",
|
815 |
|
|
dev->name, media_tbl[dev->if_port].name, media_status);
|
816 |
|
|
} else if (vortex_debug > 1)
|
817 |
|
|
printk("%s: Media %s is has no link beat, %x.\n",
|
818 |
|
|
dev->name, media_tbl[dev->if_port].name, media_status);
|
819 |
|
|
|
820 |
|
|
break;
|
821 |
|
|
default: /* Other media types handled by Tx timeouts. */
|
822 |
|
|
if (vortex_debug > 1)
|
823 |
|
|
printk("%s: Media %s is has no indication, %x.\n",
|
824 |
|
|
dev->name, media_tbl[dev->if_port].name, media_status);
|
825 |
|
|
ok = 1;
|
826 |
|
|
}
|
827 |
|
|
if ( ! ok) {
|
828 |
|
|
union wn3_config config;
|
829 |
|
|
|
830 |
|
|
do {
|
831 |
|
|
dev->if_port = media_tbl[dev->if_port].next;
|
832 |
|
|
} while ( ! (vp->available_media & media_tbl[dev->if_port].mask));
|
833 |
|
|
if (dev->if_port == 8) { /* Go back to default. */
|
834 |
|
|
dev->if_port = vp->default_media;
|
835 |
|
|
if (vortex_debug > 1)
|
836 |
|
|
printk("%s: Media selection failing, using default %s port.\n",
|
837 |
|
|
dev->name, media_tbl[dev->if_port].name);
|
838 |
|
|
} else {
|
839 |
|
|
if (vortex_debug > 1)
|
840 |
|
|
printk("%s: Media selection failed, now trying %s port.\n",
|
841 |
|
|
dev->name, media_tbl[dev->if_port].name);
|
842 |
|
|
vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
|
843 |
|
|
add_timer(&vp->timer);
|
844 |
|
|
}
|
845 |
|
|
outw((media_status & ~(Media_10TP|Media_SQE)) |
|
846 |
|
|
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
|
847 |
|
|
|
848 |
|
|
EL3WINDOW(3);
|
849 |
|
|
config.i = inl(ioaddr + Wn3_Config);
|
850 |
|
|
config.u.xcvr = dev->if_port;
|
851 |
|
|
outl(config.i, ioaddr + Wn3_Config);
|
852 |
|
|
|
853 |
|
|
outw(dev->if_port == 3 ? StartCoax : StopCoax, ioaddr + EL3_CMD);
|
854 |
|
|
}
|
855 |
|
|
EL3WINDOW(old_window);
|
856 |
|
|
} restore_flags(flags);
|
857 |
|
|
if (vortex_debug > 1)
|
858 |
|
|
printk("%s: Media selection timer finished, %s.\n",
|
859 |
|
|
dev->name, media_tbl[dev->if_port].name);
|
860 |
|
|
|
861 |
|
|
#endif /* AUTOMEDIA*/
|
862 |
|
|
return;
|
863 |
|
|
}
|
864 |
|
|
|
865 |
|
|
static int
|
866 |
|
|
vortex_start_xmit(struct sk_buff *skb, struct device *dev)
|
867 |
|
|
{
|
868 |
|
|
struct vortex_private *vp = (struct vortex_private *)dev->priv;
|
869 |
|
|
int ioaddr = dev->base_addr;
|
870 |
|
|
|
871 |
|
|
if (dev->tbusy) {
|
872 |
|
|
int tickssofar = jiffies - dev->trans_start;
|
873 |
|
|
int i;
|
874 |
|
|
|
875 |
|
|
/* Min. wait before assuming a Tx failed == 400ms. */
|
876 |
|
|
|
877 |
|
|
if (tickssofar < 400*HZ/1000) /* We probably aren't empty. */
|
878 |
|
|
return 1;
|
879 |
|
|
printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
|
880 |
|
|
dev->name, inb(ioaddr + TxStatus),
|
881 |
|
|
inw(ioaddr + EL3_STATUS));
|
882 |
|
|
/* Slight code bloat to be user friendly. */
|
883 |
|
|
if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
|
884 |
|
|
printk("%s: Transmitter encountered 16 collisions -- network"
|
885 |
|
|
" network cable problem?\n", dev->name);
|
886 |
|
|
#ifndef final_version
|
887 |
|
|
printk(" Flags; bus-master %d, full %d; dirty %d current %d.\n",
|
888 |
|
|
vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx);
|
889 |
|
|
printk(" Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
|
890 |
|
|
&vp->tx_ring[0]);
|
891 |
|
|
for (i = 0; i < TX_RING_SIZE; i++) {
|
892 |
|
|
printk(" %d: %p length %8.8x status %8.8x\n", i,
|
893 |
|
|
&vp->tx_ring[i],
|
894 |
|
|
vp->tx_ring[i].length,
|
895 |
|
|
vp->tx_ring[i].status);
|
896 |
|
|
}
|
897 |
|
|
#endif
|
898 |
|
|
/* Issue TX_RESET and TX_START commands. */
|
899 |
|
|
outw(TxReset, ioaddr + EL3_CMD);
|
900 |
|
|
for (i = 20; i >= 0 ; i--)
|
901 |
|
|
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
|
902 |
|
|
break;
|
903 |
|
|
outw(TxEnable, ioaddr + EL3_CMD);
|
904 |
|
|
dev->trans_start = jiffies;
|
905 |
|
|
/* dev->tbusy = 0;*/
|
906 |
|
|
vp->stats.tx_errors++;
|
907 |
|
|
vp->stats.tx_dropped++;
|
908 |
|
|
return 0; /* Yes, silently *drop* the packet! */
|
909 |
|
|
}
|
910 |
|
|
|
911 |
|
|
/* Block a timer-based transmit from overlapping. This could better be
|
912 |
|
|
done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
|
913 |
|
|
If this ever occurs the queue layer is doing something evil! */
|
914 |
|
|
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
|
915 |
|
|
printk("%s: Transmitter access conflict.\n", dev->name);
|
916 |
|
|
return 1;
|
917 |
|
|
}
|
918 |
|
|
|
919 |
|
|
if (vp->full_bus_master_tx) { /* BOOMERANG bus-master */
|
920 |
|
|
/* Calculate the next Tx descriptor entry. */
|
921 |
|
|
int entry = vp->cur_tx % TX_RING_SIZE;
|
922 |
|
|
struct boom_tx_desc *prev_entry;
|
923 |
|
|
unsigned long flags, i;
|
924 |
|
|
|
925 |
|
|
if (vp->tx_full) /* No room to transmit with */
|
926 |
|
|
return 1;
|
927 |
|
|
if (vp->cur_tx != 0)
|
928 |
|
|
prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
|
929 |
|
|
else
|
930 |
|
|
prev_entry = NULL;
|
931 |
|
|
if (vortex_debug > 3)
|
932 |
|
|
printk("%s: Trying to send a packet, Tx index %d.\n",
|
933 |
|
|
dev->name, vp->cur_tx);
|
934 |
|
|
/* vp->tx_full = 1; */
|
935 |
|
|
vp->tx_skbuff[entry] = skb;
|
936 |
|
|
vp->tx_ring[entry].next = 0;
|
937 |
|
|
vp->tx_ring[entry].addr = virt_to_bus(skb->data);
|
938 |
|
|
vp->tx_ring[entry].length = skb->len | 0x80000000;
|
939 |
|
|
vp->tx_ring[entry].status = skb->len | 0x80000000;
|
940 |
|
|
|
941 |
|
|
save_flags(flags);
|
942 |
|
|
cli();
|
943 |
|
|
outw(DownStall, ioaddr + EL3_CMD);
|
944 |
|
|
/* Wait for the stall to complete. */
|
945 |
|
|
for (i = 20; i >= 0 ; i--)
|
946 |
|
|
if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
|
947 |
|
|
break;
|
948 |
|
|
if (prev_entry)
|
949 |
|
|
prev_entry->next = virt_to_bus(&vp->tx_ring[entry]);
|
950 |
|
|
if (inl(ioaddr + DownListPtr) == 0) {
|
951 |
|
|
outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);
|
952 |
|
|
queued_packet++;
|
953 |
|
|
}
|
954 |
|
|
outw(DownUnstall, ioaddr + EL3_CMD);
|
955 |
|
|
restore_flags(flags);
|
956 |
|
|
|
957 |
|
|
vp->cur_tx++;
|
958 |
|
|
if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
|
959 |
|
|
vp->tx_full = 1;
|
960 |
|
|
else { /* Clear previous interrupt enable. */
|
961 |
|
|
if (prev_entry)
|
962 |
|
|
prev_entry->status &= ~0x80000000;
|
963 |
|
|
dev->tbusy = 0;
|
964 |
|
|
}
|
965 |
|
|
dev->trans_start = jiffies;
|
966 |
|
|
return 0;
|
967 |
|
|
}
|
968 |
|
|
/* Put out the doubleword header... */
|
969 |
|
|
outl(skb->len, ioaddr + TX_FIFO);
|
970 |
|
|
#ifdef VORTEX_BUS_MASTER
|
971 |
|
|
if (vp->bus_master) {
|
972 |
|
|
/* Set the bus-master controller to transfer the packet. */
|
973 |
|
|
outl((int)(skb->data), ioaddr + Wn7_MasterAddr);
|
974 |
|
|
outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
|
975 |
|
|
vp->tx_skb = skb;
|
976 |
|
|
outw(StartDMADown, ioaddr + EL3_CMD);
|
977 |
|
|
/* dev->tbusy will be cleared at the DMADone interrupt. */
|
978 |
|
|
} else {
|
979 |
|
|
/* ... and the packet rounded to a doubleword. */
|
980 |
|
|
outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
|
981 |
|
|
dev_kfree_skb (skb, FREE_WRITE);
|
982 |
|
|
if (inw(ioaddr + TxFree) > 1536) {
|
983 |
|
|
dev->tbusy = 0;
|
984 |
|
|
} else
|
985 |
|
|
/* Interrupt us when the FIFO has room for max-sized packet. */
|
986 |
|
|
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
|
987 |
|
|
}
|
988 |
|
|
#else
|
989 |
|
|
/* ... and the packet rounded to a doubleword. */
|
990 |
|
|
outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
|
991 |
|
|
dev_kfree_skb (skb, FREE_WRITE);
|
992 |
|
|
if (inw(ioaddr + TxFree) > 1536) {
|
993 |
|
|
dev->tbusy = 0;
|
994 |
|
|
} else
|
995 |
|
|
/* Interrupt us when the FIFO has room for max-sized packet. */
|
996 |
|
|
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
|
997 |
|
|
#endif /* bus master */
|
998 |
|
|
|
999 |
|
|
dev->trans_start = jiffies;
|
1000 |
|
|
|
1001 |
|
|
/* Clear the Tx status stack. */
|
1002 |
|
|
{
|
1003 |
|
|
short tx_status;
|
1004 |
|
|
int i = 4;
|
1005 |
|
|
|
1006 |
|
|
while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) {
|
1007 |
|
|
if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */
|
1008 |
|
|
if (vortex_debug > 2)
|
1009 |
|
|
printk("%s: Tx error, status %2.2x.\n",
|
1010 |
|
|
dev->name, tx_status);
|
1011 |
|
|
if (tx_status & 0x04) vp->stats.tx_fifo_errors++;
|
1012 |
|
|
if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
|
1013 |
|
|
if (tx_status & 0x30) {
|
1014 |
|
|
int j;
|
1015 |
|
|
outw(TxReset, ioaddr + EL3_CMD);
|
1016 |
|
|
for (j = 20; j >= 0 ; j--)
|
1017 |
|
|
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
|
1018 |
|
|
break;
|
1019 |
|
|
}
|
1020 |
|
|
outw(TxEnable, ioaddr + EL3_CMD);
|
1021 |
|
|
}
|
1022 |
|
|
outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
|
1023 |
|
|
}
|
1024 |
|
|
}
|
1025 |
|
|
return 0;
|
1026 |
|
|
}
|
1027 |
|
|
|
1028 |
|
|
/* The interrupt handler does all of the Rx thread work and cleans up
|
1029 |
|
|
after the Tx thread. */
|
1030 |
|
|
static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
|
1031 |
|
|
{
|
1032 |
|
|
/* Use the now-standard shared IRQ implementation. */
|
1033 |
|
|
struct device *dev = dev_id;
|
1034 |
|
|
struct vortex_private *lp;
|
1035 |
|
|
int ioaddr, status;
|
1036 |
|
|
int latency;
|
1037 |
|
|
int i = max_interrupt_work;
|
1038 |
|
|
|
1039 |
|
|
if (test_and_set_bit(0, (void*)&dev->interrupt)) {
|
1040 |
|
|
printk("%s: Re-entering the interrupt handler.\n", dev->name);
|
1041 |
|
|
return;
|
1042 |
|
|
}
|
1043 |
|
|
|
1044 |
|
|
ioaddr = dev->base_addr;
|
1045 |
|
|
latency = inb(ioaddr + Timer);
|
1046 |
|
|
lp = (struct vortex_private *)dev->priv;
|
1047 |
|
|
|
1048 |
|
|
status = inw(ioaddr + EL3_STATUS);
|
1049 |
|
|
|
1050 |
|
|
if (vortex_debug > 4)
|
1051 |
|
|
printk("%s: interrupt, status %4.4x, timer %d.\n", dev->name,
|
1052 |
|
|
status, latency);
|
1053 |
|
|
if ((status & 0xE000) != 0xE000) {
|
1054 |
|
|
static int donedidthis=0;
|
1055 |
|
|
/* Some interrupt controllers store a bogus interrupt from boot-time.
|
1056 |
|
|
Ignore a single early interrupt, but don't hang the machine for
|
1057 |
|
|
other interrupt problems. */
|
1058 |
|
|
if (donedidthis++ > 100) {
|
1059 |
|
|
printk("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
|
1060 |
|
|
dev->name, status, dev->start);
|
1061 |
|
|
FREE_IRQ(dev->irq, dev);
|
1062 |
|
|
}
|
1063 |
|
|
}
|
1064 |
|
|
|
1065 |
|
|
do {
|
1066 |
|
|
if (vortex_debug > 5)
|
1067 |
|
|
printk("%s: In interrupt loop, status %4.4x.\n",
|
1068 |
|
|
dev->name, status);
|
1069 |
|
|
if (status & RxComplete)
|
1070 |
|
|
vortex_rx(dev);
|
1071 |
|
|
|
1072 |
|
|
if (status & TxAvailable) {
|
1073 |
|
|
if (vortex_debug > 5)
|
1074 |
|
|
printk(" TX room bit was handled.\n");
|
1075 |
|
|
/* There's room in the FIFO for a full-sized packet. */
|
1076 |
|
|
outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
|
1077 |
|
|
dev->tbusy = 0;
|
1078 |
|
|
mark_bh(NET_BH);
|
1079 |
|
|
}
|
1080 |
|
|
if (status & DownComplete) {
|
1081 |
|
|
unsigned int dirty_tx = lp->dirty_tx;
|
1082 |
|
|
|
1083 |
|
|
while (lp->cur_tx - dirty_tx > 0) {
|
1084 |
|
|
int entry = dirty_tx % TX_RING_SIZE;
|
1085 |
|
|
if (inl(ioaddr + DownListPtr) ==
|
1086 |
|
|
virt_to_bus(&lp->tx_ring[entry]))
|
1087 |
|
|
break; /* It still hasn't been processed. */
|
1088 |
|
|
if (lp->tx_skbuff[entry]) {
|
1089 |
|
|
dev_kfree_skb(lp->tx_skbuff[entry], FREE_WRITE);
|
1090 |
|
|
lp->tx_skbuff[entry] = 0;
|
1091 |
|
|
}
|
1092 |
|
|
dirty_tx++;
|
1093 |
|
|
}
|
1094 |
|
|
lp->dirty_tx = dirty_tx;
|
1095 |
|
|
outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
|
1096 |
|
|
if (lp->tx_full && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
|
1097 |
|
|
lp->tx_full= 0;
|
1098 |
|
|
dev->tbusy = 0;
|
1099 |
|
|
mark_bh(NET_BH);
|
1100 |
|
|
}
|
1101 |
|
|
}
|
1102 |
|
|
#ifdef VORTEX_BUS_MASTER
|
1103 |
|
|
if (status & DMADone) {
|
1104 |
|
|
outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
|
1105 |
|
|
dev->tbusy = 0;
|
1106 |
|
|
dev_kfree_skb (lp->tx_skb, FREE_WRITE); /* Release the transfered buffer */
|
1107 |
|
|
mark_bh(NET_BH);
|
1108 |
|
|
}
|
1109 |
|
|
#endif
|
1110 |
|
|
if (status & UpComplete) {
|
1111 |
|
|
boomerang_rx(dev);
|
1112 |
|
|
outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
|
1113 |
|
|
}
|
1114 |
|
|
if (status & (AdapterFailure | RxEarly | StatsFull)) {
|
1115 |
|
|
/* Handle all uncommon interrupts at once. */
|
1116 |
|
|
if (status & RxEarly) { /* Rx early is unused. */
|
1117 |
|
|
vortex_rx(dev);
|
1118 |
|
|
outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
|
1119 |
|
|
}
|
1120 |
|
|
if (status & StatsFull) { /* Empty statistics. */
|
1121 |
|
|
static int DoneDidThat = 0;
|
1122 |
|
|
if (vortex_debug > 4)
|
1123 |
|
|
printk("%s: Updating stats.\n", dev->name);
|
1124 |
|
|
update_stats(ioaddr, dev);
|
1125 |
|
|
/* DEBUG HACK: Disable statistics as an interrupt source. */
|
1126 |
|
|
/* This occurs when we have the wrong media type! */
|
1127 |
|
|
if (DoneDidThat == 0 &&
|
1128 |
|
|
inw(ioaddr + EL3_STATUS) & StatsFull) {
|
1129 |
|
|
int win, reg;
|
1130 |
|
|
printk("%s: Updating stats failed, disabling stats as an"
|
1131 |
|
|
" interrupt source.\n", dev->name);
|
1132 |
|
|
for (win = 0; win < 8; win++) {
|
1133 |
|
|
EL3WINDOW(win);
|
1134 |
|
|
printk("\n Vortex window %d:", win);
|
1135 |
|
|
for (reg = 0; reg < 16; reg++)
|
1136 |
|
|
printk(" %2.2x", inb(ioaddr+reg));
|
1137 |
|
|
}
|
1138 |
|
|
EL3WINDOW(7);
|
1139 |
|
|
outw(SetIntrEnb | TxAvailable | RxComplete | AdapterFailure
|
1140 |
|
|
| UpComplete | DownComplete | TxComplete,
|
1141 |
|
|
ioaddr + EL3_CMD);
|
1142 |
|
|
DoneDidThat++;
|
1143 |
|
|
}
|
1144 |
|
|
}
|
1145 |
|
|
if (status & AdapterFailure) {
|
1146 |
|
|
/* Adapter failure requires Rx reset and reinit. */
|
1147 |
|
|
outw(RxReset, ioaddr + EL3_CMD);
|
1148 |
|
|
/* Set the Rx filter to the current state. */
|
1149 |
|
|
set_rx_mode(dev);
|
1150 |
|
|
outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
|
1151 |
|
|
outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
|
1152 |
|
|
}
|
1153 |
|
|
}
|
1154 |
|
|
|
1155 |
|
|
if (--i < 0) {
|
1156 |
|
|
printk("%s: Too much work in interrupt, status %4.4x. "
|
1157 |
|
|
"Disabling functions (%4.4x).\n",
|
1158 |
|
|
dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
|
1159 |
|
|
/* Disable all pending interrupts. */
|
1160 |
|
|
outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
|
1161 |
|
|
outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
|
1162 |
|
|
break;
|
1163 |
|
|
}
|
1164 |
|
|
/* Acknowledge the IRQ. */
|
1165 |
|
|
outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
|
1166 |
|
|
|
1167 |
|
|
} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
|
1168 |
|
|
|
1169 |
|
|
if (vortex_debug > 4)
|
1170 |
|
|
printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status);
|
1171 |
|
|
|
1172 |
|
|
dev->interrupt = 0;
|
1173 |
|
|
return;
|
1174 |
|
|
}
|
1175 |
|
|
|
1176 |
|
|
static int
|
1177 |
|
|
vortex_rx(struct device *dev)
|
1178 |
|
|
{
|
1179 |
|
|
struct vortex_private *vp = (struct vortex_private *)dev->priv;
|
1180 |
|
|
int ioaddr = dev->base_addr;
|
1181 |
|
|
int i;
|
1182 |
|
|
short rx_status;
|
1183 |
|
|
|
1184 |
|
|
if (vortex_debug > 5)
|
1185 |
|
|
printk(" In rx_packet(), status %4.4x, rx_status %4.4x.\n",
|
1186 |
|
|
inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
|
1187 |
|
|
while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
|
1188 |
|
|
if (rx_status & 0x4000) { /* Error, update stats. */
|
1189 |
|
|
unsigned char rx_error = inb(ioaddr + RxErrors);
|
1190 |
|
|
if (vortex_debug > 2)
|
1191 |
|
|
printk(" Rx error: status %2.2x.\n", rx_error);
|
1192 |
|
|
vp->stats.rx_errors++;
|
1193 |
|
|
if (rx_error & 0x01) vp->stats.rx_over_errors++;
|
1194 |
|
|
if (rx_error & 0x02) vp->stats.rx_length_errors++;
|
1195 |
|
|
if (rx_error & 0x04) vp->stats.rx_frame_errors++;
|
1196 |
|
|
if (rx_error & 0x08) vp->stats.rx_crc_errors++;
|
1197 |
|
|
if (rx_error & 0x10) vp->stats.rx_length_errors++;
|
1198 |
|
|
} else {
|
1199 |
|
|
/* The packet length: up to 4.5K!. */
|
1200 |
|
|
short pkt_len = rx_status & 0x1fff;
|
1201 |
|
|
struct sk_buff *skb;
|
1202 |
|
|
|
1203 |
|
|
skb = DEV_ALLOC_SKB(pkt_len + 5);
|
1204 |
|
|
if (vortex_debug > 4)
|
1205 |
|
|
printk("Receiving packet size %d status %4.4x.\n",
|
1206 |
|
|
pkt_len, rx_status);
|
1207 |
|
|
if (skb != NULL) {
|
1208 |
|
|
skb->dev = dev;
|
1209 |
|
|
#if LINUX_VERSION_CODE >= 0x10300
|
1210 |
|
|
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
|
1211 |
|
|
/* 'skb_put()' points to the start of sk_buff data area. */
|
1212 |
|
|
insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
|
1213 |
|
|
(pkt_len + 3) >> 2);
|
1214 |
|
|
outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
|
1215 |
|
|
skb->protocol = eth_type_trans(skb, dev);
|
1216 |
|
|
#else
|
1217 |
|
|
skb->len = pkt_len;
|
1218 |
|
|
/* 'skb->data' points to the start of sk_buff data area. */
|
1219 |
|
|
insl(ioaddr + RX_FIFO, skb->data, (pkt_len + 3) >> 2);
|
1220 |
|
|
outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
|
1221 |
|
|
#endif /* KERNEL_1_3_0 */
|
1222 |
|
|
netif_rx(skb);
|
1223 |
|
|
dev->last_rx = jiffies;
|
1224 |
|
|
vp->stats.rx_packets++;
|
1225 |
|
|
/* Wait a limited time to go to next packet. */
|
1226 |
|
|
for (i = 200; i >= 0; i--)
|
1227 |
|
|
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
|
1228 |
|
|
break;
|
1229 |
|
|
continue;
|
1230 |
|
|
} else if (vortex_debug)
|
1231 |
|
|
printk("%s: Couldn't allocate a sk_buff of size %d.\n",
|
1232 |
|
|
dev->name, pkt_len);
|
1233 |
|
|
}
|
1234 |
|
|
outw(RxDiscard, ioaddr + EL3_CMD);
|
1235 |
|
|
vp->stats.rx_dropped++;
|
1236 |
|
|
/* Wait a limited time to skip this packet. */
|
1237 |
|
|
for (i = 200; i >= 0; i--)
|
1238 |
|
|
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
|
1239 |
|
|
break;
|
1240 |
|
|
}
|
1241 |
|
|
|
1242 |
|
|
return 0;
|
1243 |
|
|
}
|
1244 |
|
|
|
1245 |
|
|
static int
|
1246 |
|
|
boomerang_rx(struct device *dev)
|
1247 |
|
|
{
|
1248 |
|
|
struct vortex_private *vp = (struct vortex_private *)dev->priv;
|
1249 |
|
|
int entry = vp->cur_rx % RX_RING_SIZE;
|
1250 |
|
|
int ioaddr = dev->base_addr;
|
1251 |
|
|
int rx_status;
|
1252 |
|
|
|
1253 |
|
|
if (vortex_debug > 5)
|
1254 |
|
|
printk(" In boomerang_rx(), status %4.4x, rx_status %4.4x.\n",
|
1255 |
|
|
inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
|
1256 |
|
|
while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) {
|
1257 |
|
|
if (rx_status & RxDError) { /* Error, update stats. */
|
1258 |
|
|
unsigned char rx_error = rx_status >> 16;
|
1259 |
|
|
if (vortex_debug > 2)
|
1260 |
|
|
printk(" Rx error: status %2.2x.\n", rx_error);
|
1261 |
|
|
vp->stats.rx_errors++;
|
1262 |
|
|
if (rx_error & 0x01) vp->stats.rx_over_errors++;
|
1263 |
|
|
if (rx_error & 0x02) vp->stats.rx_length_errors++;
|
1264 |
|
|
if (rx_error & 0x04) vp->stats.rx_frame_errors++;
|
1265 |
|
|
if (rx_error & 0x08) vp->stats.rx_crc_errors++;
|
1266 |
|
|
if (rx_error & 0x10) vp->stats.rx_length_errors++;
|
1267 |
|
|
} else {
|
1268 |
|
|
/* The packet length: up to 4.5K!. */
|
1269 |
|
|
short pkt_len = rx_status & 0x1fff;
|
1270 |
|
|
struct sk_buff *skb;
|
1271 |
|
|
|
1272 |
|
|
if (vortex_debug > 4)
|
1273 |
|
|
printk("Receiving packet size %d status %4.4x.\n",
|
1274 |
|
|
pkt_len, rx_status);
|
1275 |
|
|
|
1276 |
|
|
/* Check if the packet is long enough to just accept without
|
1277 |
|
|
copying to a properly sized skbuff. */
|
1278 |
|
|
if (pkt_len < rx_copybreak
|
1279 |
|
|
&& (skb = DEV_ALLOC_SKB(pkt_len + 2)) != 0) {
|
1280 |
|
|
skb->dev = dev;
|
1281 |
|
|
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
|
1282 |
|
|
/* 'skb_put()' points to the start of sk_buff data area. */
|
1283 |
|
|
memcpy(skb_put(skb, pkt_len),
|
1284 |
|
|
bus_to_virt(vp->rx_ring[entry].addr),
|
1285 |
|
|
pkt_len);
|
1286 |
|
|
rx_copy++;
|
1287 |
|
|
} else{
|
1288 |
|
|
void *temp;
|
1289 |
|
|
/* Pass up the skbuff already on the Rx ring. */
|
1290 |
|
|
skb = vp->rx_skbuff[entry];
|
1291 |
|
|
vp->rx_skbuff[entry] = NULL;
|
1292 |
|
|
temp = skb_put(skb, pkt_len);
|
1293 |
|
|
/* Remove this checking code for final release. */
|
1294 |
|
|
if (bus_to_virt(vp->rx_ring[entry].addr) != temp)
|
1295 |
|
|
printk("%s: Warning -- the skbuff addresses do not match"
|
1296 |
|
|
" in boomerang_rx: %p vs. %p / %p.\n", dev->name,
|
1297 |
|
|
bus_to_virt(vp->rx_ring[entry].addr),
|
1298 |
|
|
skb->head, temp);
|
1299 |
|
|
rx_nocopy++;
|
1300 |
|
|
}
|
1301 |
|
|
#if LINUX_VERSION_CODE > 0x10300
|
1302 |
|
|
skb->protocol = eth_type_trans(skb, dev);
|
1303 |
|
|
#else
|
1304 |
|
|
skb->len = pkt_len;
|
1305 |
|
|
#endif
|
1306 |
|
|
netif_rx(skb);
|
1307 |
|
|
dev->last_rx = jiffies;
|
1308 |
|
|
vp->stats.rx_packets++;
|
1309 |
|
|
}
|
1310 |
|
|
entry = (++vp->cur_rx) % RX_RING_SIZE;
|
1311 |
|
|
}
|
1312 |
|
|
/* Refill the Rx ring buffers. */
|
1313 |
|
|
for (; vp->dirty_rx < vp->cur_rx; vp->dirty_rx++) {
|
1314 |
|
|
struct sk_buff *skb;
|
1315 |
|
|
entry = vp->dirty_rx % RX_RING_SIZE;
|
1316 |
|
|
if (vp->rx_skbuff[entry] == NULL) {
|
1317 |
|
|
skb = dev_alloc_skb(PKT_BUF_SZ);
|
1318 |
|
|
if (skb == NULL)
|
1319 |
|
|
break; /* Bad news! */
|
1320 |
|
|
skb->dev = dev; /* Mark as being used by this device. */
|
1321 |
|
|
#if LINUX_VERSION_CODE > 0x10300
|
1322 |
|
|
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
|
1323 |
|
|
vp->rx_ring[entry].addr = virt_to_bus(skb->tail);
|
1324 |
|
|
#else
|
1325 |
|
|
vp->rx_ring[entry].addr = virt_to_bus(skb->data);
|
1326 |
|
|
#endif
|
1327 |
|
|
vp->rx_skbuff[entry] = skb;
|
1328 |
|
|
}
|
1329 |
|
|
vp->rx_ring[entry].status = 0; /* Clear complete bit. */
|
1330 |
|
|
}
|
1331 |
|
|
return 0;
|
1332 |
|
|
}
|
1333 |
|
|
|
1334 |
|
|
static int
|
1335 |
|
|
vortex_close(struct device *dev)
|
1336 |
|
|
{
|
1337 |
|
|
struct vortex_private *vp = (struct vortex_private *)dev->priv;
|
1338 |
|
|
int ioaddr = dev->base_addr;
|
1339 |
|
|
int i;
|
1340 |
|
|
|
1341 |
|
|
dev->start = 0;
|
1342 |
|
|
dev->tbusy = 1;
|
1343 |
|
|
|
1344 |
|
|
if (vortex_debug > 1) {
|
1345 |
|
|
printk("%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
|
1346 |
|
|
dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus));
|
1347 |
|
|
printk("%s: vortex close stats: rx_nocopy %d rx_copy %d"
|
1348 |
|
|
" tx_queued %d.\n",
|
1349 |
|
|
dev->name, rx_nocopy, rx_copy, queued_packet);
|
1350 |
|
|
}
|
1351 |
|
|
|
1352 |
|
|
del_timer(&vp->timer);
|
1353 |
|
|
|
1354 |
|
|
/* Turn off statistics ASAP. We update lp->stats below. */
|
1355 |
|
|
outw(StatsDisable, ioaddr + EL3_CMD);
|
1356 |
|
|
|
1357 |
|
|
/* Disable the receiver and transmitter. */
|
1358 |
|
|
outw(RxDisable, ioaddr + EL3_CMD);
|
1359 |
|
|
outw(TxDisable, ioaddr + EL3_CMD);
|
1360 |
|
|
|
1361 |
|
|
if (dev->if_port == XCVR_10base2)
|
1362 |
|
|
/* Turn off thinnet power. Green! */
|
1363 |
|
|
outw(StopCoax, ioaddr + EL3_CMD);
|
1364 |
|
|
|
1365 |
|
|
#ifdef SA_SHIRQ
|
1366 |
|
|
free_irq(dev->irq, dev);
|
1367 |
|
|
#else
|
1368 |
|
|
free_irq(dev->irq);
|
1369 |
|
|
irq2dev_map[dev->irq] = 0;
|
1370 |
|
|
#endif
|
1371 |
|
|
|
1372 |
|
|
outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
|
1373 |
|
|
|
1374 |
|
|
update_stats(ioaddr, dev);
|
1375 |
|
|
if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */
|
1376 |
|
|
outl(0, ioaddr + UpListPtr);
|
1377 |
|
|
for (i = 0; i < RX_RING_SIZE; i++)
|
1378 |
|
|
if (vp->rx_skbuff[i]) {
|
1379 |
|
|
#if LINUX_VERSION_CODE < 0x20100
|
1380 |
|
|
vp->rx_skbuff[i]->free = 1;
|
1381 |
|
|
#endif
|
1382 |
|
|
dev_kfree_skb (vp->rx_skbuff[i], FREE_WRITE);
|
1383 |
|
|
vp->rx_skbuff[i] = 0;
|
1384 |
|
|
}
|
1385 |
|
|
}
|
1386 |
|
|
if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */
|
1387 |
|
|
outl(0, ioaddr + DownListPtr);
|
1388 |
|
|
for (i = 0; i < TX_RING_SIZE; i++)
|
1389 |
|
|
if (vp->tx_skbuff[i]) {
|
1390 |
|
|
dev_kfree_skb(vp->tx_skbuff[i], FREE_WRITE);
|
1391 |
|
|
vp->tx_skbuff[i] = 0;
|
1392 |
|
|
}
|
1393 |
|
|
}
|
1394 |
|
|
|
1395 |
|
|
MOD_DEC_USE_COUNT;
|
1396 |
|
|
|
1397 |
|
|
return 0;
|
1398 |
|
|
}
|
1399 |
|
|
|
1400 |
|
|
static struct enet_statistics *
|
1401 |
|
|
vortex_get_stats(struct device *dev)
|
1402 |
|
|
{
|
1403 |
|
|
struct vortex_private *vp = (struct vortex_private *)dev->priv;
|
1404 |
|
|
unsigned long flags;
|
1405 |
|
|
|
1406 |
|
|
if (dev->start) {
|
1407 |
|
|
save_flags(flags);
|
1408 |
|
|
cli();
|
1409 |
|
|
update_stats(dev->base_addr, dev);
|
1410 |
|
|
restore_flags(flags);
|
1411 |
|
|
}
|
1412 |
|
|
return &vp->stats;
|
1413 |
|
|
}
|
1414 |
|
|
|
1415 |
|
|
/* Update statistics.
|
1416 |
|
|
Unlike with the EL3 we need not worry about interrupts changing
|
1417 |
|
|
the window setting from underneath us, but we must still guard
|
1418 |
|
|
against a race condition with a StatsUpdate interrupt updating the
|
1419 |
|
|
table. This is done by checking that the ASM (!) code generated uses
|
1420 |
|
|
atomic updates with '+='.
|
1421 |
|
|
*/
|
1422 |
|
|
static void update_stats(int ioaddr, struct device *dev)
|
1423 |
|
|
{
|
1424 |
|
|
struct vortex_private *vp = (struct vortex_private *)dev->priv;
|
1425 |
|
|
|
1426 |
|
|
/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
|
1427 |
|
|
/* Switch to the stats window, and read everything. */
|
1428 |
|
|
EL3WINDOW(6);
|
1429 |
|
|
vp->stats.tx_carrier_errors += inb(ioaddr + 0);
|
1430 |
|
|
vp->stats.tx_heartbeat_errors += inb(ioaddr + 1);
|
1431 |
|
|
/* Multiple collisions. */ inb(ioaddr + 2);
|
1432 |
|
|
vp->stats.collisions += inb(ioaddr + 3);
|
1433 |
|
|
vp->stats.tx_window_errors += inb(ioaddr + 4);
|
1434 |
|
|
vp->stats.rx_fifo_errors += inb(ioaddr + 5);
|
1435 |
|
|
vp->stats.tx_packets += inb(ioaddr + 6);
|
1436 |
|
|
vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4;
|
1437 |
|
|
/* Rx packets */ inb(ioaddr + 7); /* Must read to clear */
|
1438 |
|
|
/* Tx deferrals */ inb(ioaddr + 8);
|
1439 |
|
|
/* Don't bother with register 9, an extension of registers 6&7.
|
1440 |
|
|
If we do use the 6&7 values the atomic update assumption above
|
1441 |
|
|
is invalid. */
|
1442 |
|
|
inw(ioaddr + 10); /* Total Rx and Tx octets. */
|
1443 |
|
|
inw(ioaddr + 12);
|
1444 |
|
|
/* New: On the Vortex we must also clear the BadSSD counter. */
|
1445 |
|
|
EL3WINDOW(4);
|
1446 |
|
|
inb(ioaddr + 12);
|
1447 |
|
|
|
1448 |
|
|
/* We change back to window 7 (not 1) with the Vortex. */
|
1449 |
|
|
EL3WINDOW(7);
|
1450 |
|
|
return;
|
1451 |
|
|
}
|
1452 |
|
|
|
1453 |
|
|
/* This new version of set_rx_mode() supports v1.4 kernels.
|
1454 |
|
|
The Vortex chip has no documented multicast filter, so the only
|
1455 |
|
|
multicast setting is to receive all multicast frames. At least
|
1456 |
|
|
the chip has a very clean way to set the mode, unlike many others. */
|
1457 |
|
|
static void
|
1458 |
|
|
set_rx_mode(struct device *dev)
|
1459 |
|
|
{
|
1460 |
|
|
int ioaddr = dev->base_addr;
|
1461 |
|
|
short new_mode;
|
1462 |
|
|
|
1463 |
|
|
if (dev->flags & IFF_PROMISC) {
|
1464 |
|
|
if (vortex_debug > 3)
|
1465 |
|
|
printk("%s: Setting promiscuous mode.\n", dev->name);
|
1466 |
|
|
new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm;
|
1467 |
|
|
} else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) {
|
1468 |
|
|
new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast;
|
1469 |
|
|
} else
|
1470 |
|
|
new_mode = SetRxFilter | RxStation | RxBroadcast;
|
1471 |
|
|
|
1472 |
|
|
outw(new_mode, ioaddr + EL3_CMD);
|
1473 |
|
|
}
|
1474 |
|
|
|
1475 |
|
|
#ifdef MODULE
|
1476 |
|
|
void
|
1477 |
|
|
cleanup_module(void)
|
1478 |
|
|
{
|
1479 |
|
|
struct device *next_dev;
|
1480 |
|
|
|
1481 |
|
|
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
|
1482 |
|
|
while (root_vortex_dev) {
|
1483 |
|
|
next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module;
|
1484 |
|
|
if (root_vortex_dev->dma)
|
1485 |
|
|
free_dma(root_vortex_dev->dma);
|
1486 |
|
|
unregister_netdev(root_vortex_dev);
|
1487 |
|
|
outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD);
|
1488 |
|
|
release_region(root_vortex_dev->base_addr, CORKSCREW_TOTAL_SIZE);
|
1489 |
|
|
kfree(root_vortex_dev);
|
1490 |
|
|
root_vortex_dev = next_dev;
|
1491 |
|
|
}
|
1492 |
|
|
}
|
1493 |
|
|
#endif /* MODULE */
|
1494 |
|
|
|
1495 |
|
|
/*
|
1496 |
|
|
* Local variables:
|
1497 |
|
|
* compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c515.c"
|
1498 |
|
|
* c-indent-level: 4
|
1499 |
|
|
* tab-width: 4
|
1500 |
|
|
* End:
|
1501 |
|
|
*/
|