diff options
Diffstat (limited to 'drivers/net/pcmcia')
-rw-r--r-- | drivers/net/pcmcia/3c574_cs.c | 1307 | ||||
-rw-r--r-- | drivers/net/pcmcia/3c589_cs.c | 1081 | ||||
-rw-r--r-- | drivers/net/pcmcia/Kconfig | 132 | ||||
-rw-r--r-- | drivers/net/pcmcia/Makefile | 16 | ||||
-rw-r--r-- | drivers/net/pcmcia/axnet_cs.c | 1864 | ||||
-rw-r--r-- | drivers/net/pcmcia/com20020_cs.c | 509 | ||||
-rw-r--r-- | drivers/net/pcmcia/fmvj18x_cs.c | 1286 | ||||
-rw-r--r-- | drivers/net/pcmcia/ibmtr_cs.c | 535 | ||||
-rw-r--r-- | drivers/net/pcmcia/nmclan_cs.c | 1699 | ||||
-rw-r--r-- | drivers/net/pcmcia/ositech.h | 358 | ||||
-rw-r--r-- | drivers/net/pcmcia/pcnet_cs.c | 1659 | ||||
-rw-r--r-- | drivers/net/pcmcia/smc91c92_cs.c | 2260 | ||||
-rw-r--r-- | drivers/net/pcmcia/xirc2ps_cs.c | 2031 |
13 files changed, 14737 insertions, 0 deletions
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c new file mode 100644 index 000000000000..41e517114807 --- /dev/null +++ b/drivers/net/pcmcia/3c574_cs.c | |||
@@ -0,0 +1,1307 @@ | |||
1 | /* 3c574.c: A PCMCIA ethernet driver for the 3com 3c574 "RoadRunner". | ||
2 | |||
3 | Written 1993-1998 by | ||
4 | Donald Becker, becker@scyld.com, (driver core) and | ||
5 | David Hinds, dahinds@users.sourceforge.net (from his PC card code). | ||
6 | Locking fixes (C) Copyright 2003 Red Hat Inc | ||
7 | |||
8 | This software may be used and distributed according to the terms of | ||
9 | the GNU General Public License, incorporated herein by reference. | ||
10 | |||
11 | This driver derives from Donald Becker's 3c509 core, which has the | ||
12 | following copyright: | ||
13 | Copyright 1993 United States Government as represented by the | ||
14 | Director, National Security Agency. | ||
15 | |||
16 | |||
17 | */ | ||
18 | |||
19 | /* | ||
20 | Theory of Operation | ||
21 | |||
22 | I. Board Compatibility | ||
23 | |||
24 | This device driver is designed for the 3Com 3c574 PC card Fast Ethernet | ||
25 | Adapter. | ||
26 | |||
27 | II. Board-specific settings | ||
28 | |||
29 | None -- PC cards are autoconfigured. | ||
30 | |||
31 | III. Driver operation | ||
32 | |||
33 | The 3c574 uses a Boomerang-style interface, without the bus-master capability. | ||
34 | See the Boomerang driver and documentation for most details. | ||
35 | |||
36 | IV. Notes and chip documentation. | ||
37 | |||
38 | Two added registers are used to enhance PIO performance, RunnerRdCtrl and | ||
39 | RunnerWrCtrl. These are 11 bit down-counters that are preloaded with the | ||
40 | count of word (16 bits) reads or writes the driver is about to do to the Rx | ||
41 | or Tx FIFO. The chip is then able to hide the internal-PCI-bus to PC-card | ||
42 | translation latency by buffering the I/O operations with an 8 word FIFO. | ||
43 | Note: No other chip accesses are permitted when this buffer is used. | ||
44 | |||
45 | A second enhancement is that both attribute and common memory space | ||
46 | 0x0800-0x0fff can translated to the PIO FIFO. Thus memory operations (faster | ||
47 | with *some* PCcard bridges) may be used instead of I/O operations. | ||
48 | This is enabled by setting the 0x10 bit in the PCMCIA LAN COR. | ||
49 | |||
50 | Some slow PC card bridges work better if they never see a WAIT signal. | ||
51 | This is configured by setting the 0x20 bit in the PCMCIA LAN COR. | ||
52 | Only do this after testing that it is reliable and improves performance. | ||
53 | |||
54 | The upper five bits of RunnerRdCtrl are used to window into PCcard | ||
55 | configuration space registers. Window 0 is the regular Boomerang/Odie | ||
56 | register set, 1-5 are various PC card control registers, and 16-31 are | ||
57 | the (reversed!) CIS table. | ||
58 | |||
59 | A final note: writing the InternalConfig register in window 3 with an | ||
60 | invalid ramWidth is Very Bad. | ||
61 | |||
62 | V. References | ||
63 | |||
64 | http://www.scyld.com/expert/NWay.html | ||
65 | http://www.national.com/pf/DP/DP83840.html | ||
66 | |||
67 | Thanks to Terry Murphy of 3Com for providing development information for | ||
68 | earlier 3Com products. | ||
69 | |||
70 | */ | ||
71 | |||
72 | #include <linux/module.h> | ||
73 | #include <linux/kernel.h> | ||
74 | #include <linux/init.h> | ||
75 | #include <linux/slab.h> | ||
76 | #include <linux/string.h> | ||
77 | #include <linux/timer.h> | ||
78 | #include <linux/interrupt.h> | ||
79 | #include <linux/in.h> | ||
80 | #include <linux/delay.h> | ||
81 | #include <linux/netdevice.h> | ||
82 | #include <linux/etherdevice.h> | ||
83 | #include <linux/skbuff.h> | ||
84 | #include <linux/if_arp.h> | ||
85 | #include <linux/ioport.h> | ||
86 | #include <linux/ethtool.h> | ||
87 | #include <linux/bitops.h> | ||
88 | |||
89 | #include <pcmcia/version.h> | ||
90 | #include <pcmcia/cs_types.h> | ||
91 | #include <pcmcia/cs.h> | ||
92 | #include <pcmcia/cistpl.h> | ||
93 | #include <pcmcia/cisreg.h> | ||
94 | #include <pcmcia/ciscode.h> | ||
95 | #include <pcmcia/ds.h> | ||
96 | #include <pcmcia/mem_op.h> | ||
97 | |||
98 | #include <asm/uaccess.h> | ||
99 | #include <asm/io.h> | ||
100 | #include <asm/system.h> | ||
101 | |||
102 | /*====================================================================*/ | ||
103 | |||
104 | /* Module parameters */ | ||
105 | |||
106 | MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); | ||
107 | MODULE_DESCRIPTION("3Com 3c574 series PCMCIA ethernet driver"); | ||
108 | MODULE_LICENSE("GPL"); | ||
109 | |||
110 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) | ||
111 | |||
112 | /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ | ||
113 | INT_MODULE_PARM(max_interrupt_work, 32); | ||
114 | |||
115 | /* Force full duplex modes? */ | ||
116 | INT_MODULE_PARM(full_duplex, 0); | ||
117 | |||
118 | /* Autodetect link polarity reversal? */ | ||
119 | INT_MODULE_PARM(auto_polarity, 1); | ||
120 | |||
121 | #ifdef PCMCIA_DEBUG | ||
122 | INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); | ||
123 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) | ||
124 | static char *version = | ||
125 | "3c574_cs.c 1.65ac1 2003/04/07 Donald Becker/David Hinds, becker@scyld.com.\n"; | ||
126 | #else | ||
127 | #define DEBUG(n, args...) | ||
128 | #endif | ||
129 | |||
130 | /*====================================================================*/ | ||
131 | |||
132 | /* Time in jiffies before concluding the transmitter is hung. */ | ||
133 | #define TX_TIMEOUT ((800*HZ)/1000) | ||
134 | |||
135 | /* To minimize the size of the driver source and make the driver more | ||
136 | readable not all constants are symbolically defined. | ||
137 | You'll need the manual if you want to understand driver details anyway. */ | ||
138 | /* Offsets from base I/O address. */ | ||
139 | #define EL3_DATA 0x00 | ||
140 | #define EL3_CMD 0x0e | ||
141 | #define EL3_STATUS 0x0e | ||
142 | |||
143 | #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) | ||
144 | |||
145 | /* The top five bits written to EL3_CMD are a command, the lower | ||
146 | 11 bits are the parameter, if applicable. */ | ||
147 | enum el3_cmds { | ||
148 | TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, | ||
149 | RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11, | ||
150 | TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, | ||
151 | FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, | ||
152 | SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, | ||
153 | SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11, | ||
154 | StatsDisable = 22<<11, StopCoax = 23<<11, | ||
155 | }; | ||
156 | |||
157 | enum elxl_status { | ||
158 | IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, | ||
159 | TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, | ||
160 | IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000 }; | ||
161 | |||
162 | /* The SetRxFilter command accepts the following classes: */ | ||
163 | enum RxFilter { | ||
164 | RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 | ||
165 | }; | ||
166 | |||
167 | enum Window0 { | ||
168 | Wn0EepromCmd = 10, Wn0EepromData = 12, /* EEPROM command/address, data. */ | ||
169 | IntrStatus=0x0E, /* Valid in all windows. */ | ||
170 | }; | ||
171 | /* These assumes the larger EEPROM. */ | ||
172 | enum Win0_EEPROM_cmds { | ||
173 | EEPROM_Read = 0x200, EEPROM_WRITE = 0x100, EEPROM_ERASE = 0x300, | ||
174 | EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */ | ||
175 | EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */ | ||
176 | }; | ||
177 | |||
178 | /* Register window 1 offsets, the window used in normal operation. | ||
179 | On the "Odie" this window is always mapped at offsets 0x10-0x1f. | ||
180 | Except for TxFree, which is overlapped by RunnerWrCtrl. */ | ||
181 | enum Window1 { | ||
182 | TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14, | ||
183 | RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B, | ||
184 | TxFree = 0x0C, /* Remaining free bytes in Tx buffer. */ | ||
185 | RunnerRdCtrl = 0x16, RunnerWrCtrl = 0x1c, | ||
186 | }; | ||
187 | |||
188 | enum Window3 { /* Window 3: MAC/config bits. */ | ||
189 | Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8, | ||
190 | }; | ||
191 | union wn3_config { | ||
192 | int i; | ||
193 | struct w3_config_fields { | ||
194 | unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2; | ||
195 | int pad8:8; | ||
196 | unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1; | ||
197 | int pad24:7; | ||
198 | } u; | ||
199 | }; | ||
200 | |||
201 | enum Window4 { /* Window 4: Xcvr/media bits. */ | ||
202 | Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10, | ||
203 | }; | ||
204 | |||
205 | #define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ | ||
206 | |||
207 | struct el3_private { | ||
208 | dev_link_t link; | ||
209 | dev_node_t node; | ||
210 | struct net_device_stats stats; | ||
211 | u16 advertising, partner; /* NWay media advertisement */ | ||
212 | unsigned char phys; /* MII device address */ | ||
213 | unsigned int autoselect:1, default_media:3; /* Read from the EEPROM/Wn3_Config. */ | ||
214 | /* for transceiver monitoring */ | ||
215 | struct timer_list media; | ||
216 | unsigned short media_status; | ||
217 | unsigned short fast_poll; | ||
218 | unsigned long last_irq; | ||
219 | spinlock_t window_lock; /* Guards the Window selection */ | ||
220 | }; | ||
221 | |||
222 | /* Set iff a MII transceiver on any interface requires mdio preamble. | ||
223 | This only set with the original DP83840 on older 3c905 boards, so the extra | ||
224 | code size of a per-interface flag is not worthwhile. */ | ||
225 | static char mii_preamble_required = 0; | ||
226 | |||
227 | /* Index of functions. */ | ||
228 | |||
229 | static void tc574_config(dev_link_t *link); | ||
230 | static void tc574_release(dev_link_t *link); | ||
231 | static int tc574_event(event_t event, int priority, | ||
232 | event_callback_args_t *args); | ||
233 | |||
234 | static void mdio_sync(kio_addr_t ioaddr, int bits); | ||
235 | static int mdio_read(kio_addr_t ioaddr, int phy_id, int location); | ||
236 | static void mdio_write(kio_addr_t ioaddr, int phy_id, int location, int value); | ||
237 | static unsigned short read_eeprom(kio_addr_t ioaddr, int index); | ||
238 | static void tc574_wait_for_completion(struct net_device *dev, int cmd); | ||
239 | |||
240 | static void tc574_reset(struct net_device *dev); | ||
241 | static void media_check(unsigned long arg); | ||
242 | static int el3_open(struct net_device *dev); | ||
243 | static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
244 | static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs); | ||
245 | static void update_stats(struct net_device *dev); | ||
246 | static struct net_device_stats *el3_get_stats(struct net_device *dev); | ||
247 | static int el3_rx(struct net_device *dev, int worklimit); | ||
248 | static int el3_close(struct net_device *dev); | ||
249 | static void el3_tx_timeout(struct net_device *dev); | ||
250 | static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
251 | static struct ethtool_ops netdev_ethtool_ops; | ||
252 | static void set_rx_mode(struct net_device *dev); | ||
253 | |||
254 | static dev_info_t dev_info = "3c574_cs"; | ||
255 | |||
256 | static dev_link_t *tc574_attach(void); | ||
257 | static void tc574_detach(dev_link_t *); | ||
258 | |||
259 | static dev_link_t *dev_list; | ||
260 | |||
261 | /* | ||
262 | tc574_attach() creates an "instance" of the driver, allocating | ||
263 | local data structures for one device. The device is registered | ||
264 | with Card Services. | ||
265 | */ | ||
266 | |||
267 | static dev_link_t *tc574_attach(void) | ||
268 | { | ||
269 | struct el3_private *lp; | ||
270 | client_reg_t client_reg; | ||
271 | dev_link_t *link; | ||
272 | struct net_device *dev; | ||
273 | int ret; | ||
274 | |||
275 | DEBUG(0, "3c574_attach()\n"); | ||
276 | |||
277 | /* Create the PC card device object. */ | ||
278 | dev = alloc_etherdev(sizeof(struct el3_private)); | ||
279 | if (!dev) | ||
280 | return NULL; | ||
281 | lp = netdev_priv(dev); | ||
282 | link = &lp->link; | ||
283 | link->priv = dev; | ||
284 | |||
285 | spin_lock_init(&lp->window_lock); | ||
286 | link->io.NumPorts1 = 32; | ||
287 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
288 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
289 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
290 | link->irq.Handler = &el3_interrupt; | ||
291 | link->irq.Instance = dev; | ||
292 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
293 | link->conf.Vcc = 50; | ||
294 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
295 | link->conf.ConfigIndex = 1; | ||
296 | link->conf.Present = PRESENT_OPTION; | ||
297 | |||
298 | /* The EL3-specific entries in the device structure. */ | ||
299 | dev->hard_start_xmit = &el3_start_xmit; | ||
300 | dev->get_stats = &el3_get_stats; | ||
301 | dev->do_ioctl = &el3_ioctl; | ||
302 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | ||
303 | dev->set_multicast_list = &set_rx_mode; | ||
304 | dev->open = &el3_open; | ||
305 | dev->stop = &el3_close; | ||
306 | #ifdef HAVE_TX_TIMEOUT | ||
307 | dev->tx_timeout = el3_tx_timeout; | ||
308 | dev->watchdog_timeo = TX_TIMEOUT; | ||
309 | #endif | ||
310 | |||
311 | /* Register with Card Services */ | ||
312 | link->next = dev_list; | ||
313 | dev_list = link; | ||
314 | client_reg.dev_info = &dev_info; | ||
315 | client_reg.EventMask = | ||
316 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
317 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
318 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
319 | client_reg.event_handler = &tc574_event; | ||
320 | client_reg.Version = 0x0210; | ||
321 | client_reg.event_callback_args.client_data = link; | ||
322 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
323 | if (ret != 0) { | ||
324 | cs_error(link->handle, RegisterClient, ret); | ||
325 | tc574_detach(link); | ||
326 | return NULL; | ||
327 | } | ||
328 | |||
329 | return link; | ||
330 | } /* tc574_attach */ | ||
331 | |||
332 | /* | ||
333 | |||
334 | This deletes a driver "instance". The device is de-registered | ||
335 | with Card Services. If it has been released, all local data | ||
336 | structures are freed. Otherwise, the structures will be freed | ||
337 | when the device is released. | ||
338 | |||
339 | */ | ||
340 | |||
341 | static void tc574_detach(dev_link_t *link) | ||
342 | { | ||
343 | struct net_device *dev = link->priv; | ||
344 | dev_link_t **linkp; | ||
345 | |||
346 | DEBUG(0, "3c574_detach(0x%p)\n", link); | ||
347 | |||
348 | /* Locate device structure */ | ||
349 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
350 | if (*linkp == link) break; | ||
351 | if (*linkp == NULL) | ||
352 | return; | ||
353 | |||
354 | if (link->dev) | ||
355 | unregister_netdev(dev); | ||
356 | |||
357 | if (link->state & DEV_CONFIG) | ||
358 | tc574_release(link); | ||
359 | |||
360 | if (link->handle) | ||
361 | pcmcia_deregister_client(link->handle); | ||
362 | |||
363 | /* Unlink device structure, free bits */ | ||
364 | *linkp = link->next; | ||
365 | free_netdev(dev); | ||
366 | } /* tc574_detach */ | ||
367 | |||
368 | /* | ||
369 | tc574_config() is scheduled to run after a CARD_INSERTION event | ||
370 | is received, to configure the PCMCIA socket, and to make the | ||
371 | ethernet device available to the system. | ||
372 | */ | ||
373 | |||
374 | #define CS_CHECK(fn, ret) \ | ||
375 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
376 | |||
377 | static char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; | ||
378 | |||
379 | static void tc574_config(dev_link_t *link) | ||
380 | { | ||
381 | client_handle_t handle = link->handle; | ||
382 | struct net_device *dev = link->priv; | ||
383 | struct el3_private *lp = netdev_priv(dev); | ||
384 | tuple_t tuple; | ||
385 | cisparse_t parse; | ||
386 | unsigned short buf[32]; | ||
387 | int last_fn, last_ret, i, j; | ||
388 | kio_addr_t ioaddr; | ||
389 | u16 *phys_addr; | ||
390 | char *cardname; | ||
391 | union wn3_config config; | ||
392 | |||
393 | phys_addr = (u16 *)dev->dev_addr; | ||
394 | |||
395 | DEBUG(0, "3c574_config(0x%p)\n", link); | ||
396 | |||
397 | tuple.Attributes = 0; | ||
398 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
399 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
400 | tuple.TupleData = (cisdata_t *)buf; | ||
401 | tuple.TupleDataMax = 64; | ||
402 | tuple.TupleOffset = 0; | ||
403 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
404 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | ||
405 | link->conf.ConfigBase = parse.config.base; | ||
406 | link->conf.Present = parse.config.rmask[0]; | ||
407 | |||
408 | /* Configure card */ | ||
409 | link->state |= DEV_CONFIG; | ||
410 | |||
411 | link->io.IOAddrLines = 16; | ||
412 | for (i = j = 0; j < 0x400; j += 0x20) { | ||
413 | link->io.BasePort1 = j ^ 0x300; | ||
414 | i = pcmcia_request_io(link->handle, &link->io); | ||
415 | if (i == CS_SUCCESS) break; | ||
416 | } | ||
417 | if (i != CS_SUCCESS) { | ||
418 | cs_error(link->handle, RequestIO, i); | ||
419 | goto failed; | ||
420 | } | ||
421 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | ||
422 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | ||
423 | |||
424 | dev->irq = link->irq.AssignedIRQ; | ||
425 | dev->base_addr = link->io.BasePort1; | ||
426 | |||
427 | ioaddr = dev->base_addr; | ||
428 | |||
429 | /* The 3c574 normally uses an EEPROM for configuration info, including | ||
430 | the hardware address. The future products may include a modem chip | ||
431 | and put the address in the CIS. */ | ||
432 | tuple.DesiredTuple = 0x88; | ||
433 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { | ||
434 | pcmcia_get_tuple_data(handle, &tuple); | ||
435 | for (i = 0; i < 3; i++) | ||
436 | phys_addr[i] = htons(buf[i]); | ||
437 | } else { | ||
438 | EL3WINDOW(0); | ||
439 | for (i = 0; i < 3; i++) | ||
440 | phys_addr[i] = htons(read_eeprom(ioaddr, i + 10)); | ||
441 | if (phys_addr[0] == 0x6060) { | ||
442 | printk(KERN_NOTICE "3c574_cs: IO port conflict at 0x%03lx" | ||
443 | "-0x%03lx\n", dev->base_addr, dev->base_addr+15); | ||
444 | goto failed; | ||
445 | } | ||
446 | } | ||
447 | tuple.DesiredTuple = CISTPL_VERS_1; | ||
448 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS && | ||
449 | pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS && | ||
450 | pcmcia_parse_tuple(handle, &tuple, &parse) == CS_SUCCESS) { | ||
451 | cardname = parse.version_1.str + parse.version_1.ofs[1]; | ||
452 | } else | ||
453 | cardname = "3Com 3c574"; | ||
454 | |||
455 | { | ||
456 | u_char mcr; | ||
457 | outw(2<<11, ioaddr + RunnerRdCtrl); | ||
458 | mcr = inb(ioaddr + 2); | ||
459 | outw(0<<11, ioaddr + RunnerRdCtrl); | ||
460 | printk(KERN_INFO " ASIC rev %d,", mcr>>3); | ||
461 | EL3WINDOW(3); | ||
462 | config.i = inl(ioaddr + Wn3_Config); | ||
463 | lp->default_media = config.u.xcvr; | ||
464 | lp->autoselect = config.u.autoselect; | ||
465 | } | ||
466 | |||
467 | init_timer(&lp->media); | ||
468 | |||
469 | { | ||
470 | int phy; | ||
471 | |||
472 | /* Roadrunner only: Turn on the MII transceiver */ | ||
473 | outw(0x8040, ioaddr + Wn3_Options); | ||
474 | mdelay(1); | ||
475 | outw(0xc040, ioaddr + Wn3_Options); | ||
476 | tc574_wait_for_completion(dev, TxReset); | ||
477 | tc574_wait_for_completion(dev, RxReset); | ||
478 | mdelay(1); | ||
479 | outw(0x8040, ioaddr + Wn3_Options); | ||
480 | |||
481 | EL3WINDOW(4); | ||
482 | for (phy = 1; phy <= 32; phy++) { | ||
483 | int mii_status; | ||
484 | mdio_sync(ioaddr, 32); | ||
485 | mii_status = mdio_read(ioaddr, phy & 0x1f, 1); | ||
486 | if (mii_status != 0xffff) { | ||
487 | lp->phys = phy & 0x1f; | ||
488 | DEBUG(0, " MII transceiver at index %d, status %x.\n", | ||
489 | phy, mii_status); | ||
490 | if ((mii_status & 0x0040) == 0) | ||
491 | mii_preamble_required = 1; | ||
492 | break; | ||
493 | } | ||
494 | } | ||
495 | if (phy > 32) { | ||
496 | printk(KERN_NOTICE " No MII transceivers found!\n"); | ||
497 | goto failed; | ||
498 | } | ||
499 | i = mdio_read(ioaddr, lp->phys, 16) | 0x40; | ||
500 | mdio_write(ioaddr, lp->phys, 16, i); | ||
501 | lp->advertising = mdio_read(ioaddr, lp->phys, 4); | ||
502 | if (full_duplex) { | ||
503 | /* Only advertise the FD media types. */ | ||
504 | lp->advertising &= ~0x02a0; | ||
505 | mdio_write(ioaddr, lp->phys, 4, lp->advertising); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | link->state &= ~DEV_CONFIG_PENDING; | ||
510 | link->dev = &lp->node; | ||
511 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
512 | |||
513 | if (register_netdev(dev) != 0) { | ||
514 | printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n"); | ||
515 | link->dev = NULL; | ||
516 | goto failed; | ||
517 | } | ||
518 | |||
519 | strcpy(lp->node.dev_name, dev->name); | ||
520 | |||
521 | printk(KERN_INFO "%s: %s at io %#3lx, irq %d, hw_addr ", | ||
522 | dev->name, cardname, dev->base_addr, dev->irq); | ||
523 | for (i = 0; i < 6; i++) | ||
524 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : ".\n")); | ||
525 | printk(" %dK FIFO split %s Rx:Tx, %sMII interface.\n", | ||
526 | 8 << config.u.ram_size, ram_split[config.u.ram_split], | ||
527 | config.u.autoselect ? "autoselect " : ""); | ||
528 | |||
529 | return; | ||
530 | |||
531 | cs_failed: | ||
532 | cs_error(link->handle, last_fn, last_ret); | ||
533 | failed: | ||
534 | tc574_release(link); | ||
535 | return; | ||
536 | |||
537 | } /* tc574_config */ | ||
538 | |||
539 | /* | ||
540 | After a card is removed, tc574_release() will unregister the net | ||
541 | device, and release the PCMCIA configuration. If the device is | ||
542 | still open, this will be postponed until it is closed. | ||
543 | */ | ||
544 | |||
545 | static void tc574_release(dev_link_t *link) | ||
546 | { | ||
547 | DEBUG(0, "3c574_release(0x%p)\n", link); | ||
548 | |||
549 | pcmcia_release_configuration(link->handle); | ||
550 | pcmcia_release_io(link->handle, &link->io); | ||
551 | pcmcia_release_irq(link->handle, &link->irq); | ||
552 | |||
553 | link->state &= ~DEV_CONFIG; | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | The card status event handler. Mostly, this schedules other | ||
558 | stuff to run after an event is received. A CARD_REMOVAL event | ||
559 | also sets some flags to discourage the net drivers from trying | ||
560 | to talk to the card any more. | ||
561 | */ | ||
562 | |||
563 | static int tc574_event(event_t event, int priority, | ||
564 | event_callback_args_t *args) | ||
565 | { | ||
566 | dev_link_t *link = args->client_data; | ||
567 | struct net_device *dev = link->priv; | ||
568 | |||
569 | DEBUG(1, "3c574_event(0x%06x)\n", event); | ||
570 | |||
571 | switch (event) { | ||
572 | case CS_EVENT_CARD_REMOVAL: | ||
573 | link->state &= ~DEV_PRESENT; | ||
574 | if (link->state & DEV_CONFIG) | ||
575 | netif_device_detach(dev); | ||
576 | break; | ||
577 | case CS_EVENT_CARD_INSERTION: | ||
578 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
579 | tc574_config(link); | ||
580 | break; | ||
581 | case CS_EVENT_PM_SUSPEND: | ||
582 | link->state |= DEV_SUSPEND; | ||
583 | /* Fall through... */ | ||
584 | case CS_EVENT_RESET_PHYSICAL: | ||
585 | if (link->state & DEV_CONFIG) { | ||
586 | if (link->open) | ||
587 | netif_device_detach(dev); | ||
588 | pcmcia_release_configuration(link->handle); | ||
589 | } | ||
590 | break; | ||
591 | case CS_EVENT_PM_RESUME: | ||
592 | link->state &= ~DEV_SUSPEND; | ||
593 | /* Fall through... */ | ||
594 | case CS_EVENT_CARD_RESET: | ||
595 | if (link->state & DEV_CONFIG) { | ||
596 | pcmcia_request_configuration(link->handle, &link->conf); | ||
597 | if (link->open) { | ||
598 | tc574_reset(dev); | ||
599 | netif_device_attach(dev); | ||
600 | } | ||
601 | } | ||
602 | break; | ||
603 | } | ||
604 | return 0; | ||
605 | } /* tc574_event */ | ||
606 | |||
607 | static void dump_status(struct net_device *dev) | ||
608 | { | ||
609 | kio_addr_t ioaddr = dev->base_addr; | ||
610 | EL3WINDOW(1); | ||
611 | printk(KERN_INFO " irq status %04x, rx status %04x, tx status " | ||
612 | "%02x, tx free %04x\n", inw(ioaddr+EL3_STATUS), | ||
613 | inw(ioaddr+RxStatus), inb(ioaddr+TxStatus), | ||
614 | inw(ioaddr+TxFree)); | ||
615 | EL3WINDOW(4); | ||
616 | printk(KERN_INFO " diagnostics: fifo %04x net %04x ethernet %04x" | ||
617 | " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06), | ||
618 | inw(ioaddr+0x08), inw(ioaddr+0x0a)); | ||
619 | EL3WINDOW(1); | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | Use this for commands that may take time to finish | ||
624 | */ | ||
625 | static void tc574_wait_for_completion(struct net_device *dev, int cmd) | ||
626 | { | ||
627 | int i = 1500; | ||
628 | outw(cmd, dev->base_addr + EL3_CMD); | ||
629 | while (--i > 0) | ||
630 | if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break; | ||
631 | if (i == 0) | ||
632 | printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n", dev->name, cmd); | ||
633 | } | ||
634 | |||
635 | /* Read a word from the EEPROM using the regular EEPROM access register. | ||
636 | Assume that we are in register window zero. | ||
637 | */ | ||
638 | static unsigned short read_eeprom(kio_addr_t ioaddr, int index) | ||
639 | { | ||
640 | int timer; | ||
641 | outw(EEPROM_Read + index, ioaddr + Wn0EepromCmd); | ||
642 | /* Pause for at least 162 usec for the read to take place. */ | ||
643 | for (timer = 1620; timer >= 0; timer--) { | ||
644 | if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0) | ||
645 | break; | ||
646 | } | ||
647 | return inw(ioaddr + Wn0EepromData); | ||
648 | } | ||
649 | |||
650 | /* MII transceiver control section. | ||
651 | Read and write the MII registers using software-generated serial | ||
652 | MDIO protocol. See the MII specifications or DP83840A data sheet | ||
653 | for details. | ||
654 | The maxium data clock rate is 2.5 Mhz. The timing is easily met by the | ||
655 | slow PC card interface. */ | ||
656 | |||
657 | #define MDIO_SHIFT_CLK 0x01 | ||
658 | #define MDIO_DIR_WRITE 0x04 | ||
659 | #define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE) | ||
660 | #define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE) | ||
661 | #define MDIO_DATA_READ 0x02 | ||
662 | #define MDIO_ENB_IN 0x00 | ||
663 | |||
664 | /* Generate the preamble required for initial synchronization and | ||
665 | a few older transceivers. */ | ||
666 | static void mdio_sync(kio_addr_t ioaddr, int bits) | ||
667 | { | ||
668 | kio_addr_t mdio_addr = ioaddr + Wn4_PhysicalMgmt; | ||
669 | |||
670 | /* Establish sync by sending at least 32 logic ones. */ | ||
671 | while (-- bits >= 0) { | ||
672 | outw(MDIO_DATA_WRITE1, mdio_addr); | ||
673 | outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); | ||
674 | } | ||
675 | } | ||
676 | |||
677 | static int mdio_read(kio_addr_t ioaddr, int phy_id, int location) | ||
678 | { | ||
679 | int i; | ||
680 | int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; | ||
681 | unsigned int retval = 0; | ||
682 | kio_addr_t mdio_addr = ioaddr + Wn4_PhysicalMgmt; | ||
683 | |||
684 | if (mii_preamble_required) | ||
685 | mdio_sync(ioaddr, 32); | ||
686 | |||
687 | /* Shift the read command bits out. */ | ||
688 | for (i = 14; i >= 0; i--) { | ||
689 | int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; | ||
690 | outw(dataval, mdio_addr); | ||
691 | outw(dataval | MDIO_SHIFT_CLK, mdio_addr); | ||
692 | } | ||
693 | /* Read the two transition, 16 data, and wire-idle bits. */ | ||
694 | for (i = 19; i > 0; i--) { | ||
695 | outw(MDIO_ENB_IN, mdio_addr); | ||
696 | retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); | ||
697 | outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); | ||
698 | } | ||
699 | return (retval>>1) & 0xffff; | ||
700 | } | ||
701 | |||
702 | static void mdio_write(kio_addr_t ioaddr, int phy_id, int location, int value) | ||
703 | { | ||
704 | int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value; | ||
705 | kio_addr_t mdio_addr = ioaddr + Wn4_PhysicalMgmt; | ||
706 | int i; | ||
707 | |||
708 | if (mii_preamble_required) | ||
709 | mdio_sync(ioaddr, 32); | ||
710 | |||
711 | /* Shift the command bits out. */ | ||
712 | for (i = 31; i >= 0; i--) { | ||
713 | int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; | ||
714 | outw(dataval, mdio_addr); | ||
715 | outw(dataval | MDIO_SHIFT_CLK, mdio_addr); | ||
716 | } | ||
717 | /* Leave the interface idle. */ | ||
718 | for (i = 1; i >= 0; i--) { | ||
719 | outw(MDIO_ENB_IN, mdio_addr); | ||
720 | outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); | ||
721 | } | ||
722 | |||
723 | return; | ||
724 | } | ||
725 | |||
726 | /* Reset and restore all of the 3c574 registers. */ | ||
727 | static void tc574_reset(struct net_device *dev) | ||
728 | { | ||
729 | struct el3_private *lp = netdev_priv(dev); | ||
730 | int i; | ||
731 | kio_addr_t ioaddr = dev->base_addr; | ||
732 | unsigned long flags; | ||
733 | |||
734 | tc574_wait_for_completion(dev, TotalReset|0x10); | ||
735 | |||
736 | spin_lock_irqsave(&lp->window_lock, flags); | ||
737 | /* Clear any transactions in progress. */ | ||
738 | outw(0, ioaddr + RunnerWrCtrl); | ||
739 | outw(0, ioaddr + RunnerRdCtrl); | ||
740 | |||
741 | /* Set the station address and mask. */ | ||
742 | EL3WINDOW(2); | ||
743 | for (i = 0; i < 6; i++) | ||
744 | outb(dev->dev_addr[i], ioaddr + i); | ||
745 | for (; i < 12; i+=2) | ||
746 | outw(0, ioaddr + i); | ||
747 | |||
748 | /* Reset config options */ | ||
749 | EL3WINDOW(3); | ||
750 | outb((dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl); | ||
751 | outl((lp->autoselect ? 0x01000000 : 0) | 0x0062001b, | ||
752 | ioaddr + Wn3_Config); | ||
753 | /* Roadrunner only: Turn on the MII transceiver. */ | ||
754 | outw(0x8040, ioaddr + Wn3_Options); | ||
755 | mdelay(1); | ||
756 | outw(0xc040, ioaddr + Wn3_Options); | ||
757 | EL3WINDOW(1); | ||
758 | spin_unlock_irqrestore(&lp->window_lock, flags); | ||
759 | |||
760 | tc574_wait_for_completion(dev, TxReset); | ||
761 | tc574_wait_for_completion(dev, RxReset); | ||
762 | mdelay(1); | ||
763 | spin_lock_irqsave(&lp->window_lock, flags); | ||
764 | EL3WINDOW(3); | ||
765 | outw(0x8040, ioaddr + Wn3_Options); | ||
766 | |||
767 | /* Switch to the stats window, and clear all stats by reading. */ | ||
768 | outw(StatsDisable, ioaddr + EL3_CMD); | ||
769 | EL3WINDOW(6); | ||
770 | for (i = 0; i < 10; i++) | ||
771 | inb(ioaddr + i); | ||
772 | inw(ioaddr + 10); | ||
773 | inw(ioaddr + 12); | ||
774 | EL3WINDOW(4); | ||
775 | inb(ioaddr + 12); | ||
776 | inb(ioaddr + 13); | ||
777 | |||
778 | /* .. enable any extra statistics bits.. */ | ||
779 | outw(0x0040, ioaddr + Wn4_NetDiag); | ||
780 | |||
781 | EL3WINDOW(1); | ||
782 | spin_unlock_irqrestore(&lp->window_lock, flags); | ||
783 | |||
784 | /* .. re-sync MII and re-fill what NWay is advertising. */ | ||
785 | mdio_sync(ioaddr, 32); | ||
786 | mdio_write(ioaddr, lp->phys, 4, lp->advertising); | ||
787 | if (!auto_polarity) { | ||
788 | /* works for TDK 78Q2120 series MII's */ | ||
789 | int i = mdio_read(ioaddr, lp->phys, 16) | 0x20; | ||
790 | mdio_write(ioaddr, lp->phys, 16, i); | ||
791 | } | ||
792 | |||
793 | spin_lock_irqsave(&lp->window_lock, flags); | ||
794 | /* Switch to register set 1 for normal use, just for TxFree. */ | ||
795 | set_rx_mode(dev); | ||
796 | spin_unlock_irqrestore(&lp->window_lock, flags); | ||
797 | outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ | ||
798 | outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ | ||
799 | outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ | ||
800 | /* Allow status bits to be seen. */ | ||
801 | outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD); | ||
802 | /* Ack all pending events, and set active indicator mask. */ | ||
803 | outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, | ||
804 | ioaddr + EL3_CMD); | ||
805 | outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull | ||
806 | | AdapterFailure | RxEarly, ioaddr + EL3_CMD); | ||
807 | } | ||
808 | |||
809 | static int el3_open(struct net_device *dev) | ||
810 | { | ||
811 | struct el3_private *lp = netdev_priv(dev); | ||
812 | dev_link_t *link = &lp->link; | ||
813 | |||
814 | if (!DEV_OK(link)) | ||
815 | return -ENODEV; | ||
816 | |||
817 | link->open++; | ||
818 | netif_start_queue(dev); | ||
819 | |||
820 | tc574_reset(dev); | ||
821 | lp->media.function = &media_check; | ||
822 | lp->media.data = (unsigned long) dev; | ||
823 | lp->media.expires = jiffies + HZ; | ||
824 | add_timer(&lp->media); | ||
825 | |||
826 | DEBUG(2, "%s: opened, status %4.4x.\n", | ||
827 | dev->name, inw(dev->base_addr + EL3_STATUS)); | ||
828 | |||
829 | return 0; | ||
830 | } | ||
831 | |||
832 | static void el3_tx_timeout(struct net_device *dev) | ||
833 | { | ||
834 | struct el3_private *lp = netdev_priv(dev); | ||
835 | kio_addr_t ioaddr = dev->base_addr; | ||
836 | |||
837 | printk(KERN_NOTICE "%s: Transmit timed out!\n", dev->name); | ||
838 | dump_status(dev); | ||
839 | lp->stats.tx_errors++; | ||
840 | dev->trans_start = jiffies; | ||
841 | /* Issue TX_RESET and TX_START commands. */ | ||
842 | tc574_wait_for_completion(dev, TxReset); | ||
843 | outw(TxEnable, ioaddr + EL3_CMD); | ||
844 | netif_wake_queue(dev); | ||
845 | } | ||
846 | |||
847 | static void pop_tx_status(struct net_device *dev) | ||
848 | { | ||
849 | struct el3_private *lp = netdev_priv(dev); | ||
850 | kio_addr_t ioaddr = dev->base_addr; | ||
851 | int i; | ||
852 | |||
853 | /* Clear the Tx status stack. */ | ||
854 | for (i = 32; i > 0; i--) { | ||
855 | u_char tx_status = inb(ioaddr + TxStatus); | ||
856 | if (!(tx_status & 0x84)) | ||
857 | break; | ||
858 | /* reset transmitter on jabber error or underrun */ | ||
859 | if (tx_status & 0x30) | ||
860 | tc574_wait_for_completion(dev, TxReset); | ||
861 | if (tx_status & 0x38) { | ||
862 | DEBUG(1, "%s: transmit error: status 0x%02x\n", | ||
863 | dev->name, tx_status); | ||
864 | outw(TxEnable, ioaddr + EL3_CMD); | ||
865 | lp->stats.tx_aborted_errors++; | ||
866 | } | ||
867 | outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */ | ||
868 | } | ||
869 | } | ||
870 | |||
871 | static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
872 | { | ||
873 | kio_addr_t ioaddr = dev->base_addr; | ||
874 | struct el3_private *lp = netdev_priv(dev); | ||
875 | unsigned long flags; | ||
876 | |||
877 | DEBUG(3, "%s: el3_start_xmit(length = %ld) called, " | ||
878 | "status %4.4x.\n", dev->name, (long)skb->len, | ||
879 | inw(ioaddr + EL3_STATUS)); | ||
880 | |||
881 | spin_lock_irqsave(&lp->window_lock, flags); | ||
882 | outw(skb->len, ioaddr + TX_FIFO); | ||
883 | outw(0, ioaddr + TX_FIFO); | ||
884 | outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2); | ||
885 | |||
886 | dev->trans_start = jiffies; | ||
887 | |||
888 | /* TxFree appears only in Window 1, not offset 0x1c. */ | ||
889 | if (inw(ioaddr + TxFree) <= 1536) { | ||
890 | netif_stop_queue(dev); | ||
891 | /* Interrupt us when the FIFO has room for max-sized packet. | ||
892 | The threshold is in units of dwords. */ | ||
893 | outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); | ||
894 | } | ||
895 | |||
896 | pop_tx_status(dev); | ||
897 | spin_unlock_irqrestore(&lp->window_lock, flags); | ||
898 | dev_kfree_skb(skb); | ||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | /* The EL3 interrupt handler. */ | ||
903 | static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
904 | { | ||
905 | struct net_device *dev = (struct net_device *) dev_id; | ||
906 | struct el3_private *lp = netdev_priv(dev); | ||
907 | kio_addr_t ioaddr; | ||
908 | unsigned status; | ||
909 | int work_budget = max_interrupt_work; | ||
910 | int handled = 0; | ||
911 | |||
912 | if (!netif_device_present(dev)) | ||
913 | return IRQ_NONE; | ||
914 | ioaddr = dev->base_addr; | ||
915 | |||
916 | DEBUG(3, "%s: interrupt, status %4.4x.\n", | ||
917 | dev->name, inw(ioaddr + EL3_STATUS)); | ||
918 | |||
919 | spin_lock(&lp->window_lock); | ||
920 | |||
921 | while ((status = inw(ioaddr + EL3_STATUS)) & | ||
922 | (IntLatch | RxComplete | RxEarly | StatsFull)) { | ||
923 | if (!netif_device_present(dev) || | ||
924 | ((status & 0xe000) != 0x2000)) { | ||
925 | DEBUG(1, "%s: Interrupt from dead card\n", dev->name); | ||
926 | break; | ||
927 | } | ||
928 | |||
929 | handled = 1; | ||
930 | |||
931 | if (status & RxComplete) | ||
932 | work_budget = el3_rx(dev, work_budget); | ||
933 | |||
934 | if (status & TxAvailable) { | ||
935 | DEBUG(3, " TX room bit was handled.\n"); | ||
936 | /* There's room in the FIFO for a full-sized packet. */ | ||
937 | outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); | ||
938 | netif_wake_queue(dev); | ||
939 | } | ||
940 | |||
941 | if (status & TxComplete) | ||
942 | pop_tx_status(dev); | ||
943 | |||
944 | if (status & (AdapterFailure | RxEarly | StatsFull)) { | ||
945 | /* Handle all uncommon interrupts. */ | ||
946 | if (status & StatsFull) | ||
947 | update_stats(dev); | ||
948 | if (status & RxEarly) { | ||
949 | work_budget = el3_rx(dev, work_budget); | ||
950 | outw(AckIntr | RxEarly, ioaddr + EL3_CMD); | ||
951 | } | ||
952 | if (status & AdapterFailure) { | ||
953 | u16 fifo_diag; | ||
954 | EL3WINDOW(4); | ||
955 | fifo_diag = inw(ioaddr + Wn4_FIFODiag); | ||
956 | EL3WINDOW(1); | ||
957 | printk(KERN_NOTICE "%s: adapter failure, FIFO diagnostic" | ||
958 | " register %04x.\n", dev->name, fifo_diag); | ||
959 | if (fifo_diag & 0x0400) { | ||
960 | /* Tx overrun */ | ||
961 | tc574_wait_for_completion(dev, TxReset); | ||
962 | outw(TxEnable, ioaddr + EL3_CMD); | ||
963 | } | ||
964 | if (fifo_diag & 0x2000) { | ||
965 | /* Rx underrun */ | ||
966 | tc574_wait_for_completion(dev, RxReset); | ||
967 | set_rx_mode(dev); | ||
968 | outw(RxEnable, ioaddr + EL3_CMD); | ||
969 | } | ||
970 | outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); | ||
971 | } | ||
972 | } | ||
973 | |||
974 | if (--work_budget < 0) { | ||
975 | DEBUG(0, "%s: Too much work in interrupt, " | ||
976 | "status %4.4x.\n", dev->name, status); | ||
977 | /* Clear all interrupts */ | ||
978 | outw(AckIntr | 0xFF, ioaddr + EL3_CMD); | ||
979 | break; | ||
980 | } | ||
981 | /* Acknowledge the IRQ. */ | ||
982 | outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); | ||
983 | } | ||
984 | |||
985 | DEBUG(3, "%s: exiting interrupt, status %4.4x.\n", | ||
986 | dev->name, inw(ioaddr + EL3_STATUS)); | ||
987 | |||
988 | spin_unlock(&lp->window_lock); | ||
989 | return IRQ_RETVAL(handled); | ||
990 | } | ||
991 | |||
992 | /* | ||
993 | This timer serves two purposes: to check for missed interrupts | ||
994 | (and as a last resort, poll the NIC for events), and to monitor | ||
995 | the MII, reporting changes in cable status. | ||
996 | */ | ||
997 | static void media_check(unsigned long arg) | ||
998 | { | ||
999 | struct net_device *dev = (struct net_device *) arg; | ||
1000 | struct el3_private *lp = netdev_priv(dev); | ||
1001 | kio_addr_t ioaddr = dev->base_addr; | ||
1002 | unsigned long flags; | ||
1003 | unsigned short /* cable, */ media, partner; | ||
1004 | |||
1005 | if (!netif_device_present(dev)) | ||
1006 | goto reschedule; | ||
1007 | |||
1008 | /* Check for pending interrupt with expired latency timer: with | ||
1009 | this, we can limp along even if the interrupt is blocked */ | ||
1010 | if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) { | ||
1011 | if (!lp->fast_poll) | ||
1012 | printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); | ||
1013 | el3_interrupt(dev->irq, lp, NULL); | ||
1014 | lp->fast_poll = HZ; | ||
1015 | } | ||
1016 | if (lp->fast_poll) { | ||
1017 | lp->fast_poll--; | ||
1018 | lp->media.expires = jiffies + 2*HZ/100; | ||
1019 | add_timer(&lp->media); | ||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | spin_lock_irqsave(&lp->window_lock, flags); | ||
1024 | EL3WINDOW(4); | ||
1025 | media = mdio_read(ioaddr, lp->phys, 1); | ||
1026 | partner = mdio_read(ioaddr, lp->phys, 5); | ||
1027 | EL3WINDOW(1); | ||
1028 | |||
1029 | if (media != lp->media_status) { | ||
1030 | if ((media ^ lp->media_status) & 0x0004) | ||
1031 | printk(KERN_INFO "%s: %s link beat\n", dev->name, | ||
1032 | (lp->media_status & 0x0004) ? "lost" : "found"); | ||
1033 | if ((media ^ lp->media_status) & 0x0020) { | ||
1034 | lp->partner = 0; | ||
1035 | if (lp->media_status & 0x0020) { | ||
1036 | printk(KERN_INFO "%s: autonegotiation restarted\n", | ||
1037 | dev->name); | ||
1038 | } else if (partner) { | ||
1039 | partner &= lp->advertising; | ||
1040 | lp->partner = partner; | ||
1041 | printk(KERN_INFO "%s: autonegotiation complete: " | ||
1042 | "%sbaseT-%cD selected\n", dev->name, | ||
1043 | ((partner & 0x0180) ? "100" : "10"), | ||
1044 | ((partner & 0x0140) ? 'F' : 'H')); | ||
1045 | } else { | ||
1046 | printk(KERN_INFO "%s: link partner did not autonegotiate\n", | ||
1047 | dev->name); | ||
1048 | } | ||
1049 | |||
1050 | EL3WINDOW(3); | ||
1051 | outb((partner & 0x0140 ? 0x20 : 0) | | ||
1052 | (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl); | ||
1053 | EL3WINDOW(1); | ||
1054 | |||
1055 | } | ||
1056 | if (media & 0x0010) | ||
1057 | printk(KERN_INFO "%s: remote fault detected\n", | ||
1058 | dev->name); | ||
1059 | if (media & 0x0002) | ||
1060 | printk(KERN_INFO "%s: jabber detected\n", dev->name); | ||
1061 | lp->media_status = media; | ||
1062 | } | ||
1063 | spin_unlock_irqrestore(&lp->window_lock, flags); | ||
1064 | |||
1065 | reschedule: | ||
1066 | lp->media.expires = jiffies + HZ; | ||
1067 | add_timer(&lp->media); | ||
1068 | } | ||
1069 | |||
1070 | static struct net_device_stats *el3_get_stats(struct net_device *dev) | ||
1071 | { | ||
1072 | struct el3_private *lp = netdev_priv(dev); | ||
1073 | |||
1074 | if (netif_device_present(dev)) { | ||
1075 | unsigned long flags; | ||
1076 | spin_lock_irqsave(&lp->window_lock, flags); | ||
1077 | update_stats(dev); | ||
1078 | spin_unlock_irqrestore(&lp->window_lock, flags); | ||
1079 | } | ||
1080 | return &lp->stats; | ||
1081 | } | ||
1082 | |||
1083 | /* Update statistics. | ||
1084 | Suprisingly this need not be run single-threaded, but it effectively is. | ||
1085 | The counters clear when read, so the adds must merely be atomic. | ||
1086 | */ | ||
1087 | static void update_stats(struct net_device *dev) | ||
1088 | { | ||
1089 | struct el3_private *lp = netdev_priv(dev); | ||
1090 | kio_addr_t ioaddr = dev->base_addr; | ||
1091 | u8 rx, tx, up; | ||
1092 | |||
1093 | DEBUG(2, "%s: updating the statistics.\n", dev->name); | ||
1094 | |||
1095 | if (inw(ioaddr+EL3_STATUS) == 0xffff) /* No card. */ | ||
1096 | return; | ||
1097 | |||
1098 | /* Unlike the 3c509 we need not turn off stats updates while reading. */ | ||
1099 | /* Switch to the stats window, and read everything. */ | ||
1100 | EL3WINDOW(6); | ||
1101 | lp->stats.tx_carrier_errors += inb(ioaddr + 0); | ||
1102 | lp->stats.tx_heartbeat_errors += inb(ioaddr + 1); | ||
1103 | /* Multiple collisions. */ inb(ioaddr + 2); | ||
1104 | lp->stats.collisions += inb(ioaddr + 3); | ||
1105 | lp->stats.tx_window_errors += inb(ioaddr + 4); | ||
1106 | lp->stats.rx_fifo_errors += inb(ioaddr + 5); | ||
1107 | lp->stats.tx_packets += inb(ioaddr + 6); | ||
1108 | up = inb(ioaddr + 9); | ||
1109 | lp->stats.tx_packets += (up&0x30) << 4; | ||
1110 | /* Rx packets */ inb(ioaddr + 7); | ||
1111 | /* Tx deferrals */ inb(ioaddr + 8); | ||
1112 | rx = inw(ioaddr + 10); | ||
1113 | tx = inw(ioaddr + 12); | ||
1114 | |||
1115 | EL3WINDOW(4); | ||
1116 | /* BadSSD */ inb(ioaddr + 12); | ||
1117 | up = inb(ioaddr + 13); | ||
1118 | |||
1119 | lp->stats.tx_bytes += tx + ((up & 0xf0) << 12); | ||
1120 | |||
1121 | EL3WINDOW(1); | ||
1122 | } | ||
1123 | |||
1124 | static int el3_rx(struct net_device *dev, int worklimit) | ||
1125 | { | ||
1126 | struct el3_private *lp = netdev_priv(dev); | ||
1127 | kio_addr_t ioaddr = dev->base_addr; | ||
1128 | short rx_status; | ||
1129 | |||
1130 | DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n", | ||
1131 | dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); | ||
1132 | while (!((rx_status = inw(ioaddr + RxStatus)) & 0x8000) && | ||
1133 | (--worklimit >= 0)) { | ||
1134 | if (rx_status & 0x4000) { /* Error, update stats. */ | ||
1135 | short error = rx_status & 0x3800; | ||
1136 | lp->stats.rx_errors++; | ||
1137 | switch (error) { | ||
1138 | case 0x0000: lp->stats.rx_over_errors++; break; | ||
1139 | case 0x0800: lp->stats.rx_length_errors++; break; | ||
1140 | case 0x1000: lp->stats.rx_frame_errors++; break; | ||
1141 | case 0x1800: lp->stats.rx_length_errors++; break; | ||
1142 | case 0x2000: lp->stats.rx_frame_errors++; break; | ||
1143 | case 0x2800: lp->stats.rx_crc_errors++; break; | ||
1144 | } | ||
1145 | } else { | ||
1146 | short pkt_len = rx_status & 0x7ff; | ||
1147 | struct sk_buff *skb; | ||
1148 | |||
1149 | skb = dev_alloc_skb(pkt_len+5); | ||
1150 | |||
1151 | DEBUG(3, " Receiving packet size %d status %4.4x.\n", | ||
1152 | pkt_len, rx_status); | ||
1153 | if (skb != NULL) { | ||
1154 | skb->dev = dev; | ||
1155 | skb_reserve(skb, 2); | ||
1156 | insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len), | ||
1157 | ((pkt_len+3)>>2)); | ||
1158 | skb->protocol = eth_type_trans(skb, dev); | ||
1159 | netif_rx(skb); | ||
1160 | dev->last_rx = jiffies; | ||
1161 | lp->stats.rx_packets++; | ||
1162 | lp->stats.rx_bytes += pkt_len; | ||
1163 | } else { | ||
1164 | DEBUG(1, "%s: couldn't allocate a sk_buff of" | ||
1165 | " size %d.\n", dev->name, pkt_len); | ||
1166 | lp->stats.rx_dropped++; | ||
1167 | } | ||
1168 | } | ||
1169 | tc574_wait_for_completion(dev, RxDiscard); | ||
1170 | } | ||
1171 | |||
1172 | return worklimit; | ||
1173 | } | ||
1174 | |||
1175 | static void netdev_get_drvinfo(struct net_device *dev, | ||
1176 | struct ethtool_drvinfo *info) | ||
1177 | { | ||
1178 | strcpy(info->driver, "3c574_cs"); | ||
1179 | } | ||
1180 | |||
1181 | static struct ethtool_ops netdev_ethtool_ops = { | ||
1182 | .get_drvinfo = netdev_get_drvinfo, | ||
1183 | }; | ||
1184 | |||
1185 | /* Provide ioctl() calls to examine the MII xcvr state. */ | ||
1186 | static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||
1187 | { | ||
1188 | struct el3_private *lp = netdev_priv(dev); | ||
1189 | kio_addr_t ioaddr = dev->base_addr; | ||
1190 | u16 *data = (u16 *)&rq->ifr_ifru; | ||
1191 | int phy = lp->phys & 0x1f; | ||
1192 | |||
1193 | DEBUG(2, "%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n", | ||
1194 | dev->name, rq->ifr_ifrn.ifrn_name, cmd, | ||
1195 | data[0], data[1], data[2], data[3]); | ||
1196 | |||
1197 | switch(cmd) { | ||
1198 | case SIOCGMIIPHY: /* Get the address of the PHY in use. */ | ||
1199 | data[0] = phy; | ||
1200 | case SIOCGMIIREG: /* Read the specified MII register. */ | ||
1201 | { | ||
1202 | int saved_window; | ||
1203 | unsigned long flags; | ||
1204 | |||
1205 | spin_lock_irqsave(&lp->window_lock, flags); | ||
1206 | saved_window = inw(ioaddr + EL3_CMD) >> 13; | ||
1207 | EL3WINDOW(4); | ||
1208 | data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f); | ||
1209 | EL3WINDOW(saved_window); | ||
1210 | spin_unlock_irqrestore(&lp->window_lock, flags); | ||
1211 | return 0; | ||
1212 | } | ||
1213 | case SIOCSMIIREG: /* Write the specified MII register */ | ||
1214 | { | ||
1215 | int saved_window; | ||
1216 | unsigned long flags; | ||
1217 | |||
1218 | if (!capable(CAP_NET_ADMIN)) | ||
1219 | return -EPERM; | ||
1220 | spin_lock_irqsave(&lp->window_lock, flags); | ||
1221 | saved_window = inw(ioaddr + EL3_CMD) >> 13; | ||
1222 | EL3WINDOW(4); | ||
1223 | mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]); | ||
1224 | EL3WINDOW(saved_window); | ||
1225 | spin_unlock_irqrestore(&lp->window_lock, flags); | ||
1226 | return 0; | ||
1227 | } | ||
1228 | default: | ||
1229 | return -EOPNOTSUPP; | ||
1230 | } | ||
1231 | } | ||
1232 | |||
1233 | /* The Odie chip has a 64 bin multicast filter, but the bit layout is not | ||
1234 | documented. Until it is we revert to receiving all multicast frames when | ||
1235 | any multicast reception is desired. | ||
1236 | Note: My other drivers emit a log message whenever promiscuous mode is | ||
1237 | entered to help detect password sniffers. This is less desirable on | ||
1238 | typical PC card machines, so we omit the message. | ||
1239 | */ | ||
1240 | |||
1241 | static void set_rx_mode(struct net_device *dev) | ||
1242 | { | ||
1243 | kio_addr_t ioaddr = dev->base_addr; | ||
1244 | |||
1245 | if (dev->flags & IFF_PROMISC) | ||
1246 | outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm, | ||
1247 | ioaddr + EL3_CMD); | ||
1248 | else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) | ||
1249 | outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); | ||
1250 | else | ||
1251 | outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); | ||
1252 | } | ||
1253 | |||
1254 | static int el3_close(struct net_device *dev) | ||
1255 | { | ||
1256 | kio_addr_t ioaddr = dev->base_addr; | ||
1257 | struct el3_private *lp = netdev_priv(dev); | ||
1258 | dev_link_t *link = &lp->link; | ||
1259 | |||
1260 | DEBUG(2, "%s: shutting down ethercard.\n", dev->name); | ||
1261 | |||
1262 | if (DEV_OK(link)) { | ||
1263 | unsigned long flags; | ||
1264 | |||
1265 | /* Turn off statistics ASAP. We update lp->stats below. */ | ||
1266 | outw(StatsDisable, ioaddr + EL3_CMD); | ||
1267 | |||
1268 | /* Disable the receiver and transmitter. */ | ||
1269 | outw(RxDisable, ioaddr + EL3_CMD); | ||
1270 | outw(TxDisable, ioaddr + EL3_CMD); | ||
1271 | |||
1272 | /* Note: Switching to window 0 may disable the IRQ. */ | ||
1273 | EL3WINDOW(0); | ||
1274 | spin_lock_irqsave(&lp->window_lock, flags); | ||
1275 | update_stats(dev); | ||
1276 | spin_unlock_irqrestore(&lp->window_lock, flags); | ||
1277 | } | ||
1278 | |||
1279 | link->open--; | ||
1280 | netif_stop_queue(dev); | ||
1281 | del_timer_sync(&lp->media); | ||
1282 | |||
1283 | return 0; | ||
1284 | } | ||
1285 | |||
1286 | static struct pcmcia_driver tc574_driver = { | ||
1287 | .owner = THIS_MODULE, | ||
1288 | .drv = { | ||
1289 | .name = "3c574_cs", | ||
1290 | }, | ||
1291 | .attach = tc574_attach, | ||
1292 | .detach = tc574_detach, | ||
1293 | }; | ||
1294 | |||
1295 | static int __init init_tc574(void) | ||
1296 | { | ||
1297 | return pcmcia_register_driver(&tc574_driver); | ||
1298 | } | ||
1299 | |||
1300 | static void __exit exit_tc574(void) | ||
1301 | { | ||
1302 | pcmcia_unregister_driver(&tc574_driver); | ||
1303 | BUG_ON(dev_list != NULL); | ||
1304 | } | ||
1305 | |||
1306 | module_init(init_tc574); | ||
1307 | module_exit(exit_tc574); | ||
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c new file mode 100644 index 000000000000..89abdda1d343 --- /dev/null +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -0,0 +1,1081 @@ | |||
1 | /*====================================================================== | ||
2 | |||
3 | A PCMCIA ethernet driver for the 3com 3c589 card. | ||
4 | |||
5 | Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net | ||
6 | |||
7 | 3c589_cs.c 1.162 2001/10/13 00:08:50 | ||
8 | |||
9 | The network driver code is based on Donald Becker's 3c589 code: | ||
10 | |||
11 | Written 1994 by Donald Becker. | ||
12 | Copyright 1993 United States Government as represented by the | ||
13 | Director, National Security Agency. This software may be used and | ||
14 | distributed according to the terms of the GNU General Public License, | ||
15 | incorporated herein by reference. | ||
16 | Donald Becker may be reached at becker@scyld.com | ||
17 | |||
18 | Updated for 2.5.x by Alan Cox <alan@redhat.com> | ||
19 | |||
20 | ======================================================================*/ | ||
21 | |||
22 | #define DRV_NAME "3c589_cs" | ||
23 | #define DRV_VERSION "1.162-ac" | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/ptrace.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/string.h> | ||
31 | #include <linux/timer.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/in.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/ethtool.h> | ||
36 | #include <linux/netdevice.h> | ||
37 | #include <linux/etherdevice.h> | ||
38 | #include <linux/skbuff.h> | ||
39 | #include <linux/if_arp.h> | ||
40 | #include <linux/ioport.h> | ||
41 | #include <linux/bitops.h> | ||
42 | |||
43 | #include <pcmcia/version.h> | ||
44 | #include <pcmcia/cs_types.h> | ||
45 | #include <pcmcia/cs.h> | ||
46 | #include <pcmcia/cistpl.h> | ||
47 | #include <pcmcia/cisreg.h> | ||
48 | #include <pcmcia/ciscode.h> | ||
49 | #include <pcmcia/ds.h> | ||
50 | |||
51 | #include <asm/uaccess.h> | ||
52 | #include <asm/io.h> | ||
53 | #include <asm/system.h> | ||
54 | |||
55 | /* To minimize the size of the driver source I only define operating | ||
56 | constants if they are used several times. You'll need the manual | ||
57 | if you want to understand driver details. */ | ||
58 | /* Offsets from base I/O address. */ | ||
59 | #define EL3_DATA 0x00 | ||
60 | #define EL3_TIMER 0x0a | ||
61 | #define EL3_CMD 0x0e | ||
62 | #define EL3_STATUS 0x0e | ||
63 | |||
64 | #define EEPROM_READ 0x0080 | ||
65 | #define EEPROM_BUSY 0x8000 | ||
66 | |||
67 | #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) | ||
68 | |||
69 | /* The top five bits written to EL3_CMD are a command, the lower | ||
70 | 11 bits are the parameter, if applicable. */ | ||
71 | enum c509cmd { | ||
72 | TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, | ||
73 | RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11, | ||
74 | TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, | ||
75 | FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, | ||
76 | SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, | ||
77 | SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11, | ||
78 | StatsDisable = 22<<11, StopCoax = 23<<11, | ||
79 | }; | ||
80 | |||
81 | enum c509status { | ||
82 | IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, | ||
83 | TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, | ||
84 | IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000 | ||
85 | }; | ||
86 | |||
87 | /* The SetRxFilter command accepts the following classes: */ | ||
88 | enum RxFilter { | ||
89 | RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 | ||
90 | }; | ||
91 | |||
92 | /* Register window 1 offsets, the window used in normal operation. */ | ||
93 | #define TX_FIFO 0x00 | ||
94 | #define RX_FIFO 0x00 | ||
95 | #define RX_STATUS 0x08 | ||
96 | #define TX_STATUS 0x0B | ||
97 | #define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */ | ||
98 | |||
99 | #define WN0_IRQ 0x08 /* Window 0: Set IRQ line in bits 12-15. */ | ||
100 | #define WN4_MEDIA 0x0A /* Window 4: Various transcvr/media bits. */ | ||
101 | #define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ | ||
102 | #define MEDIA_LED 0x0001 /* Enable link light on 3C589E cards. */ | ||
103 | |||
104 | /* Time in jiffies before concluding Tx hung */ | ||
105 | #define TX_TIMEOUT ((400*HZ)/1000) | ||
106 | |||
107 | struct el3_private { | ||
108 | dev_link_t link; | ||
109 | dev_node_t node; | ||
110 | struct net_device_stats stats; | ||
111 | /* For transceiver monitoring */ | ||
112 | struct timer_list media; | ||
113 | u16 media_status; | ||
114 | u16 fast_poll; | ||
115 | unsigned long last_irq; | ||
116 | spinlock_t lock; | ||
117 | }; | ||
118 | |||
119 | static char *if_names[] = { "auto", "10baseT", "10base2", "AUI" }; | ||
120 | |||
121 | /*====================================================================*/ | ||
122 | |||
123 | /* Module parameters */ | ||
124 | |||
125 | MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); | ||
126 | MODULE_DESCRIPTION("3Com 3c589 series PCMCIA ethernet driver"); | ||
127 | MODULE_LICENSE("GPL"); | ||
128 | |||
129 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) | ||
130 | |||
131 | /* Special hook for setting if_port when module is loaded */ | ||
132 | INT_MODULE_PARM(if_port, 0); | ||
133 | |||
134 | #ifdef PCMCIA_DEBUG | ||
135 | INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); | ||
136 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) | ||
137 | static char *version = | ||
138 | DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; | ||
139 | #else | ||
140 | #define DEBUG(n, args...) | ||
141 | #endif | ||
142 | |||
143 | /*====================================================================*/ | ||
144 | |||
145 | static void tc589_config(dev_link_t *link); | ||
146 | static void tc589_release(dev_link_t *link); | ||
147 | static int tc589_event(event_t event, int priority, | ||
148 | event_callback_args_t *args); | ||
149 | |||
150 | static u16 read_eeprom(kio_addr_t ioaddr, int index); | ||
151 | static void tc589_reset(struct net_device *dev); | ||
152 | static void media_check(unsigned long arg); | ||
153 | static int el3_config(struct net_device *dev, struct ifmap *map); | ||
154 | static int el3_open(struct net_device *dev); | ||
155 | static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
156 | static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs); | ||
157 | static void update_stats(struct net_device *dev); | ||
158 | static struct net_device_stats *el3_get_stats(struct net_device *dev); | ||
159 | static int el3_rx(struct net_device *dev); | ||
160 | static int el3_close(struct net_device *dev); | ||
161 | static void el3_tx_timeout(struct net_device *dev); | ||
162 | static void set_multicast_list(struct net_device *dev); | ||
163 | static struct ethtool_ops netdev_ethtool_ops; | ||
164 | |||
165 | static dev_info_t dev_info = "3c589_cs"; | ||
166 | |||
167 | static dev_link_t *tc589_attach(void); | ||
168 | static void tc589_detach(dev_link_t *); | ||
169 | |||
170 | static dev_link_t *dev_list; | ||
171 | |||
172 | /*====================================================================== | ||
173 | |||
174 | tc589_attach() creates an "instance" of the driver, allocating | ||
175 | local data structures for one device. The device is registered | ||
176 | with Card Services. | ||
177 | |||
178 | ======================================================================*/ | ||
179 | |||
180 | static dev_link_t *tc589_attach(void) | ||
181 | { | ||
182 | struct el3_private *lp; | ||
183 | client_reg_t client_reg; | ||
184 | dev_link_t *link; | ||
185 | struct net_device *dev; | ||
186 | int ret; | ||
187 | |||
188 | DEBUG(0, "3c589_attach()\n"); | ||
189 | |||
190 | /* Create new ethernet device */ | ||
191 | dev = alloc_etherdev(sizeof(struct el3_private)); | ||
192 | if (!dev) | ||
193 | return NULL; | ||
194 | lp = netdev_priv(dev); | ||
195 | link = &lp->link; | ||
196 | link->priv = dev; | ||
197 | |||
198 | spin_lock_init(&lp->lock); | ||
199 | link->io.NumPorts1 = 16; | ||
200 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
201 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
202 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
203 | link->irq.Handler = &el3_interrupt; | ||
204 | link->irq.Instance = dev; | ||
205 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
206 | link->conf.Vcc = 50; | ||
207 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
208 | link->conf.ConfigIndex = 1; | ||
209 | link->conf.Present = PRESENT_OPTION; | ||
210 | |||
211 | /* The EL3-specific entries in the device structure. */ | ||
212 | SET_MODULE_OWNER(dev); | ||
213 | dev->hard_start_xmit = &el3_start_xmit; | ||
214 | dev->set_config = &el3_config; | ||
215 | dev->get_stats = &el3_get_stats; | ||
216 | dev->set_multicast_list = &set_multicast_list; | ||
217 | dev->open = &el3_open; | ||
218 | dev->stop = &el3_close; | ||
219 | #ifdef HAVE_TX_TIMEOUT | ||
220 | dev->tx_timeout = el3_tx_timeout; | ||
221 | dev->watchdog_timeo = TX_TIMEOUT; | ||
222 | #endif | ||
223 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | ||
224 | |||
225 | /* Register with Card Services */ | ||
226 | link->next = dev_list; | ||
227 | dev_list = link; | ||
228 | client_reg.dev_info = &dev_info; | ||
229 | client_reg.EventMask = | ||
230 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
231 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
232 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
233 | client_reg.event_handler = &tc589_event; | ||
234 | client_reg.Version = 0x0210; | ||
235 | client_reg.event_callback_args.client_data = link; | ||
236 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
237 | if (ret != 0) { | ||
238 | cs_error(link->handle, RegisterClient, ret); | ||
239 | tc589_detach(link); | ||
240 | return NULL; | ||
241 | } | ||
242 | |||
243 | return link; | ||
244 | } /* tc589_attach */ | ||
245 | |||
246 | /*====================================================================== | ||
247 | |||
248 | This deletes a driver "instance". The device is de-registered | ||
249 | with Card Services. If it has been released, all local data | ||
250 | structures are freed. Otherwise, the structures will be freed | ||
251 | when the device is released. | ||
252 | |||
253 | ======================================================================*/ | ||
254 | |||
255 | static void tc589_detach(dev_link_t *link) | ||
256 | { | ||
257 | struct net_device *dev = link->priv; | ||
258 | dev_link_t **linkp; | ||
259 | |||
260 | DEBUG(0, "3c589_detach(0x%p)\n", link); | ||
261 | |||
262 | /* Locate device structure */ | ||
263 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
264 | if (*linkp == link) break; | ||
265 | if (*linkp == NULL) | ||
266 | return; | ||
267 | |||
268 | if (link->dev) | ||
269 | unregister_netdev(dev); | ||
270 | |||
271 | if (link->state & DEV_CONFIG) | ||
272 | tc589_release(link); | ||
273 | |||
274 | if (link->handle) | ||
275 | pcmcia_deregister_client(link->handle); | ||
276 | |||
277 | /* Unlink device structure, free bits */ | ||
278 | *linkp = link->next; | ||
279 | free_netdev(dev); | ||
280 | } /* tc589_detach */ | ||
281 | |||
282 | /*====================================================================== | ||
283 | |||
284 | tc589_config() is scheduled to run after a CARD_INSERTION event | ||
285 | is received, to configure the PCMCIA socket, and to make the | ||
286 | ethernet device available to the system. | ||
287 | |||
288 | ======================================================================*/ | ||
289 | |||
290 | #define CS_CHECK(fn, ret) \ | ||
291 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
292 | |||
293 | static void tc589_config(dev_link_t *link) | ||
294 | { | ||
295 | client_handle_t handle = link->handle; | ||
296 | struct net_device *dev = link->priv; | ||
297 | struct el3_private *lp = netdev_priv(dev); | ||
298 | tuple_t tuple; | ||
299 | cisparse_t parse; | ||
300 | u16 buf[32], *phys_addr; | ||
301 | int last_fn, last_ret, i, j, multi = 0, fifo; | ||
302 | kio_addr_t ioaddr; | ||
303 | char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; | ||
304 | |||
305 | DEBUG(0, "3c589_config(0x%p)\n", link); | ||
306 | |||
307 | phys_addr = (u16 *)dev->dev_addr; | ||
308 | tuple.Attributes = 0; | ||
309 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
310 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
311 | tuple.TupleData = (cisdata_t *)buf; | ||
312 | tuple.TupleDataMax = sizeof(buf); | ||
313 | tuple.TupleOffset = 0; | ||
314 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
315 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | ||
316 | link->conf.ConfigBase = parse.config.base; | ||
317 | link->conf.Present = parse.config.rmask[0]; | ||
318 | |||
319 | /* Is this a 3c562? */ | ||
320 | tuple.DesiredTuple = CISTPL_MANFID; | ||
321 | tuple.Attributes = TUPLE_RETURN_COMMON; | ||
322 | if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && | ||
323 | (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) { | ||
324 | if (le16_to_cpu(buf[0]) != MANFID_3COM) | ||
325 | printk(KERN_INFO "3c589_cs: hmmm, is this really a " | ||
326 | "3Com card??\n"); | ||
327 | multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562); | ||
328 | } | ||
329 | |||
330 | /* Configure card */ | ||
331 | link->state |= DEV_CONFIG; | ||
332 | |||
333 | /* For the 3c562, the base address must be xx00-xx7f */ | ||
334 | link->io.IOAddrLines = 16; | ||
335 | for (i = j = 0; j < 0x400; j += 0x10) { | ||
336 | if (multi && (j & 0x80)) continue; | ||
337 | link->io.BasePort1 = j ^ 0x300; | ||
338 | i = pcmcia_request_io(link->handle, &link->io); | ||
339 | if (i == CS_SUCCESS) break; | ||
340 | } | ||
341 | if (i != CS_SUCCESS) { | ||
342 | cs_error(link->handle, RequestIO, i); | ||
343 | goto failed; | ||
344 | } | ||
345 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | ||
346 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | ||
347 | |||
348 | dev->irq = link->irq.AssignedIRQ; | ||
349 | dev->base_addr = link->io.BasePort1; | ||
350 | ioaddr = dev->base_addr; | ||
351 | EL3WINDOW(0); | ||
352 | |||
353 | /* The 3c589 has an extra EEPROM for configuration info, including | ||
354 | the hardware address. The 3c562 puts the address in the CIS. */ | ||
355 | tuple.DesiredTuple = 0x88; | ||
356 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { | ||
357 | pcmcia_get_tuple_data(handle, &tuple); | ||
358 | for (i = 0; i < 3; i++) | ||
359 | phys_addr[i] = htons(buf[i]); | ||
360 | } else { | ||
361 | for (i = 0; i < 3; i++) | ||
362 | phys_addr[i] = htons(read_eeprom(ioaddr, i)); | ||
363 | if (phys_addr[0] == 0x6060) { | ||
364 | printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx" | ||
365 | "-0x%03lx\n", dev->base_addr, dev->base_addr+15); | ||
366 | goto failed; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | /* The address and resource configuration register aren't loaded from | ||
371 | the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */ | ||
372 | outw(0x3f00, ioaddr + 8); | ||
373 | fifo = inl(ioaddr); | ||
374 | |||
375 | /* The if_port symbol can be set when the module is loaded */ | ||
376 | if ((if_port >= 0) && (if_port <= 3)) | ||
377 | dev->if_port = if_port; | ||
378 | else | ||
379 | printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); | ||
380 | |||
381 | link->dev = &lp->node; | ||
382 | link->state &= ~DEV_CONFIG_PENDING; | ||
383 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
384 | |||
385 | if (register_netdev(dev) != 0) { | ||
386 | printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); | ||
387 | link->dev = NULL; | ||
388 | goto failed; | ||
389 | } | ||
390 | |||
391 | strcpy(lp->node.dev_name, dev->name); | ||
392 | |||
393 | printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, hw_addr ", | ||
394 | dev->name, (multi ? "562" : "589"), dev->base_addr, | ||
395 | dev->irq); | ||
396 | for (i = 0; i < 6; i++) | ||
397 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); | ||
398 | printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", | ||
399 | (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], | ||
400 | if_names[dev->if_port]); | ||
401 | return; | ||
402 | |||
403 | cs_failed: | ||
404 | cs_error(link->handle, last_fn, last_ret); | ||
405 | failed: | ||
406 | tc589_release(link); | ||
407 | return; | ||
408 | |||
409 | } /* tc589_config */ | ||
410 | |||
411 | /*====================================================================== | ||
412 | |||
413 | After a card is removed, tc589_release() will unregister the net | ||
414 | device, and release the PCMCIA configuration. If the device is | ||
415 | still open, this will be postponed until it is closed. | ||
416 | |||
417 | ======================================================================*/ | ||
418 | |||
419 | static void tc589_release(dev_link_t *link) | ||
420 | { | ||
421 | DEBUG(0, "3c589_release(0x%p)\n", link); | ||
422 | |||
423 | pcmcia_release_configuration(link->handle); | ||
424 | pcmcia_release_io(link->handle, &link->io); | ||
425 | pcmcia_release_irq(link->handle, &link->irq); | ||
426 | |||
427 | link->state &= ~DEV_CONFIG; | ||
428 | } | ||
429 | |||
430 | /*====================================================================== | ||
431 | |||
432 | The card status event handler. Mostly, this schedules other | ||
433 | stuff to run after an event is received. A CARD_REMOVAL event | ||
434 | also sets some flags to discourage the net drivers from trying | ||
435 | to talk to the card any more. | ||
436 | |||
437 | ======================================================================*/ | ||
438 | |||
439 | static int tc589_event(event_t event, int priority, | ||
440 | event_callback_args_t *args) | ||
441 | { | ||
442 | dev_link_t *link = args->client_data; | ||
443 | struct net_device *dev = link->priv; | ||
444 | |||
445 | DEBUG(1, "3c589_event(0x%06x)\n", event); | ||
446 | |||
447 | switch (event) { | ||
448 | case CS_EVENT_CARD_REMOVAL: | ||
449 | link->state &= ~DEV_PRESENT; | ||
450 | if (link->state & DEV_CONFIG) | ||
451 | netif_device_detach(dev); | ||
452 | break; | ||
453 | case CS_EVENT_CARD_INSERTION: | ||
454 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
455 | tc589_config(link); | ||
456 | break; | ||
457 | case CS_EVENT_PM_SUSPEND: | ||
458 | link->state |= DEV_SUSPEND; | ||
459 | /* Fall through... */ | ||
460 | case CS_EVENT_RESET_PHYSICAL: | ||
461 | if (link->state & DEV_CONFIG) { | ||
462 | if (link->open) | ||
463 | netif_device_detach(dev); | ||
464 | pcmcia_release_configuration(link->handle); | ||
465 | } | ||
466 | break; | ||
467 | case CS_EVENT_PM_RESUME: | ||
468 | link->state &= ~DEV_SUSPEND; | ||
469 | /* Fall through... */ | ||
470 | case CS_EVENT_CARD_RESET: | ||
471 | if (link->state & DEV_CONFIG) { | ||
472 | pcmcia_request_configuration(link->handle, &link->conf); | ||
473 | if (link->open) { | ||
474 | tc589_reset(dev); | ||
475 | netif_device_attach(dev); | ||
476 | } | ||
477 | } | ||
478 | break; | ||
479 | } | ||
480 | return 0; | ||
481 | } /* tc589_event */ | ||
482 | |||
483 | /*====================================================================*/ | ||
484 | |||
485 | /* | ||
486 | Use this for commands that may take time to finish | ||
487 | */ | ||
488 | static void tc589_wait_for_completion(struct net_device *dev, int cmd) | ||
489 | { | ||
490 | int i = 100; | ||
491 | outw(cmd, dev->base_addr + EL3_CMD); | ||
492 | while (--i > 0) | ||
493 | if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break; | ||
494 | if (i == 0) | ||
495 | printk(KERN_WARNING "%s: command 0x%04x did not complete!\n", | ||
496 | dev->name, cmd); | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | Read a word from the EEPROM using the regular EEPROM access register. | ||
501 | Assume that we are in register window zero. | ||
502 | */ | ||
503 | static u16 read_eeprom(kio_addr_t ioaddr, int index) | ||
504 | { | ||
505 | int i; | ||
506 | outw(EEPROM_READ + index, ioaddr + 10); | ||
507 | /* Reading the eeprom takes 162 us */ | ||
508 | for (i = 1620; i >= 0; i--) | ||
509 | if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0) | ||
510 | break; | ||
511 | return inw(ioaddr + 12); | ||
512 | } | ||
513 | |||
514 | /* | ||
515 | Set transceiver type, perhaps to something other than what the user | ||
516 | specified in dev->if_port. | ||
517 | */ | ||
518 | static void tc589_set_xcvr(struct net_device *dev, int if_port) | ||
519 | { | ||
520 | struct el3_private *lp = netdev_priv(dev); | ||
521 | kio_addr_t ioaddr = dev->base_addr; | ||
522 | |||
523 | EL3WINDOW(0); | ||
524 | switch (if_port) { | ||
525 | case 0: case 1: outw(0, ioaddr + 6); break; | ||
526 | case 2: outw(3<<14, ioaddr + 6); break; | ||
527 | case 3: outw(1<<14, ioaddr + 6); break; | ||
528 | } | ||
529 | /* On PCMCIA, this just turns on the LED */ | ||
530 | outw((if_port == 2) ? StartCoax : StopCoax, ioaddr + EL3_CMD); | ||
531 | /* 10baseT interface, enable link beat and jabber check. */ | ||
532 | EL3WINDOW(4); | ||
533 | outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), ioaddr + WN4_MEDIA); | ||
534 | EL3WINDOW(1); | ||
535 | if (if_port == 2) | ||
536 | lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000); | ||
537 | else | ||
538 | lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800); | ||
539 | } | ||
540 | |||
541 | static void dump_status(struct net_device *dev) | ||
542 | { | ||
543 | kio_addr_t ioaddr = dev->base_addr; | ||
544 | EL3WINDOW(1); | ||
545 | printk(KERN_INFO " irq status %04x, rx status %04x, tx status " | ||
546 | "%02x tx free %04x\n", inw(ioaddr+EL3_STATUS), | ||
547 | inw(ioaddr+RX_STATUS), inb(ioaddr+TX_STATUS), | ||
548 | inw(ioaddr+TX_FREE)); | ||
549 | EL3WINDOW(4); | ||
550 | printk(KERN_INFO " diagnostics: fifo %04x net %04x ethernet %04x" | ||
551 | " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06), | ||
552 | inw(ioaddr+0x08), inw(ioaddr+0x0a)); | ||
553 | EL3WINDOW(1); | ||
554 | } | ||
555 | |||
556 | /* Reset and restore all of the 3c589 registers. */ | ||
557 | static void tc589_reset(struct net_device *dev) | ||
558 | { | ||
559 | kio_addr_t ioaddr = dev->base_addr; | ||
560 | int i; | ||
561 | |||
562 | EL3WINDOW(0); | ||
563 | outw(0x0001, ioaddr + 4); /* Activate board. */ | ||
564 | outw(0x3f00, ioaddr + 8); /* Set the IRQ line. */ | ||
565 | |||
566 | /* Set the station address in window 2. */ | ||
567 | EL3WINDOW(2); | ||
568 | for (i = 0; i < 6; i++) | ||
569 | outb(dev->dev_addr[i], ioaddr + i); | ||
570 | |||
571 | tc589_set_xcvr(dev, dev->if_port); | ||
572 | |||
573 | /* Switch to the stats window, and clear all stats by reading. */ | ||
574 | outw(StatsDisable, ioaddr + EL3_CMD); | ||
575 | EL3WINDOW(6); | ||
576 | for (i = 0; i < 9; i++) | ||
577 | inb(ioaddr+i); | ||
578 | inw(ioaddr + 10); | ||
579 | inw(ioaddr + 12); | ||
580 | |||
581 | /* Switch to register set 1 for normal use. */ | ||
582 | EL3WINDOW(1); | ||
583 | |||
584 | /* Accept b-cast and phys addr only. */ | ||
585 | outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); | ||
586 | outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ | ||
587 | outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ | ||
588 | outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ | ||
589 | /* Allow status bits to be seen. */ | ||
590 | outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD); | ||
591 | /* Ack all pending events, and set active indicator mask. */ | ||
592 | outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, | ||
593 | ioaddr + EL3_CMD); | ||
594 | outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull | ||
595 | | AdapterFailure, ioaddr + EL3_CMD); | ||
596 | } | ||
597 | |||
598 | static void netdev_get_drvinfo(struct net_device *dev, | ||
599 | struct ethtool_drvinfo *info) | ||
600 | { | ||
601 | strcpy(info->driver, DRV_NAME); | ||
602 | strcpy(info->version, DRV_VERSION); | ||
603 | sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr); | ||
604 | } | ||
605 | |||
606 | #ifdef PCMCIA_DEBUG | ||
607 | static u32 netdev_get_msglevel(struct net_device *dev) | ||
608 | { | ||
609 | return pc_debug; | ||
610 | } | ||
611 | |||
612 | static void netdev_set_msglevel(struct net_device *dev, u32 level) | ||
613 | { | ||
614 | pc_debug = level; | ||
615 | } | ||
616 | #endif /* PCMCIA_DEBUG */ | ||
617 | |||
618 | static struct ethtool_ops netdev_ethtool_ops = { | ||
619 | .get_drvinfo = netdev_get_drvinfo, | ||
620 | #ifdef PCMCIA_DEBUG | ||
621 | .get_msglevel = netdev_get_msglevel, | ||
622 | .set_msglevel = netdev_set_msglevel, | ||
623 | #endif /* PCMCIA_DEBUG */ | ||
624 | }; | ||
625 | |||
626 | static int el3_config(struct net_device *dev, struct ifmap *map) | ||
627 | { | ||
628 | if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { | ||
629 | if (map->port <= 3) { | ||
630 | dev->if_port = map->port; | ||
631 | printk(KERN_INFO "%s: switched to %s port\n", | ||
632 | dev->name, if_names[dev->if_port]); | ||
633 | tc589_set_xcvr(dev, dev->if_port); | ||
634 | } else | ||
635 | return -EINVAL; | ||
636 | } | ||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | static int el3_open(struct net_device *dev) | ||
641 | { | ||
642 | struct el3_private *lp = netdev_priv(dev); | ||
643 | dev_link_t *link = &lp->link; | ||
644 | |||
645 | if (!DEV_OK(link)) | ||
646 | return -ENODEV; | ||
647 | |||
648 | link->open++; | ||
649 | netif_start_queue(dev); | ||
650 | |||
651 | tc589_reset(dev); | ||
652 | init_timer(&lp->media); | ||
653 | lp->media.function = &media_check; | ||
654 | lp->media.data = (unsigned long) dev; | ||
655 | lp->media.expires = jiffies + HZ; | ||
656 | add_timer(&lp->media); | ||
657 | |||
658 | DEBUG(1, "%s: opened, status %4.4x.\n", | ||
659 | dev->name, inw(dev->base_addr + EL3_STATUS)); | ||
660 | |||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static void el3_tx_timeout(struct net_device *dev) | ||
665 | { | ||
666 | struct el3_private *lp = netdev_priv(dev); | ||
667 | kio_addr_t ioaddr = dev->base_addr; | ||
668 | |||
669 | printk(KERN_WARNING "%s: Transmit timed out!\n", dev->name); | ||
670 | dump_status(dev); | ||
671 | lp->stats.tx_errors++; | ||
672 | dev->trans_start = jiffies; | ||
673 | /* Issue TX_RESET and TX_START commands. */ | ||
674 | tc589_wait_for_completion(dev, TxReset); | ||
675 | outw(TxEnable, ioaddr + EL3_CMD); | ||
676 | netif_wake_queue(dev); | ||
677 | } | ||
678 | |||
679 | static void pop_tx_status(struct net_device *dev) | ||
680 | { | ||
681 | struct el3_private *lp = netdev_priv(dev); | ||
682 | kio_addr_t ioaddr = dev->base_addr; | ||
683 | int i; | ||
684 | |||
685 | /* Clear the Tx status stack. */ | ||
686 | for (i = 32; i > 0; i--) { | ||
687 | u_char tx_status = inb(ioaddr + TX_STATUS); | ||
688 | if (!(tx_status & 0x84)) break; | ||
689 | /* reset transmitter on jabber error or underrun */ | ||
690 | if (tx_status & 0x30) | ||
691 | tc589_wait_for_completion(dev, TxReset); | ||
692 | if (tx_status & 0x38) { | ||
693 | DEBUG(1, "%s: transmit error: status 0x%02x\n", | ||
694 | dev->name, tx_status); | ||
695 | outw(TxEnable, ioaddr + EL3_CMD); | ||
696 | lp->stats.tx_aborted_errors++; | ||
697 | } | ||
698 | outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */ | ||
699 | } | ||
700 | } | ||
701 | |||
702 | static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
703 | { | ||
704 | kio_addr_t ioaddr = dev->base_addr; | ||
705 | struct el3_private *priv = netdev_priv(dev); | ||
706 | |||
707 | DEBUG(3, "%s: el3_start_xmit(length = %ld) called, " | ||
708 | "status %4.4x.\n", dev->name, (long)skb->len, | ||
709 | inw(ioaddr + EL3_STATUS)); | ||
710 | |||
711 | priv->stats.tx_bytes += skb->len; | ||
712 | |||
713 | /* Put out the doubleword header... */ | ||
714 | outw(skb->len, ioaddr + TX_FIFO); | ||
715 | outw(0x00, ioaddr + TX_FIFO); | ||
716 | /* ... and the packet rounded to a doubleword. */ | ||
717 | outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); | ||
718 | |||
719 | dev->trans_start = jiffies; | ||
720 | if (inw(ioaddr + TX_FREE) <= 1536) { | ||
721 | netif_stop_queue(dev); | ||
722 | /* Interrupt us when the FIFO has room for max-sized packet. */ | ||
723 | outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); | ||
724 | } | ||
725 | |||
726 | dev_kfree_skb(skb); | ||
727 | pop_tx_status(dev); | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | /* The EL3 interrupt handler. */ | ||
733 | static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
734 | { | ||
735 | struct net_device *dev = (struct net_device *) dev_id; | ||
736 | struct el3_private *lp = netdev_priv(dev); | ||
737 | kio_addr_t ioaddr; | ||
738 | __u16 status; | ||
739 | int i = 0, handled = 1; | ||
740 | |||
741 | if (!netif_device_present(dev)) | ||
742 | return IRQ_NONE; | ||
743 | |||
744 | ioaddr = dev->base_addr; | ||
745 | |||
746 | DEBUG(3, "%s: interrupt, status %4.4x.\n", | ||
747 | dev->name, inw(ioaddr + EL3_STATUS)); | ||
748 | |||
749 | spin_lock(&lp->lock); | ||
750 | while ((status = inw(ioaddr + EL3_STATUS)) & | ||
751 | (IntLatch | RxComplete | StatsFull)) { | ||
752 | if ((status & 0xe000) != 0x2000) { | ||
753 | DEBUG(1, "%s: interrupt from dead card\n", dev->name); | ||
754 | handled = 0; | ||
755 | break; | ||
756 | } | ||
757 | |||
758 | if (status & RxComplete) | ||
759 | el3_rx(dev); | ||
760 | |||
761 | if (status & TxAvailable) { | ||
762 | DEBUG(3, " TX room bit was handled.\n"); | ||
763 | /* There's room in the FIFO for a full-sized packet. */ | ||
764 | outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); | ||
765 | netif_wake_queue(dev); | ||
766 | } | ||
767 | |||
768 | if (status & TxComplete) | ||
769 | pop_tx_status(dev); | ||
770 | |||
771 | if (status & (AdapterFailure | RxEarly | StatsFull)) { | ||
772 | /* Handle all uncommon interrupts. */ | ||
773 | if (status & StatsFull) /* Empty statistics. */ | ||
774 | update_stats(dev); | ||
775 | if (status & RxEarly) { /* Rx early is unused. */ | ||
776 | el3_rx(dev); | ||
777 | outw(AckIntr | RxEarly, ioaddr + EL3_CMD); | ||
778 | } | ||
779 | if (status & AdapterFailure) { | ||
780 | u16 fifo_diag; | ||
781 | EL3WINDOW(4); | ||
782 | fifo_diag = inw(ioaddr + 4); | ||
783 | EL3WINDOW(1); | ||
784 | printk(KERN_WARNING "%s: adapter failure, FIFO diagnostic" | ||
785 | " register %04x.\n", dev->name, fifo_diag); | ||
786 | if (fifo_diag & 0x0400) { | ||
787 | /* Tx overrun */ | ||
788 | tc589_wait_for_completion(dev, TxReset); | ||
789 | outw(TxEnable, ioaddr + EL3_CMD); | ||
790 | } | ||
791 | if (fifo_diag & 0x2000) { | ||
792 | /* Rx underrun */ | ||
793 | tc589_wait_for_completion(dev, RxReset); | ||
794 | set_multicast_list(dev); | ||
795 | outw(RxEnable, ioaddr + EL3_CMD); | ||
796 | } | ||
797 | outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); | ||
798 | } | ||
799 | } | ||
800 | |||
801 | if (++i > 10) { | ||
802 | printk(KERN_ERR "%s: infinite loop in interrupt, " | ||
803 | "status %4.4x.\n", dev->name, status); | ||
804 | /* Clear all interrupts */ | ||
805 | outw(AckIntr | 0xFF, ioaddr + EL3_CMD); | ||
806 | break; | ||
807 | } | ||
808 | /* Acknowledge the IRQ. */ | ||
809 | outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); | ||
810 | } | ||
811 | |||
812 | lp->last_irq = jiffies; | ||
813 | spin_unlock(&lp->lock); | ||
814 | DEBUG(3, "%s: exiting interrupt, status %4.4x.\n", | ||
815 | dev->name, inw(ioaddr + EL3_STATUS)); | ||
816 | return IRQ_RETVAL(handled); | ||
817 | } | ||
818 | |||
819 | static void media_check(unsigned long arg) | ||
820 | { | ||
821 | struct net_device *dev = (struct net_device *)(arg); | ||
822 | struct el3_private *lp = netdev_priv(dev); | ||
823 | kio_addr_t ioaddr = dev->base_addr; | ||
824 | u16 media, errs; | ||
825 | unsigned long flags; | ||
826 | |||
827 | if (!netif_device_present(dev)) goto reschedule; | ||
828 | |||
829 | EL3WINDOW(1); | ||
830 | /* Check for pending interrupt with expired latency timer: with | ||
831 | this, we can limp along even if the interrupt is blocked */ | ||
832 | if ((inw(ioaddr + EL3_STATUS) & IntLatch) && | ||
833 | (inb(ioaddr + EL3_TIMER) == 0xff)) { | ||
834 | if (!lp->fast_poll) | ||
835 | printk(KERN_WARNING "%s: interrupt(s) dropped!\n", dev->name); | ||
836 | el3_interrupt(dev->irq, lp, NULL); | ||
837 | lp->fast_poll = HZ; | ||
838 | } | ||
839 | if (lp->fast_poll) { | ||
840 | lp->fast_poll--; | ||
841 | lp->media.expires = jiffies + HZ/100; | ||
842 | add_timer(&lp->media); | ||
843 | return; | ||
844 | } | ||
845 | |||
846 | /* lp->lock guards the EL3 window. Window should always be 1 except | ||
847 | when the lock is held */ | ||
848 | spin_lock_irqsave(&lp->lock, flags); | ||
849 | EL3WINDOW(4); | ||
850 | media = inw(ioaddr+WN4_MEDIA) & 0xc810; | ||
851 | |||
852 | /* Ignore collisions unless we've had no irq's recently */ | ||
853 | if (jiffies - lp->last_irq < HZ) { | ||
854 | media &= ~0x0010; | ||
855 | } else { | ||
856 | /* Try harder to detect carrier errors */ | ||
857 | EL3WINDOW(6); | ||
858 | outw(StatsDisable, ioaddr + EL3_CMD); | ||
859 | errs = inb(ioaddr + 0); | ||
860 | outw(StatsEnable, ioaddr + EL3_CMD); | ||
861 | lp->stats.tx_carrier_errors += errs; | ||
862 | if (errs || (lp->media_status & 0x0010)) media |= 0x0010; | ||
863 | } | ||
864 | |||
865 | if (media != lp->media_status) { | ||
866 | if ((media & lp->media_status & 0x8000) && | ||
867 | ((lp->media_status ^ media) & 0x0800)) | ||
868 | printk(KERN_INFO "%s: %s link beat\n", dev->name, | ||
869 | (lp->media_status & 0x0800 ? "lost" : "found")); | ||
870 | else if ((media & lp->media_status & 0x4000) && | ||
871 | ((lp->media_status ^ media) & 0x0010)) | ||
872 | printk(KERN_INFO "%s: coax cable %s\n", dev->name, | ||
873 | (lp->media_status & 0x0010 ? "ok" : "problem")); | ||
874 | if (dev->if_port == 0) { | ||
875 | if (media & 0x8000) { | ||
876 | if (media & 0x0800) | ||
877 | printk(KERN_INFO "%s: flipped to 10baseT\n", | ||
878 | dev->name); | ||
879 | else | ||
880 | tc589_set_xcvr(dev, 2); | ||
881 | } else if (media & 0x4000) { | ||
882 | if (media & 0x0010) | ||
883 | tc589_set_xcvr(dev, 1); | ||
884 | else | ||
885 | printk(KERN_INFO "%s: flipped to 10base2\n", | ||
886 | dev->name); | ||
887 | } | ||
888 | } | ||
889 | lp->media_status = media; | ||
890 | } | ||
891 | |||
892 | EL3WINDOW(1); | ||
893 | spin_unlock_irqrestore(&lp->lock, flags); | ||
894 | |||
895 | reschedule: | ||
896 | lp->media.expires = jiffies + HZ; | ||
897 | add_timer(&lp->media); | ||
898 | } | ||
899 | |||
900 | static struct net_device_stats *el3_get_stats(struct net_device *dev) | ||
901 | { | ||
902 | struct el3_private *lp = netdev_priv(dev); | ||
903 | unsigned long flags; | ||
904 | dev_link_t *link = &lp->link; | ||
905 | |||
906 | if (DEV_OK(link)) { | ||
907 | spin_lock_irqsave(&lp->lock, flags); | ||
908 | update_stats(dev); | ||
909 | spin_unlock_irqrestore(&lp->lock, flags); | ||
910 | } | ||
911 | return &lp->stats; | ||
912 | } | ||
913 | |||
914 | /* | ||
915 | Update statistics. We change to register window 6, so this should be run | ||
916 | single-threaded if the device is active. This is expected to be a rare | ||
917 | operation, and it's simpler for the rest of the driver to assume that | ||
918 | window 1 is always valid rather than use a special window-state variable. | ||
919 | |||
920 | Caller must hold the lock for this | ||
921 | */ | ||
922 | static void update_stats(struct net_device *dev) | ||
923 | { | ||
924 | struct el3_private *lp = netdev_priv(dev); | ||
925 | kio_addr_t ioaddr = dev->base_addr; | ||
926 | |||
927 | DEBUG(2, "%s: updating the statistics.\n", dev->name); | ||
928 | /* Turn off statistics updates while reading. */ | ||
929 | outw(StatsDisable, ioaddr + EL3_CMD); | ||
930 | /* Switch to the stats window, and read everything. */ | ||
931 | EL3WINDOW(6); | ||
932 | lp->stats.tx_carrier_errors += inb(ioaddr + 0); | ||
933 | lp->stats.tx_heartbeat_errors += inb(ioaddr + 1); | ||
934 | /* Multiple collisions. */ inb(ioaddr + 2); | ||
935 | lp->stats.collisions += inb(ioaddr + 3); | ||
936 | lp->stats.tx_window_errors += inb(ioaddr + 4); | ||
937 | lp->stats.rx_fifo_errors += inb(ioaddr + 5); | ||
938 | lp->stats.tx_packets += inb(ioaddr + 6); | ||
939 | /* Rx packets */ inb(ioaddr + 7); | ||
940 | /* Tx deferrals */ inb(ioaddr + 8); | ||
941 | /* Rx octets */ inw(ioaddr + 10); | ||
942 | /* Tx octets */ inw(ioaddr + 12); | ||
943 | |||
944 | /* Back to window 1, and turn statistics back on. */ | ||
945 | EL3WINDOW(1); | ||
946 | outw(StatsEnable, ioaddr + EL3_CMD); | ||
947 | } | ||
948 | |||
949 | static int el3_rx(struct net_device *dev) | ||
950 | { | ||
951 | struct el3_private *lp = netdev_priv(dev); | ||
952 | kio_addr_t ioaddr = dev->base_addr; | ||
953 | int worklimit = 32; | ||
954 | short rx_status; | ||
955 | |||
956 | DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n", | ||
957 | dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS)); | ||
958 | while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) && | ||
959 | (--worklimit >= 0)) { | ||
960 | if (rx_status & 0x4000) { /* Error, update stats. */ | ||
961 | short error = rx_status & 0x3800; | ||
962 | lp->stats.rx_errors++; | ||
963 | switch (error) { | ||
964 | case 0x0000: lp->stats.rx_over_errors++; break; | ||
965 | case 0x0800: lp->stats.rx_length_errors++; break; | ||
966 | case 0x1000: lp->stats.rx_frame_errors++; break; | ||
967 | case 0x1800: lp->stats.rx_length_errors++; break; | ||
968 | case 0x2000: lp->stats.rx_frame_errors++; break; | ||
969 | case 0x2800: lp->stats.rx_crc_errors++; break; | ||
970 | } | ||
971 | } else { | ||
972 | short pkt_len = rx_status & 0x7ff; | ||
973 | struct sk_buff *skb; | ||
974 | |||
975 | skb = dev_alloc_skb(pkt_len+5); | ||
976 | |||
977 | DEBUG(3, " Receiving packet size %d status %4.4x.\n", | ||
978 | pkt_len, rx_status); | ||
979 | if (skb != NULL) { | ||
980 | skb->dev = dev; | ||
981 | skb_reserve(skb, 2); | ||
982 | insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len), | ||
983 | (pkt_len+3)>>2); | ||
984 | skb->protocol = eth_type_trans(skb, dev); | ||
985 | netif_rx(skb); | ||
986 | dev->last_rx = jiffies; | ||
987 | lp->stats.rx_packets++; | ||
988 | lp->stats.rx_bytes += pkt_len; | ||
989 | } else { | ||
990 | DEBUG(1, "%s: couldn't allocate a sk_buff of" | ||
991 | " size %d.\n", dev->name, pkt_len); | ||
992 | lp->stats.rx_dropped++; | ||
993 | } | ||
994 | } | ||
995 | /* Pop the top of the Rx FIFO */ | ||
996 | tc589_wait_for_completion(dev, RxDiscard); | ||
997 | } | ||
998 | if (worklimit == 0) | ||
999 | printk(KERN_WARNING "%s: too much work in el3_rx!\n", dev->name); | ||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
1003 | static void set_multicast_list(struct net_device *dev) | ||
1004 | { | ||
1005 | struct el3_private *lp = netdev_priv(dev); | ||
1006 | dev_link_t *link = &lp->link; | ||
1007 | kio_addr_t ioaddr = dev->base_addr; | ||
1008 | u16 opts = SetRxFilter | RxStation | RxBroadcast; | ||
1009 | |||
1010 | if (!(DEV_OK(link))) return; | ||
1011 | if (dev->flags & IFF_PROMISC) | ||
1012 | opts |= RxMulticast | RxProm; | ||
1013 | else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) | ||
1014 | opts |= RxMulticast; | ||
1015 | outw(opts, ioaddr + EL3_CMD); | ||
1016 | } | ||
1017 | |||
1018 | static int el3_close(struct net_device *dev) | ||
1019 | { | ||
1020 | struct el3_private *lp = netdev_priv(dev); | ||
1021 | dev_link_t *link = &lp->link; | ||
1022 | kio_addr_t ioaddr = dev->base_addr; | ||
1023 | |||
1024 | DEBUG(1, "%s: shutting down ethercard.\n", dev->name); | ||
1025 | |||
1026 | if (DEV_OK(link)) { | ||
1027 | /* Turn off statistics ASAP. We update lp->stats below. */ | ||
1028 | outw(StatsDisable, ioaddr + EL3_CMD); | ||
1029 | |||
1030 | /* Disable the receiver and transmitter. */ | ||
1031 | outw(RxDisable, ioaddr + EL3_CMD); | ||
1032 | outw(TxDisable, ioaddr + EL3_CMD); | ||
1033 | |||
1034 | if (dev->if_port == 2) | ||
1035 | /* Turn off thinnet power. Green! */ | ||
1036 | outw(StopCoax, ioaddr + EL3_CMD); | ||
1037 | else if (dev->if_port == 1) { | ||
1038 | /* Disable link beat and jabber */ | ||
1039 | EL3WINDOW(4); | ||
1040 | outw(0, ioaddr + WN4_MEDIA); | ||
1041 | } | ||
1042 | |||
1043 | /* Switching back to window 0 disables the IRQ. */ | ||
1044 | EL3WINDOW(0); | ||
1045 | /* But we explicitly zero the IRQ line select anyway. */ | ||
1046 | outw(0x0f00, ioaddr + WN0_IRQ); | ||
1047 | |||
1048 | /* Check if the card still exists */ | ||
1049 | if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000) | ||
1050 | update_stats(dev); | ||
1051 | } | ||
1052 | |||
1053 | link->open--; | ||
1054 | netif_stop_queue(dev); | ||
1055 | del_timer_sync(&lp->media); | ||
1056 | |||
1057 | return 0; | ||
1058 | } | ||
1059 | |||
1060 | static struct pcmcia_driver tc589_driver = { | ||
1061 | .owner = THIS_MODULE, | ||
1062 | .drv = { | ||
1063 | .name = "3c589_cs", | ||
1064 | }, | ||
1065 | .attach = tc589_attach, | ||
1066 | .detach = tc589_detach, | ||
1067 | }; | ||
1068 | |||
1069 | static int __init init_tc589(void) | ||
1070 | { | ||
1071 | return pcmcia_register_driver(&tc589_driver); | ||
1072 | } | ||
1073 | |||
1074 | static void __exit exit_tc589(void) | ||
1075 | { | ||
1076 | pcmcia_unregister_driver(&tc589_driver); | ||
1077 | BUG_ON(dev_list != NULL); | ||
1078 | } | ||
1079 | |||
1080 | module_init(init_tc589); | ||
1081 | module_exit(exit_tc589); | ||
diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig new file mode 100644 index 000000000000..74f862001247 --- /dev/null +++ b/drivers/net/pcmcia/Kconfig | |||
@@ -0,0 +1,132 @@ | |||
1 | # | ||
2 | # PCMCIA Network device configuration | ||
3 | # | ||
4 | |||
5 | menu "PCMCIA network device support" | ||
6 | depends on NETDEVICES && PCMCIA!=n | ||
7 | |||
8 | config NET_PCMCIA | ||
9 | bool "PCMCIA network device support" | ||
10 | ---help--- | ||
11 | Say Y if you would like to include support for any PCMCIA or CardBus | ||
12 | network adapters, then say Y to the driver for your particular card | ||
13 | below. PCMCIA- or PC-cards are credit-card size devices often used | ||
14 | with laptops computers; CardBus is the newer and faster version of | ||
15 | PCMCIA. | ||
16 | |||
17 | To use your PC-cards, you will need supporting software from David | ||
18 | Hinds' pcmcia-cs package (see the file <file:Documentation/Changes> | ||
19 | for location). You also want to check out the PCMCIA-HOWTO, | ||
20 | available from <http://www.tldp.org/docs.html#howto>. | ||
21 | |||
22 | If unsure, say N. | ||
23 | |||
24 | config PCMCIA_3C589 | ||
25 | tristate "3Com 3c589 PCMCIA support" | ||
26 | depends on NET_PCMCIA && PCMCIA | ||
27 | help | ||
28 | Say Y here if you intend to attach a 3Com 3c589 or compatible PCMCIA | ||
29 | (PC-card) Ethernet card to your computer. | ||
30 | |||
31 | To compile this driver as a module, choose M here: the module will be | ||
32 | called 3c589_cs. If unsure, say N. | ||
33 | |||
34 | config PCMCIA_3C574 | ||
35 | tristate "3Com 3c574 PCMCIA support" | ||
36 | depends on NET_PCMCIA && PCMCIA | ||
37 | help | ||
38 | Say Y here if you intend to attach a 3Com 3c574 or compatible PCMCIA | ||
39 | (PC-card) Fast Ethernet card to your computer. | ||
40 | |||
41 | To compile this driver as a module, choose M here: the module will be | ||
42 | called 3c574_cs. If unsure, say N. | ||
43 | |||
44 | config PCMCIA_FMVJ18X | ||
45 | tristate "Fujitsu FMV-J18x PCMCIA support" | ||
46 | depends on NET_PCMCIA && PCMCIA | ||
47 | select CRC32 | ||
48 | help | ||
49 | Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible | ||
50 | PCMCIA (PC-card) Ethernet card to your computer. | ||
51 | |||
52 | To compile this driver as a module, choose M here: the module will be | ||
53 | called fmvj18x_cs. If unsure, say N. | ||
54 | |||
55 | config PCMCIA_PCNET | ||
56 | tristate "NE2000 compatible PCMCIA support" | ||
57 | depends on NET_PCMCIA && PCMCIA | ||
58 | select CRC32 | ||
59 | help | ||
60 | Say Y here if you intend to attach an NE2000 compatible PCMCIA | ||
61 | (PC-card) Ethernet or Fast Ethernet card to your computer. | ||
62 | |||
63 | To compile this driver as a module, choose M here: the module will be | ||
64 | called pcnet_cs. If unsure, say N. | ||
65 | |||
66 | config PCMCIA_NMCLAN | ||
67 | tristate "New Media PCMCIA support" | ||
68 | depends on NET_PCMCIA && PCMCIA | ||
69 | help | ||
70 | Say Y here if you intend to attach a New Media Ethernet or LiveWire | ||
71 | PCMCIA (PC-card) Ethernet card to your computer. | ||
72 | |||
73 | To compile this driver as a module, choose M here: the module will be | ||
74 | called nmclan_cs. If unsure, say N. | ||
75 | |||
76 | config PCMCIA_SMC91C92 | ||
77 | tristate "SMC 91Cxx PCMCIA support" | ||
78 | depends on NET_PCMCIA && PCMCIA | ||
79 | select CRC32 | ||
80 | select MII | ||
81 | help | ||
82 | Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA | ||
83 | (PC-card) Ethernet or Fast Ethernet card to your computer. | ||
84 | |||
85 | To compile this driver as a module, choose M here: the module will be | ||
86 | called smc91c92_cs. If unsure, say N. | ||
87 | |||
88 | config PCMCIA_XIRC2PS | ||
89 | tristate "Xircom 16-bit PCMCIA support" | ||
90 | depends on NET_PCMCIA && PCMCIA | ||
91 | help | ||
92 | Say Y here if you intend to attach a Xircom 16-bit PCMCIA (PC-card) | ||
93 | Ethernet or Fast Ethernet card to your computer. | ||
94 | |||
95 | To compile this driver as a module, choose M here: the module will be | ||
96 | called xirc2ps_cs. If unsure, say N. | ||
97 | |||
98 | config PCMCIA_AXNET | ||
99 | tristate "Asix AX88190 PCMCIA support" | ||
100 | depends on NET_PCMCIA && PCMCIA | ||
101 | ---help--- | ||
102 | Say Y here if you intend to attach an Asix AX88190-based PCMCIA | ||
103 | (PC-card) Fast Ethernet card to your computer. These cards are | ||
104 | nearly NE2000 compatible but need a separate driver due to a few | ||
105 | misfeatures. | ||
106 | |||
107 | To compile this driver as a module, choose M here: the module will be | ||
108 | called axnet_cs. If unsure, say N. | ||
109 | |||
110 | config ARCNET_COM20020_CS | ||
111 | tristate "COM20020 ARCnet PCMCIA support" | ||
112 | depends on NET_PCMCIA && ARCNET_COM20020 && PCMCIA | ||
113 | help | ||
114 | Say Y here if you intend to attach this type of ARCnet PCMCIA card | ||
115 | to your computer. | ||
116 | |||
117 | To compile this driver as a module, choose M here: the module will be | ||
118 | called com20020_cs. If unsure, say N. | ||
119 | |||
120 | config PCMCIA_IBMTR | ||
121 | tristate "IBM PCMCIA tokenring adapter support" | ||
122 | depends on NET_PCMCIA && IBMTR!=y && TR && PCMCIA && !64BIT | ||
123 | help | ||
124 | Say Y here if you intend to attach this type of Token Ring PCMCIA | ||
125 | card to your computer. You then also need to say Y to "Token Ring | ||
126 | driver support". | ||
127 | |||
128 | To compile this driver as a module, choose M here: the module will be | ||
129 | called ibmtr_cs. | ||
130 | |||
131 | endmenu | ||
132 | |||
diff --git a/drivers/net/pcmcia/Makefile b/drivers/net/pcmcia/Makefile new file mode 100644 index 000000000000..87d2d99f4c14 --- /dev/null +++ b/drivers/net/pcmcia/Makefile | |||
@@ -0,0 +1,16 @@ | |||
1 | # | ||
2 | # Makefile for the Linux PCMCIA network device drivers. | ||
3 | # | ||
4 | |||
5 | # 16-bit client drivers | ||
6 | obj-$(CONFIG_PCMCIA_3C589) += 3c589_cs.o | ||
7 | obj-$(CONFIG_PCMCIA_3C574) += 3c574_cs.o | ||
8 | obj-$(CONFIG_PCMCIA_FMVJ18X) += fmvj18x_cs.o | ||
9 | obj-$(CONFIG_PCMCIA_NMCLAN) += nmclan_cs.o | ||
10 | obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o | ||
11 | obj-$(CONFIG_PCMCIA_SMC91C92) += smc91c92_cs.o | ||
12 | obj-$(CONFIG_PCMCIA_XIRC2PS) += xirc2ps_cs.o | ||
13 | obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o | ||
14 | obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o | ||
15 | |||
16 | obj-$(CONFIG_PCMCIA_IBMTR) += ibmtr_cs.o | ||
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c new file mode 100644 index 000000000000..853b586e481a --- /dev/null +++ b/drivers/net/pcmcia/axnet_cs.c | |||
@@ -0,0 +1,1864 @@ | |||
1 | /*====================================================================== | ||
2 | |||
3 | A PCMCIA ethernet driver for Asix AX88190-based cards | ||
4 | |||
5 | The Asix AX88190 is a NS8390-derived chipset with a few nasty | ||
6 | idiosyncracies that make it very inconvenient to support with a | ||
7 | standard 8390 driver. This driver is based on pcnet_cs, with the | ||
8 | tweaked 8390 code grafted on the end. Much of what I did was to | ||
9 | clean up and update a similar driver supplied by Asix, which was | ||
10 | adapted by William Lee, william@asix.com.tw. | ||
11 | |||
12 | Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net | ||
13 | |||
14 | axnet_cs.c 1.28 2002/06/29 06:27:37 | ||
15 | |||
16 | The network driver code is based on Donald Becker's NE2000 code: | ||
17 | |||
18 | Written 1992,1993 by Donald Becker. | ||
19 | Copyright 1993 United States Government as represented by the | ||
20 | Director, National Security Agency. This software may be used and | ||
21 | distributed according to the terms of the GNU General Public License, | ||
22 | incorporated herein by reference. | ||
23 | Donald Becker may be reached at becker@scyld.com | ||
24 | |||
25 | ======================================================================*/ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/ptrace.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/string.h> | ||
33 | #include <linux/timer.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | #include <linux/ethtool.h> | ||
37 | #include <linux/netdevice.h> | ||
38 | #include "../8390.h" | ||
39 | |||
40 | #include <pcmcia/version.h> | ||
41 | #include <pcmcia/cs_types.h> | ||
42 | #include <pcmcia/cs.h> | ||
43 | #include <pcmcia/cistpl.h> | ||
44 | #include <pcmcia/ciscode.h> | ||
45 | #include <pcmcia/ds.h> | ||
46 | #include <pcmcia/cisreg.h> | ||
47 | |||
48 | #include <asm/io.h> | ||
49 | #include <asm/system.h> | ||
50 | #include <asm/byteorder.h> | ||
51 | #include <asm/uaccess.h> | ||
52 | |||
53 | #define AXNET_CMD 0x00 | ||
54 | #define AXNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */ | ||
55 | #define AXNET_RESET 0x1f /* Issue a read to reset, a write to clear. */ | ||
56 | #define AXNET_MII_EEP 0x14 /* Offset of MII access port */ | ||
57 | #define AXNET_TEST 0x15 /* Offset of TEST Register port */ | ||
58 | #define AXNET_GPIO 0x17 /* Offset of General Purpose Register Port */ | ||
59 | |||
60 | #define AXNET_START_PG 0x40 /* First page of TX buffer */ | ||
61 | #define AXNET_STOP_PG 0x80 /* Last page +1 of RX ring */ | ||
62 | |||
63 | #define AXNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */ | ||
64 | |||
65 | #define IS_AX88190 0x0001 | ||
66 | #define IS_AX88790 0x0002 | ||
67 | |||
68 | /*====================================================================*/ | ||
69 | |||
70 | /* Module parameters */ | ||
71 | |||
72 | MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); | ||
73 | MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver"); | ||
74 | MODULE_LICENSE("GPL"); | ||
75 | |||
76 | #ifdef PCMCIA_DEBUG | ||
77 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) | ||
78 | |||
79 | INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); | ||
80 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) | ||
81 | static char *version = | ||
82 | "axnet_cs.c 1.28 2002/06/29 06:27:37 (David Hinds)"; | ||
83 | #else | ||
84 | #define DEBUG(n, args...) | ||
85 | #endif | ||
86 | |||
87 | /*====================================================================*/ | ||
88 | |||
89 | static void axnet_config(dev_link_t *link); | ||
90 | static void axnet_release(dev_link_t *link); | ||
91 | static int axnet_event(event_t event, int priority, | ||
92 | event_callback_args_t *args); | ||
93 | static int axnet_open(struct net_device *dev); | ||
94 | static int axnet_close(struct net_device *dev); | ||
95 | static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
96 | static struct ethtool_ops netdev_ethtool_ops; | ||
97 | static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs); | ||
98 | static void ei_watchdog(u_long arg); | ||
99 | static void axnet_reset_8390(struct net_device *dev); | ||
100 | |||
101 | static int mdio_read(kio_addr_t addr, int phy_id, int loc); | ||
102 | static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value); | ||
103 | |||
104 | static void get_8390_hdr(struct net_device *, | ||
105 | struct e8390_pkt_hdr *, int); | ||
106 | static void block_input(struct net_device *dev, int count, | ||
107 | struct sk_buff *skb, int ring_offset); | ||
108 | static void block_output(struct net_device *dev, int count, | ||
109 | const u_char *buf, const int start_page); | ||
110 | |||
111 | static dev_link_t *axnet_attach(void); | ||
112 | static void axnet_detach(dev_link_t *); | ||
113 | |||
114 | static dev_info_t dev_info = "axnet_cs"; | ||
115 | static dev_link_t *dev_list; | ||
116 | |||
117 | static void axdev_setup(struct net_device *dev); | ||
118 | static void AX88190_init(struct net_device *dev, int startp); | ||
119 | static int ax_open(struct net_device *dev); | ||
120 | static int ax_close(struct net_device *dev); | ||
121 | static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs *regs); | ||
122 | |||
123 | /*====================================================================*/ | ||
124 | |||
125 | typedef struct axnet_dev_t { | ||
126 | dev_link_t link; | ||
127 | dev_node_t node; | ||
128 | caddr_t base; | ||
129 | struct timer_list watchdog; | ||
130 | int stale, fast_poll; | ||
131 | u_short link_status; | ||
132 | u_char duplex_flag; | ||
133 | int phy_id; | ||
134 | int flags; | ||
135 | } axnet_dev_t; | ||
136 | |||
137 | static inline axnet_dev_t *PRIV(struct net_device *dev) | ||
138 | { | ||
139 | void *p = (char *)netdev_priv(dev) + sizeof(struct ei_device); | ||
140 | return p; | ||
141 | } | ||
142 | |||
143 | /*====================================================================== | ||
144 | |||
145 | axnet_attach() creates an "instance" of the driver, allocating | ||
146 | local data structures for one device. The device is registered | ||
147 | with Card Services. | ||
148 | |||
149 | ======================================================================*/ | ||
150 | |||
151 | static dev_link_t *axnet_attach(void) | ||
152 | { | ||
153 | axnet_dev_t *info; | ||
154 | dev_link_t *link; | ||
155 | struct net_device *dev; | ||
156 | client_reg_t client_reg; | ||
157 | int ret; | ||
158 | |||
159 | DEBUG(0, "axnet_attach()\n"); | ||
160 | |||
161 | dev = alloc_netdev(sizeof(struct ei_device) + sizeof(axnet_dev_t), | ||
162 | "eth%d", axdev_setup); | ||
163 | |||
164 | if (!dev) | ||
165 | return NULL; | ||
166 | |||
167 | info = PRIV(dev); | ||
168 | link = &info->link; | ||
169 | link->priv = dev; | ||
170 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | ||
171 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
172 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
173 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
174 | |||
175 | dev->open = &axnet_open; | ||
176 | dev->stop = &axnet_close; | ||
177 | dev->do_ioctl = &axnet_ioctl; | ||
178 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | ||
179 | |||
180 | /* Register with Card Services */ | ||
181 | link->next = dev_list; | ||
182 | dev_list = link; | ||
183 | client_reg.dev_info = &dev_info; | ||
184 | client_reg.EventMask = | ||
185 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
186 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
187 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
188 | client_reg.event_handler = &axnet_event; | ||
189 | client_reg.Version = 0x0210; | ||
190 | client_reg.event_callback_args.client_data = link; | ||
191 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
192 | if (ret != CS_SUCCESS) { | ||
193 | cs_error(link->handle, RegisterClient, ret); | ||
194 | axnet_detach(link); | ||
195 | return NULL; | ||
196 | } | ||
197 | |||
198 | return link; | ||
199 | } /* axnet_attach */ | ||
200 | |||
201 | /*====================================================================== | ||
202 | |||
203 | This deletes a driver "instance". The device is de-registered | ||
204 | with Card Services. If it has been released, all local data | ||
205 | structures are freed. Otherwise, the structures will be freed | ||
206 | when the device is released. | ||
207 | |||
208 | ======================================================================*/ | ||
209 | |||
210 | static void axnet_detach(dev_link_t *link) | ||
211 | { | ||
212 | struct net_device *dev = link->priv; | ||
213 | dev_link_t **linkp; | ||
214 | |||
215 | DEBUG(0, "axnet_detach(0x%p)\n", link); | ||
216 | |||
217 | /* Locate device structure */ | ||
218 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
219 | if (*linkp == link) break; | ||
220 | if (*linkp == NULL) | ||
221 | return; | ||
222 | |||
223 | if (link->dev) | ||
224 | unregister_netdev(dev); | ||
225 | |||
226 | if (link->state & DEV_CONFIG) | ||
227 | axnet_release(link); | ||
228 | |||
229 | if (link->handle) | ||
230 | pcmcia_deregister_client(link->handle); | ||
231 | |||
232 | /* Unlink device structure, free bits */ | ||
233 | *linkp = link->next; | ||
234 | free_netdev(dev); | ||
235 | } /* axnet_detach */ | ||
236 | |||
237 | /*====================================================================== | ||
238 | |||
239 | This probes for a card's hardware address by reading the PROM. | ||
240 | |||
241 | ======================================================================*/ | ||
242 | |||
243 | static int get_prom(dev_link_t *link) | ||
244 | { | ||
245 | struct net_device *dev = link->priv; | ||
246 | kio_addr_t ioaddr = dev->base_addr; | ||
247 | int i, j; | ||
248 | |||
249 | /* This is based on drivers/net/ne.c */ | ||
250 | struct { | ||
251 | u_char value, offset; | ||
252 | } program_seq[] = { | ||
253 | {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ | ||
254 | {0x01, EN0_DCFG}, /* Set word-wide access. */ | ||
255 | {0x00, EN0_RCNTLO}, /* Clear the count regs. */ | ||
256 | {0x00, EN0_RCNTHI}, | ||
257 | {0x00, EN0_IMR}, /* Mask completion irq. */ | ||
258 | {0xFF, EN0_ISR}, | ||
259 | {E8390_RXOFF|0x40, EN0_RXCR}, /* 0x60 Set to monitor */ | ||
260 | {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ | ||
261 | {0x10, EN0_RCNTLO}, | ||
262 | {0x00, EN0_RCNTHI}, | ||
263 | {0x00, EN0_RSARLO}, /* DMA starting at 0x0400. */ | ||
264 | {0x04, EN0_RSARHI}, | ||
265 | {E8390_RREAD+E8390_START, E8390_CMD}, | ||
266 | }; | ||
267 | |||
268 | /* Not much of a test, but the alternatives are messy */ | ||
269 | if (link->conf.ConfigBase != 0x03c0) | ||
270 | return 0; | ||
271 | |||
272 | axnet_reset_8390(dev); | ||
273 | mdelay(10); | ||
274 | |||
275 | for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) | ||
276 | outb_p(program_seq[i].value, ioaddr + program_seq[i].offset); | ||
277 | |||
278 | for (i = 0; i < 6; i += 2) { | ||
279 | j = inw(ioaddr + AXNET_DATAPORT); | ||
280 | dev->dev_addr[i] = j & 0xff; | ||
281 | dev->dev_addr[i+1] = j >> 8; | ||
282 | } | ||
283 | return 1; | ||
284 | } /* get_prom */ | ||
285 | |||
286 | /*====================================================================== | ||
287 | |||
288 | axnet_config() is scheduled to run after a CARD_INSERTION event | ||
289 | is received, to configure the PCMCIA socket, and to make the | ||
290 | ethernet device available to the system. | ||
291 | |||
292 | ======================================================================*/ | ||
293 | |||
294 | #define CS_CHECK(fn, ret) \ | ||
295 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
296 | |||
297 | static int try_io_port(dev_link_t *link) | ||
298 | { | ||
299 | int j, ret; | ||
300 | if (link->io.NumPorts1 == 32) { | ||
301 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
302 | if (link->io.NumPorts2 > 0) { | ||
303 | /* for master/slave multifunction cards */ | ||
304 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; | ||
305 | link->irq.Attributes = | ||
306 | IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | ||
307 | } | ||
308 | } else { | ||
309 | /* This should be two 16-port windows */ | ||
310 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
311 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_16; | ||
312 | } | ||
313 | if (link->io.BasePort1 == 0) { | ||
314 | link->io.IOAddrLines = 16; | ||
315 | for (j = 0; j < 0x400; j += 0x20) { | ||
316 | link->io.BasePort1 = j ^ 0x300; | ||
317 | link->io.BasePort2 = (j ^ 0x300) + 0x10; | ||
318 | ret = pcmcia_request_io(link->handle, &link->io); | ||
319 | if (ret == CS_SUCCESS) return ret; | ||
320 | } | ||
321 | return ret; | ||
322 | } else { | ||
323 | return pcmcia_request_io(link->handle, &link->io); | ||
324 | } | ||
325 | } | ||
326 | |||
327 | static void axnet_config(dev_link_t *link) | ||
328 | { | ||
329 | client_handle_t handle = link->handle; | ||
330 | struct net_device *dev = link->priv; | ||
331 | axnet_dev_t *info = PRIV(dev); | ||
332 | tuple_t tuple; | ||
333 | cisparse_t parse; | ||
334 | int i, j, last_ret, last_fn; | ||
335 | u_short buf[64]; | ||
336 | config_info_t conf; | ||
337 | |||
338 | DEBUG(0, "axnet_config(0x%p)\n", link); | ||
339 | |||
340 | tuple.Attributes = 0; | ||
341 | tuple.TupleData = (cisdata_t *)buf; | ||
342 | tuple.TupleDataMax = sizeof(buf); | ||
343 | tuple.TupleOffset = 0; | ||
344 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
345 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
346 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
347 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | ||
348 | link->conf.ConfigBase = parse.config.base; | ||
349 | /* don't trust the CIS on this; Linksys got it wrong */ | ||
350 | link->conf.Present = 0x63; | ||
351 | |||
352 | /* Configure card */ | ||
353 | link->state |= DEV_CONFIG; | ||
354 | |||
355 | /* Look up current Vcc */ | ||
356 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); | ||
357 | link->conf.Vcc = conf.Vcc; | ||
358 | |||
359 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
360 | tuple.Attributes = 0; | ||
361 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
362 | while (last_ret == CS_SUCCESS) { | ||
363 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | ||
364 | cistpl_io_t *io = &(parse.cftable_entry.io); | ||
365 | |||
366 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | ||
367 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0 || | ||
368 | cfg->index == 0 || cfg->io.nwin == 0) | ||
369 | goto next_entry; | ||
370 | |||
371 | link->conf.ConfigIndex = 0x05; | ||
372 | /* For multifunction cards, by convention, we configure the | ||
373 | network function with window 0, and serial with window 1 */ | ||
374 | if (io->nwin > 1) { | ||
375 | i = (io->win[1].len > io->win[0].len); | ||
376 | link->io.BasePort2 = io->win[1-i].base; | ||
377 | link->io.NumPorts2 = io->win[1-i].len; | ||
378 | } else { | ||
379 | i = link->io.NumPorts2 = 0; | ||
380 | } | ||
381 | link->io.BasePort1 = io->win[i].base; | ||
382 | link->io.NumPorts1 = io->win[i].len; | ||
383 | link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
384 | if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) { | ||
385 | last_ret = try_io_port(link); | ||
386 | if (last_ret == CS_SUCCESS) break; | ||
387 | } | ||
388 | next_entry: | ||
389 | last_ret = pcmcia_get_next_tuple(handle, &tuple); | ||
390 | } | ||
391 | if (last_ret != CS_SUCCESS) { | ||
392 | cs_error(handle, RequestIO, last_ret); | ||
393 | goto failed; | ||
394 | } | ||
395 | |||
396 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | ||
397 | |||
398 | if (link->io.NumPorts2 == 8) { | ||
399 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
400 | link->conf.Status = CCSR_AUDIO_ENA; | ||
401 | } | ||
402 | |||
403 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | ||
404 | dev->irq = link->irq.AssignedIRQ; | ||
405 | dev->base_addr = link->io.BasePort1; | ||
406 | |||
407 | if (!get_prom(link)) { | ||
408 | printk(KERN_NOTICE "axnet_cs: this is not an AX88190 card!\n"); | ||
409 | printk(KERN_NOTICE "axnet_cs: use pcnet_cs instead.\n"); | ||
410 | goto failed; | ||
411 | } | ||
412 | |||
413 | ei_status.name = "AX88190"; | ||
414 | ei_status.word16 = 1; | ||
415 | ei_status.tx_start_page = AXNET_START_PG; | ||
416 | ei_status.rx_start_page = AXNET_START_PG + TX_PAGES; | ||
417 | ei_status.stop_page = AXNET_STOP_PG; | ||
418 | ei_status.reset_8390 = &axnet_reset_8390; | ||
419 | ei_status.get_8390_hdr = &get_8390_hdr; | ||
420 | ei_status.block_input = &block_input; | ||
421 | ei_status.block_output = &block_output; | ||
422 | |||
423 | if (inb(dev->base_addr + AXNET_TEST) != 0) | ||
424 | info->flags |= IS_AX88790; | ||
425 | else | ||
426 | info->flags |= IS_AX88190; | ||
427 | |||
428 | if (info->flags & IS_AX88790) | ||
429 | outb(0x10, dev->base_addr + AXNET_GPIO); /* select Internal PHY */ | ||
430 | |||
431 | for (i = 0; i < 32; i++) { | ||
432 | j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); | ||
433 | if ((j != 0) && (j != 0xffff)) break; | ||
434 | } | ||
435 | |||
436 | /* Maybe PHY is in power down mode. (PPD_SET = 1) | ||
437 | Bit 2 of CCSR is active low. */ | ||
438 | if (i == 32) { | ||
439 | conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 }; | ||
440 | pcmcia_access_configuration_register(link->handle, ®); | ||
441 | for (i = 0; i < 32; i++) { | ||
442 | j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); | ||
443 | if ((j != 0) && (j != 0xffff)) break; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | info->phy_id = (i < 32) ? i : -1; | ||
448 | link->dev = &info->node; | ||
449 | link->state &= ~DEV_CONFIG_PENDING; | ||
450 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
451 | |||
452 | if (register_netdev(dev) != 0) { | ||
453 | printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); | ||
454 | link->dev = NULL; | ||
455 | goto failed; | ||
456 | } | ||
457 | |||
458 | strcpy(info->node.dev_name, dev->name); | ||
459 | |||
460 | printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, hw_addr ", | ||
461 | dev->name, ((info->flags & IS_AX88790) ? 7 : 1), | ||
462 | dev->base_addr, dev->irq); | ||
463 | for (i = 0; i < 6; i++) | ||
464 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); | ||
465 | if (info->phy_id != -1) { | ||
466 | DEBUG(0, " MII transceiver at index %d, status %x.\n", info->phy_id, j); | ||
467 | } else { | ||
468 | printk(KERN_NOTICE " No MII transceivers found!\n"); | ||
469 | } | ||
470 | return; | ||
471 | |||
472 | cs_failed: | ||
473 | cs_error(link->handle, last_fn, last_ret); | ||
474 | failed: | ||
475 | axnet_release(link); | ||
476 | link->state &= ~DEV_CONFIG_PENDING; | ||
477 | return; | ||
478 | } /* axnet_config */ | ||
479 | |||
480 | /*====================================================================== | ||
481 | |||
482 | After a card is removed, axnet_release() will unregister the net | ||
483 | device, and release the PCMCIA configuration. If the device is | ||
484 | still open, this will be postponed until it is closed. | ||
485 | |||
486 | ======================================================================*/ | ||
487 | |||
488 | static void axnet_release(dev_link_t *link) | ||
489 | { | ||
490 | DEBUG(0, "axnet_release(0x%p)\n", link); | ||
491 | |||
492 | pcmcia_release_configuration(link->handle); | ||
493 | pcmcia_release_io(link->handle, &link->io); | ||
494 | pcmcia_release_irq(link->handle, &link->irq); | ||
495 | |||
496 | link->state &= ~DEV_CONFIG; | ||
497 | } | ||
498 | |||
499 | /*====================================================================== | ||
500 | |||
501 | The card status event handler. Mostly, this schedules other | ||
502 | stuff to run after an event is received. A CARD_REMOVAL event | ||
503 | also sets some flags to discourage the net drivers from trying | ||
504 | to talk to the card any more. | ||
505 | |||
506 | ======================================================================*/ | ||
507 | |||
508 | static int axnet_event(event_t event, int priority, | ||
509 | event_callback_args_t *args) | ||
510 | { | ||
511 | dev_link_t *link = args->client_data; | ||
512 | struct net_device *dev = link->priv; | ||
513 | |||
514 | DEBUG(2, "axnet_event(0x%06x)\n", event); | ||
515 | |||
516 | switch (event) { | ||
517 | case CS_EVENT_CARD_REMOVAL: | ||
518 | link->state &= ~DEV_PRESENT; | ||
519 | if (link->state & DEV_CONFIG) | ||
520 | netif_device_detach(dev); | ||
521 | break; | ||
522 | case CS_EVENT_CARD_INSERTION: | ||
523 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
524 | axnet_config(link); | ||
525 | break; | ||
526 | case CS_EVENT_PM_SUSPEND: | ||
527 | link->state |= DEV_SUSPEND; | ||
528 | /* Fall through... */ | ||
529 | case CS_EVENT_RESET_PHYSICAL: | ||
530 | if (link->state & DEV_CONFIG) { | ||
531 | if (link->open) | ||
532 | netif_device_detach(dev); | ||
533 | pcmcia_release_configuration(link->handle); | ||
534 | } | ||
535 | break; | ||
536 | case CS_EVENT_PM_RESUME: | ||
537 | link->state &= ~DEV_SUSPEND; | ||
538 | /* Fall through... */ | ||
539 | case CS_EVENT_CARD_RESET: | ||
540 | if (link->state & DEV_CONFIG) { | ||
541 | pcmcia_request_configuration(link->handle, &link->conf); | ||
542 | if (link->open) { | ||
543 | axnet_reset_8390(dev); | ||
544 | AX88190_init(dev, 1); | ||
545 | netif_device_attach(dev); | ||
546 | } | ||
547 | } | ||
548 | break; | ||
549 | } | ||
550 | return 0; | ||
551 | } /* axnet_event */ | ||
552 | |||
553 | /*====================================================================== | ||
554 | |||
555 | MII interface support | ||
556 | |||
557 | ======================================================================*/ | ||
558 | |||
559 | #define MDIO_SHIFT_CLK 0x01 | ||
560 | #define MDIO_DATA_WRITE0 0x00 | ||
561 | #define MDIO_DATA_WRITE1 0x08 | ||
562 | #define MDIO_DATA_READ 0x04 | ||
563 | #define MDIO_MASK 0x0f | ||
564 | #define MDIO_ENB_IN 0x02 | ||
565 | |||
566 | static void mdio_sync(kio_addr_t addr) | ||
567 | { | ||
568 | int bits; | ||
569 | for (bits = 0; bits < 32; bits++) { | ||
570 | outb_p(MDIO_DATA_WRITE1, addr); | ||
571 | outb_p(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr); | ||
572 | } | ||
573 | } | ||
574 | |||
575 | static int mdio_read(kio_addr_t addr, int phy_id, int loc) | ||
576 | { | ||
577 | u_int cmd = (0xf6<<10)|(phy_id<<5)|loc; | ||
578 | int i, retval = 0; | ||
579 | |||
580 | mdio_sync(addr); | ||
581 | for (i = 14; i >= 0; i--) { | ||
582 | int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; | ||
583 | outb_p(dat, addr); | ||
584 | outb_p(dat | MDIO_SHIFT_CLK, addr); | ||
585 | } | ||
586 | for (i = 19; i > 0; i--) { | ||
587 | outb_p(MDIO_ENB_IN, addr); | ||
588 | retval = (retval << 1) | ((inb_p(addr) & MDIO_DATA_READ) != 0); | ||
589 | outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr); | ||
590 | } | ||
591 | return (retval>>1) & 0xffff; | ||
592 | } | ||
593 | |||
594 | static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value) | ||
595 | { | ||
596 | u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value; | ||
597 | int i; | ||
598 | |||
599 | mdio_sync(addr); | ||
600 | for (i = 31; i >= 0; i--) { | ||
601 | int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; | ||
602 | outb_p(dat, addr); | ||
603 | outb_p(dat | MDIO_SHIFT_CLK, addr); | ||
604 | } | ||
605 | for (i = 1; i >= 0; i--) { | ||
606 | outb_p(MDIO_ENB_IN, addr); | ||
607 | outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr); | ||
608 | } | ||
609 | } | ||
610 | |||
611 | /*====================================================================*/ | ||
612 | |||
613 | static int axnet_open(struct net_device *dev) | ||
614 | { | ||
615 | axnet_dev_t *info = PRIV(dev); | ||
616 | dev_link_t *link = &info->link; | ||
617 | |||
618 | DEBUG(2, "axnet_open('%s')\n", dev->name); | ||
619 | |||
620 | if (!DEV_OK(link)) | ||
621 | return -ENODEV; | ||
622 | |||
623 | link->open++; | ||
624 | |||
625 | request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev); | ||
626 | |||
627 | info->link_status = 0x00; | ||
628 | init_timer(&info->watchdog); | ||
629 | info->watchdog.function = &ei_watchdog; | ||
630 | info->watchdog.data = (u_long)dev; | ||
631 | info->watchdog.expires = jiffies + HZ; | ||
632 | add_timer(&info->watchdog); | ||
633 | |||
634 | return ax_open(dev); | ||
635 | } /* axnet_open */ | ||
636 | |||
637 | /*====================================================================*/ | ||
638 | |||
639 | static int axnet_close(struct net_device *dev) | ||
640 | { | ||
641 | axnet_dev_t *info = PRIV(dev); | ||
642 | dev_link_t *link = &info->link; | ||
643 | |||
644 | DEBUG(2, "axnet_close('%s')\n", dev->name); | ||
645 | |||
646 | ax_close(dev); | ||
647 | free_irq(dev->irq, dev); | ||
648 | |||
649 | link->open--; | ||
650 | netif_stop_queue(dev); | ||
651 | del_timer_sync(&info->watchdog); | ||
652 | |||
653 | return 0; | ||
654 | } /* axnet_close */ | ||
655 | |||
656 | /*====================================================================== | ||
657 | |||
658 | Hard reset the card. This used to pause for the same period that | ||
659 | a 8390 reset command required, but that shouldn't be necessary. | ||
660 | |||
661 | ======================================================================*/ | ||
662 | |||
663 | static void axnet_reset_8390(struct net_device *dev) | ||
664 | { | ||
665 | kio_addr_t nic_base = dev->base_addr; | ||
666 | int i; | ||
667 | |||
668 | ei_status.txing = ei_status.dmaing = 0; | ||
669 | |||
670 | outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD); | ||
671 | |||
672 | outb(inb(nic_base + AXNET_RESET), nic_base + AXNET_RESET); | ||
673 | |||
674 | for (i = 0; i < 100; i++) { | ||
675 | if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0) | ||
676 | break; | ||
677 | udelay(100); | ||
678 | } | ||
679 | outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */ | ||
680 | |||
681 | if (i == 100) | ||
682 | printk(KERN_ERR "%s: axnet_reset_8390() did not complete.\n", | ||
683 | dev->name); | ||
684 | |||
685 | } /* axnet_reset_8390 */ | ||
686 | |||
687 | /*====================================================================*/ | ||
688 | |||
689 | static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs) | ||
690 | { | ||
691 | struct net_device *dev = dev_id; | ||
692 | PRIV(dev)->stale = 0; | ||
693 | return ax_interrupt(irq, dev_id, regs); | ||
694 | } | ||
695 | |||
696 | static void ei_watchdog(u_long arg) | ||
697 | { | ||
698 | struct net_device *dev = (struct net_device *)(arg); | ||
699 | axnet_dev_t *info = PRIV(dev); | ||
700 | kio_addr_t nic_base = dev->base_addr; | ||
701 | kio_addr_t mii_addr = nic_base + AXNET_MII_EEP; | ||
702 | u_short link; | ||
703 | |||
704 | if (!netif_device_present(dev)) goto reschedule; | ||
705 | |||
706 | /* Check for pending interrupt with expired latency timer: with | ||
707 | this, we can limp along even if the interrupt is blocked */ | ||
708 | if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { | ||
709 | if (!info->fast_poll) | ||
710 | printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); | ||
711 | ei_irq_wrapper(dev->irq, dev, NULL); | ||
712 | info->fast_poll = HZ; | ||
713 | } | ||
714 | if (info->fast_poll) { | ||
715 | info->fast_poll--; | ||
716 | info->watchdog.expires = jiffies + 1; | ||
717 | add_timer(&info->watchdog); | ||
718 | return; | ||
719 | } | ||
720 | |||
721 | if (info->phy_id < 0) | ||
722 | goto reschedule; | ||
723 | link = mdio_read(mii_addr, info->phy_id, 1); | ||
724 | if (!link || (link == 0xffff)) { | ||
725 | printk(KERN_INFO "%s: MII is missing!\n", dev->name); | ||
726 | info->phy_id = -1; | ||
727 | goto reschedule; | ||
728 | } | ||
729 | |||
730 | link &= 0x0004; | ||
731 | if (link != info->link_status) { | ||
732 | u_short p = mdio_read(mii_addr, info->phy_id, 5); | ||
733 | printk(KERN_INFO "%s: %s link beat\n", dev->name, | ||
734 | (link) ? "found" : "lost"); | ||
735 | if (link) { | ||
736 | info->duplex_flag = (p & 0x0140) ? 0x80 : 0x00; | ||
737 | if (p) | ||
738 | printk(KERN_INFO "%s: autonegotiation complete: " | ||
739 | "%sbaseT-%cD selected\n", dev->name, | ||
740 | ((p & 0x0180) ? "100" : "10"), | ||
741 | ((p & 0x0140) ? 'F' : 'H')); | ||
742 | else | ||
743 | printk(KERN_INFO "%s: link partner did not autonegotiate\n", | ||
744 | dev->name); | ||
745 | AX88190_init(dev, 1); | ||
746 | } | ||
747 | info->link_status = link; | ||
748 | } | ||
749 | |||
750 | reschedule: | ||
751 | info->watchdog.expires = jiffies + HZ; | ||
752 | add_timer(&info->watchdog); | ||
753 | } | ||
754 | |||
755 | static void netdev_get_drvinfo(struct net_device *dev, | ||
756 | struct ethtool_drvinfo *info) | ||
757 | { | ||
758 | strcpy(info->driver, "axnet_cs"); | ||
759 | } | ||
760 | |||
761 | static struct ethtool_ops netdev_ethtool_ops = { | ||
762 | .get_drvinfo = netdev_get_drvinfo, | ||
763 | }; | ||
764 | |||
765 | /*====================================================================*/ | ||
766 | |||
767 | static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||
768 | { | ||
769 | axnet_dev_t *info = PRIV(dev); | ||
770 | u16 *data = (u16 *)&rq->ifr_ifru; | ||
771 | kio_addr_t mii_addr = dev->base_addr + AXNET_MII_EEP; | ||
772 | switch (cmd) { | ||
773 | case SIOCGMIIPHY: | ||
774 | data[0] = info->phy_id; | ||
775 | case SIOCGMIIREG: /* Read MII PHY register. */ | ||
776 | data[3] = mdio_read(mii_addr, data[0], data[1] & 0x1f); | ||
777 | return 0; | ||
778 | case SIOCSMIIREG: /* Write MII PHY register. */ | ||
779 | if (!capable(CAP_NET_ADMIN)) | ||
780 | return -EPERM; | ||
781 | mdio_write(mii_addr, data[0], data[1] & 0x1f, data[2]); | ||
782 | return 0; | ||
783 | } | ||
784 | return -EOPNOTSUPP; | ||
785 | } | ||
786 | |||
787 | /*====================================================================*/ | ||
788 | |||
789 | static void get_8390_hdr(struct net_device *dev, | ||
790 | struct e8390_pkt_hdr *hdr, | ||
791 | int ring_page) | ||
792 | { | ||
793 | kio_addr_t nic_base = dev->base_addr; | ||
794 | |||
795 | outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */ | ||
796 | outb_p(ring_page, nic_base + EN0_RSARHI); | ||
797 | outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD); | ||
798 | |||
799 | insw(nic_base + AXNET_DATAPORT, hdr, | ||
800 | sizeof(struct e8390_pkt_hdr)>>1); | ||
801 | /* Fix for big endian systems */ | ||
802 | hdr->count = le16_to_cpu(hdr->count); | ||
803 | |||
804 | } | ||
805 | |||
806 | /*====================================================================*/ | ||
807 | |||
808 | static void block_input(struct net_device *dev, int count, | ||
809 | struct sk_buff *skb, int ring_offset) | ||
810 | { | ||
811 | kio_addr_t nic_base = dev->base_addr; | ||
812 | int xfer_count = count; | ||
813 | char *buf = skb->data; | ||
814 | |||
815 | #ifdef PCMCIA_DEBUG | ||
816 | if ((ei_debug > 4) && (count != 4)) | ||
817 | printk(KERN_DEBUG "%s: [bi=%d]\n", dev->name, count+4); | ||
818 | #endif | ||
819 | outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); | ||
820 | outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); | ||
821 | outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD); | ||
822 | |||
823 | insw(nic_base + AXNET_DATAPORT,buf,count>>1); | ||
824 | if (count & 0x01) | ||
825 | buf[count-1] = inb(nic_base + AXNET_DATAPORT), xfer_count++; | ||
826 | |||
827 | } | ||
828 | |||
829 | /*====================================================================*/ | ||
830 | |||
831 | static void block_output(struct net_device *dev, int count, | ||
832 | const u_char *buf, const int start_page) | ||
833 | { | ||
834 | kio_addr_t nic_base = dev->base_addr; | ||
835 | |||
836 | #ifdef PCMCIA_DEBUG | ||
837 | if (ei_debug > 4) | ||
838 | printk(KERN_DEBUG "%s: [bo=%d]\n", dev->name, count); | ||
839 | #endif | ||
840 | |||
841 | /* Round the count up for word writes. Do we need to do this? | ||
842 | What effect will an odd byte count have on the 8390? | ||
843 | I should check someday. */ | ||
844 | if (count & 0x01) | ||
845 | count++; | ||
846 | |||
847 | outb_p(0x00, nic_base + EN0_RSARLO); | ||
848 | outb_p(start_page, nic_base + EN0_RSARHI); | ||
849 | outb_p(E8390_RWRITE+E8390_START, nic_base + AXNET_CMD); | ||
850 | outsw(nic_base + AXNET_DATAPORT, buf, count>>1); | ||
851 | } | ||
852 | |||
853 | static struct pcmcia_driver axnet_cs_driver = { | ||
854 | .owner = THIS_MODULE, | ||
855 | .drv = { | ||
856 | .name = "axnet_cs", | ||
857 | }, | ||
858 | .attach = axnet_attach, | ||
859 | .detach = axnet_detach, | ||
860 | }; | ||
861 | |||
862 | static int __init init_axnet_cs(void) | ||
863 | { | ||
864 | return pcmcia_register_driver(&axnet_cs_driver); | ||
865 | } | ||
866 | |||
867 | static void __exit exit_axnet_cs(void) | ||
868 | { | ||
869 | pcmcia_unregister_driver(&axnet_cs_driver); | ||
870 | BUG_ON(dev_list != NULL); | ||
871 | } | ||
872 | |||
873 | module_init(init_axnet_cs); | ||
874 | module_exit(exit_axnet_cs); | ||
875 | |||
876 | /*====================================================================*/ | ||
877 | |||
878 | /* 8390.c: A general NS8390 ethernet driver core for linux. */ | ||
879 | /* | ||
880 | Written 1992-94 by Donald Becker. | ||
881 | |||
882 | Copyright 1993 United States Government as represented by the | ||
883 | Director, National Security Agency. | ||
884 | |||
885 | This software may be used and distributed according to the terms | ||
886 | of the GNU General Public License, incorporated herein by reference. | ||
887 | |||
888 | The author may be reached as becker@scyld.com, or C/O | ||
889 | Scyld Computing Corporation | ||
890 | 410 Severn Ave., Suite 210 | ||
891 | Annapolis MD 21403 | ||
892 | |||
893 | This is the chip-specific code for many 8390-based ethernet adaptors. | ||
894 | This is not a complete driver, it must be combined with board-specific | ||
895 | code such as ne.c, wd.c, 3c503.c, etc. | ||
896 | |||
897 | Seeing how at least eight drivers use this code, (not counting the | ||
898 | PCMCIA ones either) it is easy to break some card by what seems like | ||
899 | a simple innocent change. Please contact me or Donald if you think | ||
900 | you have found something that needs changing. -- PG | ||
901 | |||
902 | Changelog: | ||
903 | |||
904 | Paul Gortmaker : remove set_bit lock, other cleanups. | ||
905 | Paul Gortmaker : add ei_get_8390_hdr() so we can pass skb's to | ||
906 | ei_block_input() for eth_io_copy_and_sum(). | ||
907 | Paul Gortmaker : exchange static int ei_pingpong for a #define, | ||
908 | also add better Tx error handling. | ||
909 | Paul Gortmaker : rewrite Rx overrun handling as per NS specs. | ||
910 | Alexey Kuznetsov : use the 8390's six bit hash multicast filter. | ||
911 | Paul Gortmaker : tweak ANK's above multicast changes a bit. | ||
912 | Paul Gortmaker : update packet statistics for v2.1.x | ||
913 | Alan Cox : support arbitary stupid port mappings on the | ||
914 | 68K Macintosh. Support >16bit I/O spaces | ||
915 | Paul Gortmaker : add kmod support for auto-loading of the 8390 | ||
916 | module by all drivers that require it. | ||
917 | Alan Cox : Spinlocking work, added 'BUG_83C690' | ||
918 | Paul Gortmaker : Separate out Tx timeout code from Tx path. | ||
919 | |||
920 | Sources: | ||
921 | The National Semiconductor LAN Databook, and the 3Com 3c503 databook. | ||
922 | |||
923 | */ | ||
924 | |||
925 | static const char *version_8390 = | ||
926 | "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@scyld.com)\n"; | ||
927 | |||
928 | #include <linux/bitops.h> | ||
929 | #include <asm/irq.h> | ||
930 | #include <linux/fcntl.h> | ||
931 | #include <linux/in.h> | ||
932 | #include <linux/interrupt.h> | ||
933 | |||
934 | #include <linux/etherdevice.h> | ||
935 | |||
936 | #define BUG_83C690 | ||
937 | |||
938 | /* These are the operational function interfaces to board-specific | ||
939 | routines. | ||
940 | void reset_8390(struct net_device *dev) | ||
941 | Resets the board associated with DEV, including a hardware reset of | ||
942 | the 8390. This is only called when there is a transmit timeout, and | ||
943 | it is always followed by 8390_init(). | ||
944 | void block_output(struct net_device *dev, int count, const unsigned char *buf, | ||
945 | int start_page) | ||
946 | Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The | ||
947 | "page" value uses the 8390's 256-byte pages. | ||
948 | void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page) | ||
949 | Read the 4 byte, page aligned 8390 header. *If* there is a | ||
950 | subsequent read, it will be of the rest of the packet. | ||
951 | void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) | ||
952 | Read COUNT bytes from the packet buffer into the skb data area. Start | ||
953 | reading from RING_OFFSET, the address as the 8390 sees it. This will always | ||
954 | follow the read of the 8390 header. | ||
955 | */ | ||
956 | #define ei_reset_8390 (ei_local->reset_8390) | ||
957 | #define ei_block_output (ei_local->block_output) | ||
958 | #define ei_block_input (ei_local->block_input) | ||
959 | #define ei_get_8390_hdr (ei_local->get_8390_hdr) | ||
960 | |||
961 | /* use 0 for production, 1 for verification, >2 for debug */ | ||
962 | #ifndef ei_debug | ||
963 | int ei_debug = 1; | ||
964 | #endif | ||
965 | |||
966 | /* Index to functions. */ | ||
967 | static void ei_tx_intr(struct net_device *dev); | ||
968 | static void ei_tx_err(struct net_device *dev); | ||
969 | static void ei_tx_timeout(struct net_device *dev); | ||
970 | static void ei_receive(struct net_device *dev); | ||
971 | static void ei_rx_overrun(struct net_device *dev); | ||
972 | |||
973 | /* Routines generic to NS8390-based boards. */ | ||
974 | static void NS8390_trigger_send(struct net_device *dev, unsigned int length, | ||
975 | int start_page); | ||
976 | static void set_multicast_list(struct net_device *dev); | ||
977 | static void do_set_multicast_list(struct net_device *dev); | ||
978 | |||
979 | /* | ||
980 | * SMP and the 8390 setup. | ||
981 | * | ||
982 | * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is | ||
983 | * a page register that controls bank and packet buffer access. We guard | ||
984 | * this with ei_local->page_lock. Nobody should assume or set the page other | ||
985 | * than zero when the lock is not held. Lock holders must restore page 0 | ||
986 | * before unlocking. Even pure readers must take the lock to protect in | ||
987 | * page 0. | ||
988 | * | ||
989 | * To make life difficult the chip can also be very slow. We therefore can't | ||
990 | * just use spinlocks. For the longer lockups we disable the irq the device | ||
991 | * sits on and hold the lock. We must hold the lock because there is a dual | ||
992 | * processor case other than interrupts (get stats/set multicast list in | ||
993 | * parallel with each other and transmit). | ||
994 | * | ||
995 | * Note: in theory we can just disable the irq on the card _but_ there is | ||
996 | * a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs" | ||
997 | * enter lock, take the queued irq. So we waddle instead of flying. | ||
998 | * | ||
999 | * Finally by special arrangement for the purpose of being generally | ||
1000 | * annoying the transmit function is called bh atomic. That places | ||
1001 | * restrictions on the user context callers as disable_irq won't save | ||
1002 | * them. | ||
1003 | */ | ||
1004 | |||
1005 | /** | ||
1006 | * ax_open - Open/initialize the board. | ||
1007 | * @dev: network device to initialize | ||
1008 | * | ||
1009 | * This routine goes all-out, setting everything | ||
1010 | * up anew at each open, even though many of these registers should only | ||
1011 | * need to be set once at boot. | ||
1012 | */ | ||
1013 | static int ax_open(struct net_device *dev) | ||
1014 | { | ||
1015 | unsigned long flags; | ||
1016 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); | ||
1017 | |||
1018 | #ifdef HAVE_TX_TIMEOUT | ||
1019 | /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout | ||
1020 | wrapper that does e.g. media check & then calls ei_tx_timeout. */ | ||
1021 | if (dev->tx_timeout == NULL) | ||
1022 | dev->tx_timeout = ei_tx_timeout; | ||
1023 | if (dev->watchdog_timeo <= 0) | ||
1024 | dev->watchdog_timeo = TX_TIMEOUT; | ||
1025 | #endif | ||
1026 | |||
1027 | /* | ||
1028 | * Grab the page lock so we own the register set, then call | ||
1029 | * the init function. | ||
1030 | */ | ||
1031 | |||
1032 | spin_lock_irqsave(&ei_local->page_lock, flags); | ||
1033 | AX88190_init(dev, 1); | ||
1034 | /* Set the flag before we drop the lock, That way the IRQ arrives | ||
1035 | after its set and we get no silly warnings */ | ||
1036 | netif_start_queue(dev); | ||
1037 | spin_unlock_irqrestore(&ei_local->page_lock, flags); | ||
1038 | ei_local->irqlock = 0; | ||
1039 | return 0; | ||
1040 | } | ||
1041 | |||
1042 | #define dev_lock(dev) (((struct ei_device *)netdev_priv(dev))->page_lock) | ||
1043 | |||
1044 | /** | ||
1045 | * ax_close - shut down network device | ||
1046 | * @dev: network device to close | ||
1047 | * | ||
1048 | * Opposite of ax_open(). Only used when "ifconfig <devname> down" is done. | ||
1049 | */ | ||
1050 | int ax_close(struct net_device *dev) | ||
1051 | { | ||
1052 | unsigned long flags; | ||
1053 | |||
1054 | /* | ||
1055 | * Hold the page lock during close | ||
1056 | */ | ||
1057 | |||
1058 | spin_lock_irqsave(&dev_lock(dev), flags); | ||
1059 | AX88190_init(dev, 0); | ||
1060 | spin_unlock_irqrestore(&dev_lock(dev), flags); | ||
1061 | netif_stop_queue(dev); | ||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | /** | ||
1066 | * ei_tx_timeout - handle transmit time out condition | ||
1067 | * @dev: network device which has apparently fallen asleep | ||
1068 | * | ||
1069 | * Called by kernel when device never acknowledges a transmit has | ||
1070 | * completed (or failed) - i.e. never posted a Tx related interrupt. | ||
1071 | */ | ||
1072 | |||
1073 | void ei_tx_timeout(struct net_device *dev) | ||
1074 | { | ||
1075 | long e8390_base = dev->base_addr; | ||
1076 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); | ||
1077 | int txsr, isr, tickssofar = jiffies - dev->trans_start; | ||
1078 | unsigned long flags; | ||
1079 | |||
1080 | ei_local->stat.tx_errors++; | ||
1081 | |||
1082 | spin_lock_irqsave(&ei_local->page_lock, flags); | ||
1083 | txsr = inb(e8390_base+EN0_TSR); | ||
1084 | isr = inb(e8390_base+EN0_ISR); | ||
1085 | spin_unlock_irqrestore(&ei_local->page_lock, flags); | ||
1086 | |||
1087 | printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", | ||
1088 | dev->name, (txsr & ENTSR_ABT) ? "excess collisions." : | ||
1089 | (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar); | ||
1090 | |||
1091 | if (!isr && !ei_local->stat.tx_packets) | ||
1092 | { | ||
1093 | /* The 8390 probably hasn't gotten on the cable yet. */ | ||
1094 | ei_local->interface_num ^= 1; /* Try a different xcvr. */ | ||
1095 | } | ||
1096 | |||
1097 | /* Ugly but a reset can be slow, yet must be protected */ | ||
1098 | |||
1099 | disable_irq_nosync(dev->irq); | ||
1100 | spin_lock(&ei_local->page_lock); | ||
1101 | |||
1102 | /* Try to restart the card. Perhaps the user has fixed something. */ | ||
1103 | ei_reset_8390(dev); | ||
1104 | AX88190_init(dev, 1); | ||
1105 | |||
1106 | spin_unlock(&ei_local->page_lock); | ||
1107 | enable_irq(dev->irq); | ||
1108 | netif_wake_queue(dev); | ||
1109 | } | ||
1110 | |||
1111 | /** | ||
1112 | * ei_start_xmit - begin packet transmission | ||
1113 | * @skb: packet to be sent | ||
1114 | * @dev: network device to which packet is sent | ||
1115 | * | ||
1116 | * Sends a packet to an 8390 network device. | ||
1117 | */ | ||
1118 | |||
1119 | static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
1120 | { | ||
1121 | long e8390_base = dev->base_addr; | ||
1122 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); | ||
1123 | int length, send_length, output_page; | ||
1124 | unsigned long flags; | ||
1125 | u8 packet[ETH_ZLEN]; | ||
1126 | |||
1127 | netif_stop_queue(dev); | ||
1128 | |||
1129 | length = skb->len; | ||
1130 | |||
1131 | /* Mask interrupts from the ethercard. | ||
1132 | SMP: We have to grab the lock here otherwise the IRQ handler | ||
1133 | on another CPU can flip window and race the IRQ mask set. We end | ||
1134 | up trashing the mcast filter not disabling irqs if we don't lock */ | ||
1135 | |||
1136 | spin_lock_irqsave(&ei_local->page_lock, flags); | ||
1137 | outb_p(0x00, e8390_base + EN0_IMR); | ||
1138 | spin_unlock_irqrestore(&ei_local->page_lock, flags); | ||
1139 | |||
1140 | /* | ||
1141 | * Slow phase with lock held. | ||
1142 | */ | ||
1143 | |||
1144 | disable_irq_nosync(dev->irq); | ||
1145 | |||
1146 | spin_lock(&ei_local->page_lock); | ||
1147 | |||
1148 | ei_local->irqlock = 1; | ||
1149 | |||
1150 | send_length = ETH_ZLEN < length ? length : ETH_ZLEN; | ||
1151 | |||
1152 | /* | ||
1153 | * We have two Tx slots available for use. Find the first free | ||
1154 | * slot, and then perform some sanity checks. With two Tx bufs, | ||
1155 | * you get very close to transmitting back-to-back packets. With | ||
1156 | * only one Tx buf, the transmitter sits idle while you reload the | ||
1157 | * card, leaving a substantial gap between each transmitted packet. | ||
1158 | */ | ||
1159 | |||
1160 | if (ei_local->tx1 == 0) | ||
1161 | { | ||
1162 | output_page = ei_local->tx_start_page; | ||
1163 | ei_local->tx1 = send_length; | ||
1164 | if (ei_debug && ei_local->tx2 > 0) | ||
1165 | printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n", | ||
1166 | dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing); | ||
1167 | } | ||
1168 | else if (ei_local->tx2 == 0) | ||
1169 | { | ||
1170 | output_page = ei_local->tx_start_page + TX_PAGES/2; | ||
1171 | ei_local->tx2 = send_length; | ||
1172 | if (ei_debug && ei_local->tx1 > 0) | ||
1173 | printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n", | ||
1174 | dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing); | ||
1175 | } | ||
1176 | else | ||
1177 | { /* We should never get here. */ | ||
1178 | if (ei_debug) | ||
1179 | printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n", | ||
1180 | dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx); | ||
1181 | ei_local->irqlock = 0; | ||
1182 | netif_stop_queue(dev); | ||
1183 | outb_p(ENISR_ALL, e8390_base + EN0_IMR); | ||
1184 | spin_unlock(&ei_local->page_lock); | ||
1185 | enable_irq(dev->irq); | ||
1186 | ei_local->stat.tx_errors++; | ||
1187 | return 1; | ||
1188 | } | ||
1189 | |||
1190 | /* | ||
1191 | * Okay, now upload the packet and trigger a send if the transmitter | ||
1192 | * isn't already sending. If it is busy, the interrupt handler will | ||
1193 | * trigger the send later, upon receiving a Tx done interrupt. | ||
1194 | */ | ||
1195 | |||
1196 | if (length == skb->len) | ||
1197 | ei_block_output(dev, length, skb->data, output_page); | ||
1198 | else { | ||
1199 | memset(packet, 0, ETH_ZLEN); | ||
1200 | memcpy(packet, skb->data, skb->len); | ||
1201 | ei_block_output(dev, length, packet, output_page); | ||
1202 | } | ||
1203 | |||
1204 | if (! ei_local->txing) | ||
1205 | { | ||
1206 | ei_local->txing = 1; | ||
1207 | NS8390_trigger_send(dev, send_length, output_page); | ||
1208 | dev->trans_start = jiffies; | ||
1209 | if (output_page == ei_local->tx_start_page) | ||
1210 | { | ||
1211 | ei_local->tx1 = -1; | ||
1212 | ei_local->lasttx = -1; | ||
1213 | } | ||
1214 | else | ||
1215 | { | ||
1216 | ei_local->tx2 = -1; | ||
1217 | ei_local->lasttx = -2; | ||
1218 | } | ||
1219 | } | ||
1220 | else ei_local->txqueue++; | ||
1221 | |||
1222 | if (ei_local->tx1 && ei_local->tx2) | ||
1223 | netif_stop_queue(dev); | ||
1224 | else | ||
1225 | netif_start_queue(dev); | ||
1226 | |||
1227 | /* Turn 8390 interrupts back on. */ | ||
1228 | ei_local->irqlock = 0; | ||
1229 | outb_p(ENISR_ALL, e8390_base + EN0_IMR); | ||
1230 | |||
1231 | spin_unlock(&ei_local->page_lock); | ||
1232 | enable_irq(dev->irq); | ||
1233 | |||
1234 | dev_kfree_skb (skb); | ||
1235 | ei_local->stat.tx_bytes += send_length; | ||
1236 | |||
1237 | return 0; | ||
1238 | } | ||
1239 | |||
1240 | /** | ||
1241 | * ax_interrupt - handle the interrupts from an 8390 | ||
1242 | * @irq: interrupt number | ||
1243 | * @dev_id: a pointer to the net_device | ||
1244 | * @regs: unused | ||
1245 | * | ||
1246 | * Handle the ether interface interrupts. We pull packets from | ||
1247 | * the 8390 via the card specific functions and fire them at the networking | ||
1248 | * stack. We also handle transmit completions and wake the transmit path if | ||
1249 | * necessary. We also update the counters and do other housekeeping as | ||
1250 | * needed. | ||
1251 | */ | ||
1252 | |||
1253 | static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs * regs) | ||
1254 | { | ||
1255 | struct net_device *dev = dev_id; | ||
1256 | long e8390_base; | ||
1257 | int interrupts, nr_serviced = 0, i; | ||
1258 | struct ei_device *ei_local; | ||
1259 | int handled = 0; | ||
1260 | |||
1261 | if (dev == NULL) | ||
1262 | { | ||
1263 | printk ("net_interrupt(): irq %d for unknown device.\n", irq); | ||
1264 | return IRQ_NONE; | ||
1265 | } | ||
1266 | |||
1267 | e8390_base = dev->base_addr; | ||
1268 | ei_local = (struct ei_device *) netdev_priv(dev); | ||
1269 | |||
1270 | /* | ||
1271 | * Protect the irq test too. | ||
1272 | */ | ||
1273 | |||
1274 | spin_lock(&ei_local->page_lock); | ||
1275 | |||
1276 | if (ei_local->irqlock) | ||
1277 | { | ||
1278 | #if 1 /* This might just be an interrupt for a PCI device sharing this line */ | ||
1279 | /* The "irqlock" check is only for testing. */ | ||
1280 | printk(ei_local->irqlock | ||
1281 | ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n" | ||
1282 | : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n", | ||
1283 | dev->name, inb_p(e8390_base + EN0_ISR), | ||
1284 | inb_p(e8390_base + EN0_IMR)); | ||
1285 | #endif | ||
1286 | spin_unlock(&ei_local->page_lock); | ||
1287 | return IRQ_NONE; | ||
1288 | } | ||
1289 | |||
1290 | if (ei_debug > 3) | ||
1291 | printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name, | ||
1292 | inb_p(e8390_base + EN0_ISR)); | ||
1293 | |||
1294 | outb_p(0x00, e8390_base + EN0_ISR); | ||
1295 | ei_local->irqlock = 1; | ||
1296 | |||
1297 | /* !!Assumption!! -- we stay in page 0. Don't break this. */ | ||
1298 | while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 | ||
1299 | && ++nr_serviced < MAX_SERVICE) | ||
1300 | { | ||
1301 | if (!netif_running(dev) || (interrupts == 0xff)) { | ||
1302 | if (ei_debug > 1) | ||
1303 | printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name); | ||
1304 | outb_p(interrupts, e8390_base + EN0_ISR); | ||
1305 | interrupts = 0; | ||
1306 | break; | ||
1307 | } | ||
1308 | handled = 1; | ||
1309 | |||
1310 | /* AX88190 bug fix. */ | ||
1311 | outb_p(interrupts, e8390_base + EN0_ISR); | ||
1312 | for (i = 0; i < 10; i++) { | ||
1313 | if (!(inb(e8390_base + EN0_ISR) & interrupts)) | ||
1314 | break; | ||
1315 | outb_p(0, e8390_base + EN0_ISR); | ||
1316 | outb_p(interrupts, e8390_base + EN0_ISR); | ||
1317 | } | ||
1318 | if (interrupts & ENISR_OVER) | ||
1319 | ei_rx_overrun(dev); | ||
1320 | else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) | ||
1321 | { | ||
1322 | /* Got a good (?) packet. */ | ||
1323 | ei_receive(dev); | ||
1324 | } | ||
1325 | /* Push the next to-transmit packet through. */ | ||
1326 | if (interrupts & ENISR_TX) | ||
1327 | ei_tx_intr(dev); | ||
1328 | else if (interrupts & ENISR_TX_ERR) | ||
1329 | ei_tx_err(dev); | ||
1330 | |||
1331 | if (interrupts & ENISR_COUNTERS) | ||
1332 | { | ||
1333 | ei_local->stat.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0); | ||
1334 | ei_local->stat.rx_crc_errors += inb_p(e8390_base + EN0_COUNTER1); | ||
1335 | ei_local->stat.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2); | ||
1336 | } | ||
1337 | } | ||
1338 | |||
1339 | if (interrupts && ei_debug) | ||
1340 | { | ||
1341 | handled = 1; | ||
1342 | if (nr_serviced >= MAX_SERVICE) | ||
1343 | { | ||
1344 | /* 0xFF is valid for a card removal */ | ||
1345 | if(interrupts!=0xFF) | ||
1346 | printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n", | ||
1347 | dev->name, interrupts); | ||
1348 | outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */ | ||
1349 | } else { | ||
1350 | printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts); | ||
1351 | outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */ | ||
1352 | } | ||
1353 | } | ||
1354 | |||
1355 | /* Turn 8390 interrupts back on. */ | ||
1356 | ei_local->irqlock = 0; | ||
1357 | outb_p(ENISR_ALL, e8390_base + EN0_IMR); | ||
1358 | |||
1359 | spin_unlock(&ei_local->page_lock); | ||
1360 | return IRQ_RETVAL(handled); | ||
1361 | } | ||
1362 | |||
1363 | /** | ||
1364 | * ei_tx_err - handle transmitter error | ||
1365 | * @dev: network device which threw the exception | ||
1366 | * | ||
1367 | * A transmitter error has happened. Most likely excess collisions (which | ||
1368 | * is a fairly normal condition). If the error is one where the Tx will | ||
1369 | * have been aborted, we try and send another one right away, instead of | ||
1370 | * letting the failed packet sit and collect dust in the Tx buffer. This | ||
1371 | * is a much better solution as it avoids kernel based Tx timeouts, and | ||
1372 | * an unnecessary card reset. | ||
1373 | * | ||
1374 | * Called with lock held. | ||
1375 | */ | ||
1376 | |||
1377 | static void ei_tx_err(struct net_device *dev) | ||
1378 | { | ||
1379 | long e8390_base = dev->base_addr; | ||
1380 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); | ||
1381 | unsigned char txsr = inb_p(e8390_base+EN0_TSR); | ||
1382 | unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU); | ||
1383 | |||
1384 | #ifdef VERBOSE_ERROR_DUMP | ||
1385 | printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr); | ||
1386 | if (txsr & ENTSR_ABT) | ||
1387 | printk("excess-collisions "); | ||
1388 | if (txsr & ENTSR_ND) | ||
1389 | printk("non-deferral "); | ||
1390 | if (txsr & ENTSR_CRS) | ||
1391 | printk("lost-carrier "); | ||
1392 | if (txsr & ENTSR_FU) | ||
1393 | printk("FIFO-underrun "); | ||
1394 | if (txsr & ENTSR_CDH) | ||
1395 | printk("lost-heartbeat "); | ||
1396 | printk("\n"); | ||
1397 | #endif | ||
1398 | |||
1399 | if (tx_was_aborted) | ||
1400 | ei_tx_intr(dev); | ||
1401 | else | ||
1402 | { | ||
1403 | ei_local->stat.tx_errors++; | ||
1404 | if (txsr & ENTSR_CRS) ei_local->stat.tx_carrier_errors++; | ||
1405 | if (txsr & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++; | ||
1406 | if (txsr & ENTSR_OWC) ei_local->stat.tx_window_errors++; | ||
1407 | } | ||
1408 | } | ||
1409 | |||
1410 | /** | ||
1411 | * ei_tx_intr - transmit interrupt handler | ||
1412 | * @dev: network device for which tx intr is handled | ||
1413 | * | ||
1414 | * We have finished a transmit: check for errors and then trigger the next | ||
1415 | * packet to be sent. Called with lock held. | ||
1416 | */ | ||
1417 | |||
1418 | static void ei_tx_intr(struct net_device *dev) | ||
1419 | { | ||
1420 | long e8390_base = dev->base_addr; | ||
1421 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); | ||
1422 | int status = inb(e8390_base + EN0_TSR); | ||
1423 | |||
1424 | /* | ||
1425 | * There are two Tx buffers, see which one finished, and trigger | ||
1426 | * the send of another one if it exists. | ||
1427 | */ | ||
1428 | ei_local->txqueue--; | ||
1429 | |||
1430 | if (ei_local->tx1 < 0) | ||
1431 | { | ||
1432 | if (ei_local->lasttx != 1 && ei_local->lasttx != -1) | ||
1433 | printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n", | ||
1434 | ei_local->name, ei_local->lasttx, ei_local->tx1); | ||
1435 | ei_local->tx1 = 0; | ||
1436 | if (ei_local->tx2 > 0) | ||
1437 | { | ||
1438 | ei_local->txing = 1; | ||
1439 | NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6); | ||
1440 | dev->trans_start = jiffies; | ||
1441 | ei_local->tx2 = -1, | ||
1442 | ei_local->lasttx = 2; | ||
1443 | } | ||
1444 | else ei_local->lasttx = 20, ei_local->txing = 0; | ||
1445 | } | ||
1446 | else if (ei_local->tx2 < 0) | ||
1447 | { | ||
1448 | if (ei_local->lasttx != 2 && ei_local->lasttx != -2) | ||
1449 | printk("%s: bogus last_tx_buffer %d, tx2=%d.\n", | ||
1450 | ei_local->name, ei_local->lasttx, ei_local->tx2); | ||
1451 | ei_local->tx2 = 0; | ||
1452 | if (ei_local->tx1 > 0) | ||
1453 | { | ||
1454 | ei_local->txing = 1; | ||
1455 | NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page); | ||
1456 | dev->trans_start = jiffies; | ||
1457 | ei_local->tx1 = -1; | ||
1458 | ei_local->lasttx = 1; | ||
1459 | } | ||
1460 | else | ||
1461 | ei_local->lasttx = 10, ei_local->txing = 0; | ||
1462 | } | ||
1463 | // else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n", | ||
1464 | // dev->name, ei_local->lasttx); | ||
1465 | |||
1466 | /* Minimize Tx latency: update the statistics after we restart TXing. */ | ||
1467 | if (status & ENTSR_COL) | ||
1468 | ei_local->stat.collisions++; | ||
1469 | if (status & ENTSR_PTX) | ||
1470 | ei_local->stat.tx_packets++; | ||
1471 | else | ||
1472 | { | ||
1473 | ei_local->stat.tx_errors++; | ||
1474 | if (status & ENTSR_ABT) | ||
1475 | { | ||
1476 | ei_local->stat.tx_aborted_errors++; | ||
1477 | ei_local->stat.collisions += 16; | ||
1478 | } | ||
1479 | if (status & ENTSR_CRS) | ||
1480 | ei_local->stat.tx_carrier_errors++; | ||
1481 | if (status & ENTSR_FU) | ||
1482 | ei_local->stat.tx_fifo_errors++; | ||
1483 | if (status & ENTSR_CDH) | ||
1484 | ei_local->stat.tx_heartbeat_errors++; | ||
1485 | if (status & ENTSR_OWC) | ||
1486 | ei_local->stat.tx_window_errors++; | ||
1487 | } | ||
1488 | netif_wake_queue(dev); | ||
1489 | } | ||
1490 | |||
1491 | /** | ||
1492 | * ei_receive - receive some packets | ||
1493 | * @dev: network device with which receive will be run | ||
1494 | * | ||
1495 | * We have a good packet(s), get it/them out of the buffers. | ||
1496 | * Called with lock held. | ||
1497 | */ | ||
1498 | |||
1499 | static void ei_receive(struct net_device *dev) | ||
1500 | { | ||
1501 | long e8390_base = dev->base_addr; | ||
1502 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); | ||
1503 | unsigned char rxing_page, this_frame, next_frame; | ||
1504 | unsigned short current_offset; | ||
1505 | int rx_pkt_count = 0; | ||
1506 | struct e8390_pkt_hdr rx_frame; | ||
1507 | |||
1508 | while (++rx_pkt_count < 10) | ||
1509 | { | ||
1510 | int pkt_len, pkt_stat; | ||
1511 | |||
1512 | /* Get the rx page (incoming packet pointer). */ | ||
1513 | rxing_page = inb_p(e8390_base + EN1_CURPAG -1); | ||
1514 | |||
1515 | /* Remove one frame from the ring. Boundary is always a page behind. */ | ||
1516 | this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1; | ||
1517 | if (this_frame >= ei_local->stop_page) | ||
1518 | this_frame = ei_local->rx_start_page; | ||
1519 | |||
1520 | /* Someday we'll omit the previous, iff we never get this message. | ||
1521 | (There is at least one clone claimed to have a problem.) | ||
1522 | |||
1523 | Keep quiet if it looks like a card removal. One problem here | ||
1524 | is that some clones crash in roughly the same way. | ||
1525 | */ | ||
1526 | if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF)) | ||
1527 | printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n", | ||
1528 | dev->name, this_frame, ei_local->current_page); | ||
1529 | |||
1530 | if (this_frame == rxing_page) /* Read all the frames? */ | ||
1531 | break; /* Done for now */ | ||
1532 | |||
1533 | current_offset = this_frame << 8; | ||
1534 | ei_get_8390_hdr(dev, &rx_frame, this_frame); | ||
1535 | |||
1536 | pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr); | ||
1537 | pkt_stat = rx_frame.status; | ||
1538 | |||
1539 | next_frame = this_frame + 1 + ((pkt_len+4)>>8); | ||
1540 | |||
1541 | if (pkt_len < 60 || pkt_len > 1518) | ||
1542 | { | ||
1543 | if (ei_debug) | ||
1544 | printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n", | ||
1545 | dev->name, rx_frame.count, rx_frame.status, | ||
1546 | rx_frame.next); | ||
1547 | ei_local->stat.rx_errors++; | ||
1548 | ei_local->stat.rx_length_errors++; | ||
1549 | } | ||
1550 | else if ((pkt_stat & 0x0F) == ENRSR_RXOK) | ||
1551 | { | ||
1552 | struct sk_buff *skb; | ||
1553 | |||
1554 | skb = dev_alloc_skb(pkt_len+2); | ||
1555 | if (skb == NULL) | ||
1556 | { | ||
1557 | if (ei_debug > 1) | ||
1558 | printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n", | ||
1559 | dev->name, pkt_len); | ||
1560 | ei_local->stat.rx_dropped++; | ||
1561 | break; | ||
1562 | } | ||
1563 | else | ||
1564 | { | ||
1565 | skb_reserve(skb,2); /* IP headers on 16 byte boundaries */ | ||
1566 | skb->dev = dev; | ||
1567 | skb_put(skb, pkt_len); /* Make room */ | ||
1568 | ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame)); | ||
1569 | skb->protocol=eth_type_trans(skb,dev); | ||
1570 | netif_rx(skb); | ||
1571 | dev->last_rx = jiffies; | ||
1572 | ei_local->stat.rx_packets++; | ||
1573 | ei_local->stat.rx_bytes += pkt_len; | ||
1574 | if (pkt_stat & ENRSR_PHY) | ||
1575 | ei_local->stat.multicast++; | ||
1576 | } | ||
1577 | } | ||
1578 | else | ||
1579 | { | ||
1580 | if (ei_debug) | ||
1581 | printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n", | ||
1582 | dev->name, rx_frame.status, rx_frame.next, | ||
1583 | rx_frame.count); | ||
1584 | ei_local->stat.rx_errors++; | ||
1585 | /* NB: The NIC counts CRC, frame and missed errors. */ | ||
1586 | if (pkt_stat & ENRSR_FO) | ||
1587 | ei_local->stat.rx_fifo_errors++; | ||
1588 | } | ||
1589 | next_frame = rx_frame.next; | ||
1590 | |||
1591 | /* This _should_ never happen: it's here for avoiding bad clones. */ | ||
1592 | if (next_frame >= ei_local->stop_page) { | ||
1593 | printk("%s: next frame inconsistency, %#2x\n", dev->name, | ||
1594 | next_frame); | ||
1595 | next_frame = ei_local->rx_start_page; | ||
1596 | } | ||
1597 | ei_local->current_page = next_frame; | ||
1598 | outb_p(next_frame-1, e8390_base+EN0_BOUNDARY); | ||
1599 | } | ||
1600 | |||
1601 | return; | ||
1602 | } | ||
1603 | |||
1604 | /** | ||
1605 | * ei_rx_overrun - handle receiver overrun | ||
1606 | * @dev: network device which threw exception | ||
1607 | * | ||
1608 | * We have a receiver overrun: we have to kick the 8390 to get it started | ||
1609 | * again. Problem is that you have to kick it exactly as NS prescribes in | ||
1610 | * the updated datasheets, or "the NIC may act in an unpredictable manner." | ||
1611 | * This includes causing "the NIC to defer indefinitely when it is stopped | ||
1612 | * on a busy network." Ugh. | ||
1613 | * Called with lock held. Don't call this with the interrupts off or your | ||
1614 | * computer will hate you - it takes 10ms or so. | ||
1615 | */ | ||
1616 | |||
1617 | static void ei_rx_overrun(struct net_device *dev) | ||
1618 | { | ||
1619 | axnet_dev_t *info = (axnet_dev_t *)dev; | ||
1620 | long e8390_base = dev->base_addr; | ||
1621 | unsigned char was_txing, must_resend = 0; | ||
1622 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); | ||
1623 | |||
1624 | /* | ||
1625 | * Record whether a Tx was in progress and then issue the | ||
1626 | * stop command. | ||
1627 | */ | ||
1628 | was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS; | ||
1629 | outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); | ||
1630 | |||
1631 | if (ei_debug > 1) | ||
1632 | printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name); | ||
1633 | ei_local->stat.rx_over_errors++; | ||
1634 | |||
1635 | /* | ||
1636 | * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total. | ||
1637 | * Early datasheets said to poll the reset bit, but now they say that | ||
1638 | * it "is not a reliable indicator and subsequently should be ignored." | ||
1639 | * We wait at least 10ms. | ||
1640 | */ | ||
1641 | |||
1642 | mdelay(10); | ||
1643 | |||
1644 | /* | ||
1645 | * Reset RBCR[01] back to zero as per magic incantation. | ||
1646 | */ | ||
1647 | outb_p(0x00, e8390_base+EN0_RCNTLO); | ||
1648 | outb_p(0x00, e8390_base+EN0_RCNTHI); | ||
1649 | |||
1650 | /* | ||
1651 | * See if any Tx was interrupted or not. According to NS, this | ||
1652 | * step is vital, and skipping it will cause no end of havoc. | ||
1653 | */ | ||
1654 | |||
1655 | if (was_txing) | ||
1656 | { | ||
1657 | unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR); | ||
1658 | if (!tx_completed) | ||
1659 | must_resend = 1; | ||
1660 | } | ||
1661 | |||
1662 | /* | ||
1663 | * Have to enter loopback mode and then restart the NIC before | ||
1664 | * you are allowed to slurp packets up off the ring. | ||
1665 | */ | ||
1666 | outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); | ||
1667 | outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD); | ||
1668 | |||
1669 | /* | ||
1670 | * Clear the Rx ring of all the debris, and ack the interrupt. | ||
1671 | */ | ||
1672 | ei_receive(dev); | ||
1673 | |||
1674 | /* | ||
1675 | * Leave loopback mode, and resend any packet that got stopped. | ||
1676 | */ | ||
1677 | outb_p(E8390_TXCONFIG | info->duplex_flag, e8390_base + EN0_TXCR); | ||
1678 | if (must_resend) | ||
1679 | outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD); | ||
1680 | } | ||
1681 | |||
1682 | /* | ||
1683 | * Collect the stats. This is called unlocked and from several contexts. | ||
1684 | */ | ||
1685 | |||
1686 | static struct net_device_stats *get_stats(struct net_device *dev) | ||
1687 | { | ||
1688 | long ioaddr = dev->base_addr; | ||
1689 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); | ||
1690 | unsigned long flags; | ||
1691 | |||
1692 | /* If the card is stopped, just return the present stats. */ | ||
1693 | if (!netif_running(dev)) | ||
1694 | return &ei_local->stat; | ||
1695 | |||
1696 | spin_lock_irqsave(&ei_local->page_lock,flags); | ||
1697 | /* Read the counter registers, assuming we are in page 0. */ | ||
1698 | ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0); | ||
1699 | ei_local->stat.rx_crc_errors += inb_p(ioaddr + EN0_COUNTER1); | ||
1700 | ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2); | ||
1701 | spin_unlock_irqrestore(&ei_local->page_lock, flags); | ||
1702 | |||
1703 | return &ei_local->stat; | ||
1704 | } | ||
1705 | |||
1706 | /** | ||
1707 | * do_set_multicast_list - set/clear multicast filter | ||
1708 | * @dev: net device for which multicast filter is adjusted | ||
1709 | * | ||
1710 | * Set or clear the multicast filter for this adaptor. May be called | ||
1711 | * from a BH in 2.1.x. Must be called with lock held. | ||
1712 | */ | ||
1713 | |||
1714 | static void do_set_multicast_list(struct net_device *dev) | ||
1715 | { | ||
1716 | long e8390_base = dev->base_addr; | ||
1717 | |||
1718 | if(dev->flags&IFF_PROMISC) | ||
1719 | outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR); | ||
1720 | else if(dev->flags&IFF_ALLMULTI || dev->mc_list) | ||
1721 | outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR); | ||
1722 | else | ||
1723 | outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); | ||
1724 | } | ||
1725 | |||
1726 | /* | ||
1727 | * Called without lock held. This is invoked from user context and may | ||
1728 | * be parallel to just about everything else. Its also fairly quick and | ||
1729 | * not called too often. Must protect against both bh and irq users | ||
1730 | */ | ||
1731 | |||
1732 | static void set_multicast_list(struct net_device *dev) | ||
1733 | { | ||
1734 | unsigned long flags; | ||
1735 | |||
1736 | spin_lock_irqsave(&dev_lock(dev), flags); | ||
1737 | do_set_multicast_list(dev); | ||
1738 | spin_unlock_irqrestore(&dev_lock(dev), flags); | ||
1739 | } | ||
1740 | |||
1741 | /** | ||
1742 | * axdev_setup - init rest of 8390 device struct | ||
1743 | * @dev: network device structure to init | ||
1744 | * | ||
1745 | * Initialize the rest of the 8390 device structure. Do NOT __init | ||
1746 | * this, as it is used by 8390 based modular drivers too. | ||
1747 | */ | ||
1748 | |||
1749 | static void axdev_setup(struct net_device *dev) | ||
1750 | { | ||
1751 | struct ei_device *ei_local; | ||
1752 | if (ei_debug > 1) | ||
1753 | printk(version_8390); | ||
1754 | |||
1755 | SET_MODULE_OWNER(dev); | ||
1756 | |||
1757 | |||
1758 | ei_local = (struct ei_device *)netdev_priv(dev); | ||
1759 | spin_lock_init(&ei_local->page_lock); | ||
1760 | |||
1761 | dev->hard_start_xmit = &ei_start_xmit; | ||
1762 | dev->get_stats = get_stats; | ||
1763 | dev->set_multicast_list = &set_multicast_list; | ||
1764 | |||
1765 | ether_setup(dev); | ||
1766 | } | ||
1767 | |||
1768 | /* This page of functions should be 8390 generic */ | ||
1769 | /* Follow National Semi's recommendations for initializing the "NIC". */ | ||
1770 | |||
1771 | /** | ||
1772 | * AX88190_init - initialize 8390 hardware | ||
1773 | * @dev: network device to initialize | ||
1774 | * @startp: boolean. non-zero value to initiate chip processing | ||
1775 | * | ||
1776 | * Must be called with lock held. | ||
1777 | */ | ||
1778 | |||
1779 | static void AX88190_init(struct net_device *dev, int startp) | ||
1780 | { | ||
1781 | axnet_dev_t *info = PRIV(dev); | ||
1782 | long e8390_base = dev->base_addr; | ||
1783 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); | ||
1784 | int i; | ||
1785 | int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48; | ||
1786 | |||
1787 | if(sizeof(struct e8390_pkt_hdr)!=4) | ||
1788 | panic("8390.c: header struct mispacked\n"); | ||
1789 | /* Follow National Semi's recommendations for initing the DP83902. */ | ||
1790 | outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */ | ||
1791 | outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */ | ||
1792 | /* Clear the remote byte count registers. */ | ||
1793 | outb_p(0x00, e8390_base + EN0_RCNTLO); | ||
1794 | outb_p(0x00, e8390_base + EN0_RCNTHI); | ||
1795 | /* Set to monitor and loopback mode -- this is vital!. */ | ||
1796 | outb_p(E8390_RXOFF|0x40, e8390_base + EN0_RXCR); /* 0x60 */ | ||
1797 | outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ | ||
1798 | /* Set the transmit page and receive ring. */ | ||
1799 | outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR); | ||
1800 | ei_local->tx1 = ei_local->tx2 = 0; | ||
1801 | outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG); | ||
1802 | outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ | ||
1803 | ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */ | ||
1804 | outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG); | ||
1805 | /* Clear the pending interrupts and mask. */ | ||
1806 | outb_p(0xFF, e8390_base + EN0_ISR); | ||
1807 | outb_p(0x00, e8390_base + EN0_IMR); | ||
1808 | |||
1809 | /* Copy the station address into the DS8390 registers. */ | ||
1810 | |||
1811 | outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */ | ||
1812 | for(i = 0; i < 6; i++) | ||
1813 | { | ||
1814 | outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i)); | ||
1815 | if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) | ||
1816 | printk(KERN_ERR "Hw. address read/write mismap %d\n",i); | ||
1817 | } | ||
1818 | /* | ||
1819 | * Initialize the multicast list to accept-all. If we enable multicast | ||
1820 | * the higher levels can do the filtering. | ||
1821 | */ | ||
1822 | for (i = 0; i < 8; i++) | ||
1823 | outb_p(0xff, e8390_base + EN1_MULT + i); | ||
1824 | |||
1825 | outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); | ||
1826 | outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); | ||
1827 | |||
1828 | netif_start_queue(dev); | ||
1829 | ei_local->tx1 = ei_local->tx2 = 0; | ||
1830 | ei_local->txing = 0; | ||
1831 | |||
1832 | if (startp) | ||
1833 | { | ||
1834 | outb_p(0xff, e8390_base + EN0_ISR); | ||
1835 | outb_p(ENISR_ALL, e8390_base + EN0_IMR); | ||
1836 | outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); | ||
1837 | outb_p(E8390_TXCONFIG | info->duplex_flag, | ||
1838 | e8390_base + EN0_TXCR); /* xmit on. */ | ||
1839 | /* 3c503 TechMan says rxconfig only after the NIC is started. */ | ||
1840 | outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); /* rx on, */ | ||
1841 | do_set_multicast_list(dev); /* (re)load the mcast table */ | ||
1842 | } | ||
1843 | } | ||
1844 | |||
1845 | /* Trigger a transmit start, assuming the length is valid. | ||
1846 | Always called with the page lock held */ | ||
1847 | |||
1848 | static void NS8390_trigger_send(struct net_device *dev, unsigned int length, | ||
1849 | int start_page) | ||
1850 | { | ||
1851 | long e8390_base = dev->base_addr; | ||
1852 | struct ei_device *ei_local __attribute((unused)) = (struct ei_device *) netdev_priv(dev); | ||
1853 | |||
1854 | if (inb_p(e8390_base) & E8390_TRANS) | ||
1855 | { | ||
1856 | printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n", | ||
1857 | dev->name); | ||
1858 | return; | ||
1859 | } | ||
1860 | outb_p(length & 0xff, e8390_base + EN0_TCNTLO); | ||
1861 | outb_p(length >> 8, e8390_base + EN0_TCNTHI); | ||
1862 | outb_p(start_page, e8390_base + EN0_TPSR); | ||
1863 | outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD); | ||
1864 | } | ||
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c new file mode 100644 index 000000000000..4294e1e3f156 --- /dev/null +++ b/drivers/net/pcmcia/com20020_cs.c | |||
@@ -0,0 +1,509 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - COM20020 PCMCIA support | ||
3 | * | ||
4 | * Written 1994-1999 by Avery Pennarun, | ||
5 | * based on an ISA version by David Woodhouse. | ||
6 | * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4) | ||
7 | * which was derived from pcnet_cs.c by David Hinds. | ||
8 | * Some additional portions derived from skeleton.c by Donald Becker. | ||
9 | * | ||
10 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
11 | * for sponsoring the further development of this driver. | ||
12 | * | ||
13 | * ********************** | ||
14 | * | ||
15 | * The original copyright of skeleton.c was as follows: | ||
16 | * | ||
17 | * skeleton.c Written 1993 by Donald Becker. | ||
18 | * Copyright 1993 United States Government as represented by the | ||
19 | * Director, National Security Agency. This software may only be used | ||
20 | * and distributed according to the terms of the GNU General Public License as | ||
21 | * modified by SRC, incorporated herein by reference. | ||
22 | * | ||
23 | * ********************** | ||
24 | * Changes: | ||
25 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000 | ||
26 | * - reorganize kmallocs in com20020_attach, checking all for failure | ||
27 | * and releasing the previous allocations if one fails | ||
28 | * ********************** | ||
29 | * | ||
30 | * For more details, see drivers/net/arcnet.c | ||
31 | * | ||
32 | * ********************** | ||
33 | */ | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/ptrace.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/string.h> | ||
39 | #include <linux/timer.h> | ||
40 | #include <linux/delay.h> | ||
41 | #include <linux/module.h> | ||
42 | #include <linux/netdevice.h> | ||
43 | #include <linux/arcdevice.h> | ||
44 | #include <linux/com20020.h> | ||
45 | |||
46 | #include <pcmcia/version.h> | ||
47 | #include <pcmcia/cs_types.h> | ||
48 | #include <pcmcia/cs.h> | ||
49 | #include <pcmcia/cistpl.h> | ||
50 | #include <pcmcia/ds.h> | ||
51 | |||
52 | #include <asm/io.h> | ||
53 | #include <asm/system.h> | ||
54 | |||
55 | #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n" | ||
56 | |||
57 | #ifdef PCMCIA_DEBUG | ||
58 | |||
59 | static int pc_debug = PCMCIA_DEBUG; | ||
60 | module_param(pc_debug, int, 0); | ||
61 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) | ||
62 | |||
63 | static void regdump(struct net_device *dev) | ||
64 | { | ||
65 | int ioaddr = dev->base_addr; | ||
66 | int count; | ||
67 | |||
68 | printk("com20020 register dump:\n"); | ||
69 | for (count = ioaddr; count < ioaddr + 16; count++) | ||
70 | { | ||
71 | if (!(count % 16)) | ||
72 | printk("\n%04X: ", count); | ||
73 | printk("%02X ", inb(count)); | ||
74 | } | ||
75 | printk("\n"); | ||
76 | |||
77 | printk("buffer0 dump:\n"); | ||
78 | /* set up the address register */ | ||
79 | count = 0; | ||
80 | outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI); | ||
81 | outb(count & 0xff, _ADDR_LO); | ||
82 | |||
83 | for (count = 0; count < 256+32; count++) | ||
84 | { | ||
85 | if (!(count % 16)) | ||
86 | printk("\n%04X: ", count); | ||
87 | |||
88 | /* copy the data */ | ||
89 | printk("%02X ", inb(_MEMDATA)); | ||
90 | } | ||
91 | printk("\n"); | ||
92 | } | ||
93 | |||
94 | #else | ||
95 | |||
96 | #define DEBUG(n, args...) do { } while (0) | ||
97 | static inline void regdump(struct net_device *dev) { } | ||
98 | |||
99 | #endif | ||
100 | |||
101 | |||
102 | /*====================================================================*/ | ||
103 | |||
104 | /* Parameters that can be set with 'insmod' */ | ||
105 | |||
106 | static int node; | ||
107 | static int timeout = 3; | ||
108 | static int backplane; | ||
109 | static int clockp; | ||
110 | static int clockm; | ||
111 | |||
112 | module_param(node, int, 0); | ||
113 | module_param(timeout, int, 0); | ||
114 | module_param(backplane, int, 0); | ||
115 | module_param(clockp, int, 0); | ||
116 | module_param(clockm, int, 0); | ||
117 | |||
118 | MODULE_LICENSE("GPL"); | ||
119 | |||
120 | /*====================================================================*/ | ||
121 | |||
122 | static void com20020_config(dev_link_t *link); | ||
123 | static void com20020_release(dev_link_t *link); | ||
124 | static int com20020_event(event_t event, int priority, | ||
125 | event_callback_args_t *args); | ||
126 | |||
127 | static dev_info_t dev_info = "com20020_cs"; | ||
128 | |||
129 | static dev_link_t *com20020_attach(void); | ||
130 | static void com20020_detach(dev_link_t *); | ||
131 | |||
132 | static dev_link_t *dev_list; | ||
133 | |||
134 | /*====================================================================*/ | ||
135 | |||
136 | typedef struct com20020_dev_t { | ||
137 | struct net_device *dev; | ||
138 | dev_node_t node; | ||
139 | } com20020_dev_t; | ||
140 | |||
141 | /*====================================================================== | ||
142 | |||
143 | com20020_attach() creates an "instance" of the driver, allocating | ||
144 | local data structures for one device. The device is registered | ||
145 | with Card Services. | ||
146 | |||
147 | ======================================================================*/ | ||
148 | |||
149 | static dev_link_t *com20020_attach(void) | ||
150 | { | ||
151 | client_reg_t client_reg; | ||
152 | dev_link_t *link; | ||
153 | com20020_dev_t *info; | ||
154 | struct net_device *dev; | ||
155 | int ret; | ||
156 | struct arcnet_local *lp; | ||
157 | |||
158 | DEBUG(0, "com20020_attach()\n"); | ||
159 | |||
160 | /* Create new network device */ | ||
161 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); | ||
162 | if (!link) | ||
163 | return NULL; | ||
164 | |||
165 | info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); | ||
166 | if (!info) | ||
167 | goto fail_alloc_info; | ||
168 | |||
169 | dev = alloc_arcdev(""); | ||
170 | if (!dev) | ||
171 | goto fail_alloc_dev; | ||
172 | |||
173 | memset(info, 0, sizeof(struct com20020_dev_t)); | ||
174 | memset(link, 0, sizeof(struct dev_link_t)); | ||
175 | lp = dev->priv; | ||
176 | lp->timeout = timeout; | ||
177 | lp->backplane = backplane; | ||
178 | lp->clockp = clockp; | ||
179 | lp->clockm = clockm & 3; | ||
180 | lp->hw.owner = THIS_MODULE; | ||
181 | |||
182 | /* fill in our module parameters as defaults */ | ||
183 | dev->dev_addr[0] = node; | ||
184 | |||
185 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
186 | link->io.NumPorts1 = 16; | ||
187 | link->io.IOAddrLines = 16; | ||
188 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | ||
189 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
190 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
191 | link->conf.Vcc = 50; | ||
192 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
193 | link->conf.Present = PRESENT_OPTION; | ||
194 | |||
195 | |||
196 | link->irq.Instance = info->dev = dev; | ||
197 | link->priv = info; | ||
198 | |||
199 | /* Register with Card Services */ | ||
200 | link->next = dev_list; | ||
201 | dev_list = link; | ||
202 | client_reg.dev_info = &dev_info; | ||
203 | client_reg.EventMask = | ||
204 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
205 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
206 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
207 | client_reg.event_handler = &com20020_event; | ||
208 | client_reg.Version = 0x0210; | ||
209 | client_reg.event_callback_args.client_data = link; | ||
210 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
211 | if (ret != 0) { | ||
212 | cs_error(link->handle, RegisterClient, ret); | ||
213 | com20020_detach(link); | ||
214 | return NULL; | ||
215 | } | ||
216 | |||
217 | return link; | ||
218 | |||
219 | fail_alloc_dev: | ||
220 | kfree(info); | ||
221 | fail_alloc_info: | ||
222 | kfree(link); | ||
223 | return NULL; | ||
224 | } /* com20020_attach */ | ||
225 | |||
226 | /*====================================================================== | ||
227 | |||
228 | This deletes a driver "instance". The device is de-registered | ||
229 | with Card Services. If it has been released, all local data | ||
230 | structures are freed. Otherwise, the structures will be freed | ||
231 | when the device is released. | ||
232 | |||
233 | ======================================================================*/ | ||
234 | |||
235 | static void com20020_detach(dev_link_t *link) | ||
236 | { | ||
237 | struct com20020_dev_t *info = link->priv; | ||
238 | dev_link_t **linkp; | ||
239 | struct net_device *dev; | ||
240 | |||
241 | DEBUG(1,"detach...\n"); | ||
242 | |||
243 | DEBUG(0, "com20020_detach(0x%p)\n", link); | ||
244 | |||
245 | /* Locate device structure */ | ||
246 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
247 | if (*linkp == link) break; | ||
248 | if (*linkp == NULL) | ||
249 | return; | ||
250 | |||
251 | dev = info->dev; | ||
252 | |||
253 | if (link->dev) { | ||
254 | DEBUG(1,"unregister...\n"); | ||
255 | |||
256 | unregister_netdev(dev); | ||
257 | |||
258 | /* | ||
259 | * this is necessary because we register our IRQ separately | ||
260 | * from card services. | ||
261 | */ | ||
262 | if (dev->irq) | ||
263 | free_irq(dev->irq, dev); | ||
264 | } | ||
265 | |||
266 | if (link->state & DEV_CONFIG) | ||
267 | com20020_release(link); | ||
268 | |||
269 | if (link->handle) | ||
270 | pcmcia_deregister_client(link->handle); | ||
271 | |||
272 | /* Unlink device structure, free bits */ | ||
273 | DEBUG(1,"unlinking...\n"); | ||
274 | *linkp = link->next; | ||
275 | if (link->priv) | ||
276 | { | ||
277 | dev = info->dev; | ||
278 | if (dev) | ||
279 | { | ||
280 | DEBUG(1,"kfree...\n"); | ||
281 | free_netdev(dev); | ||
282 | } | ||
283 | DEBUG(1,"kfree2...\n"); | ||
284 | kfree(info); | ||
285 | } | ||
286 | DEBUG(1,"kfree3...\n"); | ||
287 | kfree(link); | ||
288 | |||
289 | } /* com20020_detach */ | ||
290 | |||
291 | /*====================================================================== | ||
292 | |||
293 | com20020_config() is scheduled to run after a CARD_INSERTION event | ||
294 | is received, to configure the PCMCIA socket, and to make the | ||
295 | device available to the system. | ||
296 | |||
297 | ======================================================================*/ | ||
298 | |||
299 | #define CS_CHECK(fn, ret) \ | ||
300 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
301 | |||
302 | static void com20020_config(dev_link_t *link) | ||
303 | { | ||
304 | struct arcnet_local *lp; | ||
305 | client_handle_t handle; | ||
306 | tuple_t tuple; | ||
307 | cisparse_t parse; | ||
308 | com20020_dev_t *info; | ||
309 | struct net_device *dev; | ||
310 | int i, last_ret, last_fn; | ||
311 | u_char buf[64]; | ||
312 | int ioaddr; | ||
313 | |||
314 | handle = link->handle; | ||
315 | info = link->priv; | ||
316 | dev = info->dev; | ||
317 | |||
318 | DEBUG(1,"config...\n"); | ||
319 | |||
320 | DEBUG(0, "com20020_config(0x%p)\n", link); | ||
321 | |||
322 | tuple.Attributes = 0; | ||
323 | tuple.TupleData = buf; | ||
324 | tuple.TupleDataMax = 64; | ||
325 | tuple.TupleOffset = 0; | ||
326 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
327 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
328 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
329 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | ||
330 | link->conf.ConfigBase = parse.config.base; | ||
331 | |||
332 | /* Configure card */ | ||
333 | link->state |= DEV_CONFIG; | ||
334 | |||
335 | DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); | ||
336 | i = !CS_SUCCESS; | ||
337 | if (!link->io.BasePort1) | ||
338 | { | ||
339 | for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) | ||
340 | { | ||
341 | link->io.BasePort1 = ioaddr; | ||
342 | i = pcmcia_request_io(link->handle, &link->io); | ||
343 | if (i == CS_SUCCESS) | ||
344 | break; | ||
345 | } | ||
346 | } | ||
347 | else | ||
348 | i = pcmcia_request_io(link->handle, &link->io); | ||
349 | |||
350 | if (i != CS_SUCCESS) | ||
351 | { | ||
352 | DEBUG(1,"arcnet: requestIO failed totally!\n"); | ||
353 | goto failed; | ||
354 | } | ||
355 | |||
356 | ioaddr = dev->base_addr = link->io.BasePort1; | ||
357 | DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr); | ||
358 | |||
359 | DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n", | ||
360 | link->irq.AssignedIRQ, | ||
361 | link->irq.IRQInfo1, link->irq.IRQInfo2); | ||
362 | i = pcmcia_request_irq(link->handle, &link->irq); | ||
363 | if (i != CS_SUCCESS) | ||
364 | { | ||
365 | DEBUG(1,"arcnet: requestIRQ failed totally!\n"); | ||
366 | goto failed; | ||
367 | } | ||
368 | |||
369 | dev->irq = link->irq.AssignedIRQ; | ||
370 | |||
371 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | ||
372 | |||
373 | if (com20020_check(dev)) | ||
374 | { | ||
375 | regdump(dev); | ||
376 | goto failed; | ||
377 | } | ||
378 | |||
379 | lp = dev->priv; | ||
380 | lp->card_name = "PCMCIA COM20020"; | ||
381 | lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ | ||
382 | |||
383 | link->dev = &info->node; | ||
384 | link->state &= ~DEV_CONFIG_PENDING; | ||
385 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
386 | |||
387 | i = com20020_found(dev, 0); /* calls register_netdev */ | ||
388 | |||
389 | if (i != 0) { | ||
390 | DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n"); | ||
391 | link->dev = NULL; | ||
392 | goto failed; | ||
393 | } | ||
394 | |||
395 | strcpy(info->node.dev_name, dev->name); | ||
396 | |||
397 | DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n", | ||
398 | dev->name, dev->base_addr, dev->irq); | ||
399 | return; | ||
400 | |||
401 | cs_failed: | ||
402 | cs_error(link->handle, last_fn, last_ret); | ||
403 | failed: | ||
404 | DEBUG(1,"com20020_config failed...\n"); | ||
405 | com20020_release(link); | ||
406 | } /* com20020_config */ | ||
407 | |||
408 | /*====================================================================== | ||
409 | |||
410 | After a card is removed, com20020_release() will unregister the net | ||
411 | device, and release the PCMCIA configuration. If the device is | ||
412 | still open, this will be postponed until it is closed. | ||
413 | |||
414 | ======================================================================*/ | ||
415 | |||
416 | static void com20020_release(dev_link_t *link) | ||
417 | { | ||
418 | |||
419 | DEBUG(1,"release...\n"); | ||
420 | |||
421 | DEBUG(0, "com20020_release(0x%p)\n", link); | ||
422 | |||
423 | pcmcia_release_configuration(link->handle); | ||
424 | pcmcia_release_io(link->handle, &link->io); | ||
425 | pcmcia_release_irq(link->handle, &link->irq); | ||
426 | |||
427 | link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); | ||
428 | } | ||
429 | |||
430 | /*====================================================================== | ||
431 | |||
432 | The card status event handler. Mostly, this schedules other | ||
433 | stuff to run after an event is received. A CARD_REMOVAL event | ||
434 | also sets some flags to discourage the net drivers from trying | ||
435 | to talk to the card any more. | ||
436 | |||
437 | ======================================================================*/ | ||
438 | |||
439 | static int com20020_event(event_t event, int priority, | ||
440 | event_callback_args_t *args) | ||
441 | { | ||
442 | dev_link_t *link = args->client_data; | ||
443 | com20020_dev_t *info = link->priv; | ||
444 | struct net_device *dev = info->dev; | ||
445 | |||
446 | DEBUG(1, "com20020_event(0x%06x)\n", event); | ||
447 | |||
448 | switch (event) { | ||
449 | case CS_EVENT_CARD_REMOVAL: | ||
450 | link->state &= ~DEV_PRESENT; | ||
451 | if (link->state & DEV_CONFIG) | ||
452 | netif_device_detach(dev); | ||
453 | break; | ||
454 | case CS_EVENT_CARD_INSERTION: | ||
455 | link->state |= DEV_PRESENT; | ||
456 | com20020_config(link); | ||
457 | break; | ||
458 | case CS_EVENT_PM_SUSPEND: | ||
459 | link->state |= DEV_SUSPEND; | ||
460 | /* Fall through... */ | ||
461 | case CS_EVENT_RESET_PHYSICAL: | ||
462 | if (link->state & DEV_CONFIG) { | ||
463 | if (link->open) { | ||
464 | netif_device_detach(dev); | ||
465 | } | ||
466 | pcmcia_release_configuration(link->handle); | ||
467 | } | ||
468 | break; | ||
469 | case CS_EVENT_PM_RESUME: | ||
470 | link->state &= ~DEV_SUSPEND; | ||
471 | /* Fall through... */ | ||
472 | case CS_EVENT_CARD_RESET: | ||
473 | if (link->state & DEV_CONFIG) { | ||
474 | pcmcia_request_configuration(link->handle, &link->conf); | ||
475 | if (link->open) { | ||
476 | int ioaddr = dev->base_addr; | ||
477 | struct arcnet_local *lp = dev->priv; | ||
478 | ARCRESET; | ||
479 | } | ||
480 | } | ||
481 | break; | ||
482 | } | ||
483 | return 0; | ||
484 | } /* com20020_event */ | ||
485 | |||
486 | |||
487 | |||
488 | static struct pcmcia_driver com20020_cs_driver = { | ||
489 | .owner = THIS_MODULE, | ||
490 | .drv = { | ||
491 | .name = "com20020_cs", | ||
492 | }, | ||
493 | .attach = com20020_attach, | ||
494 | .detach = com20020_detach, | ||
495 | }; | ||
496 | |||
497 | static int __init init_com20020_cs(void) | ||
498 | { | ||
499 | return pcmcia_register_driver(&com20020_cs_driver); | ||
500 | } | ||
501 | |||
502 | static void __exit exit_com20020_cs(void) | ||
503 | { | ||
504 | pcmcia_unregister_driver(&com20020_cs_driver); | ||
505 | BUG_ON(dev_list != NULL); | ||
506 | } | ||
507 | |||
508 | module_init(init_com20020_cs); | ||
509 | module_exit(exit_com20020_cs); | ||
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c new file mode 100644 index 000000000000..0424865e8094 --- /dev/null +++ b/drivers/net/pcmcia/fmvj18x_cs.c | |||
@@ -0,0 +1,1286 @@ | |||
1 | /*====================================================================== | ||
2 | fmvj18x_cs.c 2.8 2002/03/23 | ||
3 | |||
4 | A fmvj18x (and its compatibles) PCMCIA client driver | ||
5 | |||
6 | Contributed by Shingo Fujimoto, shingo@flab.fujitsu.co.jp | ||
7 | |||
8 | TDK LAK-CD021 and CONTEC C-NET(PC)C support added by | ||
9 | Nobuhiro Katayama, kata-n@po.iijnet.or.jp | ||
10 | |||
11 | The PCMCIA client code is based on code written by David Hinds. | ||
12 | Network code is based on the "FMV-18x driver" by Yutaka TAMIYA | ||
13 | but is actually largely Donald Becker's AT1700 driver, which | ||
14 | carries the following attribution: | ||
15 | |||
16 | Written 1993-94 by Donald Becker. | ||
17 | |||
18 | Copyright 1993 United States Government as represented by the | ||
19 | Director, National Security Agency. | ||
20 | |||
21 | This software may be used and distributed according to the terms | ||
22 | of the GNU General Public License, incorporated herein by reference. | ||
23 | |||
24 | The author may be reached as becker@scyld.com, or C/O | ||
25 | Scyld Computing Corporation | ||
26 | 410 Severn Ave., Suite 210 | ||
27 | Annapolis MD 21403 | ||
28 | |||
29 | ======================================================================*/ | ||
30 | |||
31 | #define DRV_NAME "fmvj18x_cs" | ||
32 | #define DRV_VERSION "2.8" | ||
33 | |||
34 | #include <linux/module.h> | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/ptrace.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/string.h> | ||
40 | #include <linux/timer.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | #include <linux/in.h> | ||
43 | #include <linux/delay.h> | ||
44 | #include <linux/ethtool.h> | ||
45 | #include <linux/netdevice.h> | ||
46 | #include <linux/etherdevice.h> | ||
47 | #include <linux/skbuff.h> | ||
48 | #include <linux/if_arp.h> | ||
49 | #include <linux/ioport.h> | ||
50 | #include <linux/crc32.h> | ||
51 | |||
52 | #include <pcmcia/version.h> | ||
53 | #include <pcmcia/cs_types.h> | ||
54 | #include <pcmcia/cs.h> | ||
55 | #include <pcmcia/cistpl.h> | ||
56 | #include <pcmcia/ciscode.h> | ||
57 | #include <pcmcia/ds.h> | ||
58 | |||
59 | #include <asm/uaccess.h> | ||
60 | #include <asm/io.h> | ||
61 | #include <asm/system.h> | ||
62 | |||
63 | /*====================================================================*/ | ||
64 | |||
65 | /* Module parameters */ | ||
66 | |||
67 | MODULE_DESCRIPTION("fmvj18x and compatible PCMCIA ethernet driver"); | ||
68 | MODULE_LICENSE("GPL"); | ||
69 | |||
70 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) | ||
71 | |||
72 | /* SRAM configuration */ | ||
73 | /* 0:4KB*2 TX buffer else:8KB*2 TX buffer */ | ||
74 | INT_MODULE_PARM(sram_config, 0); | ||
75 | |||
76 | #ifdef PCMCIA_DEBUG | ||
77 | INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); | ||
78 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) | ||
79 | static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23"; | ||
80 | #else | ||
81 | #define DEBUG(n, args...) | ||
82 | #endif | ||
83 | |||
84 | /*====================================================================*/ | ||
85 | /* | ||
86 | PCMCIA event handlers | ||
87 | */ | ||
88 | static void fmvj18x_config(dev_link_t *link); | ||
89 | static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id); | ||
90 | static int fmvj18x_setup_mfc(dev_link_t *link); | ||
91 | static void fmvj18x_release(dev_link_t *link); | ||
92 | static int fmvj18x_event(event_t event, int priority, | ||
93 | event_callback_args_t *args); | ||
94 | static dev_link_t *fmvj18x_attach(void); | ||
95 | static void fmvj18x_detach(dev_link_t *); | ||
96 | |||
97 | /* | ||
98 | LAN controller(MBH86960A) specific routines | ||
99 | */ | ||
100 | static int fjn_config(struct net_device *dev, struct ifmap *map); | ||
101 | static int fjn_open(struct net_device *dev); | ||
102 | static int fjn_close(struct net_device *dev); | ||
103 | static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
104 | static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs); | ||
105 | static void fjn_rx(struct net_device *dev); | ||
106 | static void fjn_reset(struct net_device *dev); | ||
107 | static struct net_device_stats *fjn_get_stats(struct net_device *dev); | ||
108 | static void set_rx_mode(struct net_device *dev); | ||
109 | static void fjn_tx_timeout(struct net_device *dev); | ||
110 | static struct ethtool_ops netdev_ethtool_ops; | ||
111 | |||
112 | static dev_info_t dev_info = "fmvj18x_cs"; | ||
113 | static dev_link_t *dev_list; | ||
114 | |||
115 | /* | ||
116 | card type | ||
117 | */ | ||
118 | typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, | ||
119 | XXX10304 | ||
120 | } cardtype_t; | ||
121 | |||
122 | /* | ||
123 | driver specific data structure | ||
124 | */ | ||
125 | typedef struct local_info_t { | ||
126 | dev_link_t link; | ||
127 | dev_node_t node; | ||
128 | struct net_device_stats stats; | ||
129 | long open_time; | ||
130 | uint tx_started:1; | ||
131 | uint tx_queue; | ||
132 | u_short tx_queue_len; | ||
133 | cardtype_t cardtype; | ||
134 | u_short sent; | ||
135 | u_char mc_filter[8]; | ||
136 | } local_info_t; | ||
137 | |||
138 | #define MC_FILTERBREAK 64 | ||
139 | |||
140 | /*====================================================================*/ | ||
141 | /* | ||
142 | ioport offset from the base address | ||
143 | */ | ||
144 | #define TX_STATUS 0 /* transmit status register */ | ||
145 | #define RX_STATUS 1 /* receive status register */ | ||
146 | #define TX_INTR 2 /* transmit interrupt mask register */ | ||
147 | #define RX_INTR 3 /* receive interrupt mask register */ | ||
148 | #define TX_MODE 4 /* transmit mode register */ | ||
149 | #define RX_MODE 5 /* receive mode register */ | ||
150 | #define CONFIG_0 6 /* configuration register 0 */ | ||
151 | #define CONFIG_1 7 /* configuration register 1 */ | ||
152 | |||
153 | #define NODE_ID 8 /* node ID register (bank 0) */ | ||
154 | #define MAR_ADR 8 /* multicast address registers (bank 1) */ | ||
155 | |||
156 | #define DATAPORT 8 /* buffer mem port registers (bank 2) */ | ||
157 | #define TX_START 10 /* transmit start register */ | ||
158 | #define COL_CTRL 11 /* 16 collision control register */ | ||
159 | #define BMPR12 12 /* reserved */ | ||
160 | #define BMPR13 13 /* reserved */ | ||
161 | #define RX_SKIP 14 /* skip received packet register */ | ||
162 | |||
163 | #define LAN_CTRL 16 /* LAN card control register */ | ||
164 | |||
165 | #define MAC_ID 0x1a /* hardware address */ | ||
166 | #define UNGERMANN_MAC_ID 0x18 /* UNGERMANN-BASS hardware address */ | ||
167 | |||
168 | /* | ||
169 | control bits | ||
170 | */ | ||
171 | #define ENA_TMT_OK 0x80 | ||
172 | #define ENA_TMT_REC 0x20 | ||
173 | #define ENA_COL 0x04 | ||
174 | #define ENA_16_COL 0x02 | ||
175 | #define ENA_TBUS_ERR 0x01 | ||
176 | |||
177 | #define ENA_PKT_RDY 0x80 | ||
178 | #define ENA_BUS_ERR 0x40 | ||
179 | #define ENA_LEN_ERR 0x08 | ||
180 | #define ENA_ALG_ERR 0x04 | ||
181 | #define ENA_CRC_ERR 0x02 | ||
182 | #define ENA_OVR_FLO 0x01 | ||
183 | |||
184 | /* flags */ | ||
185 | #define F_TMT_RDY 0x80 /* can accept new packet */ | ||
186 | #define F_NET_BSY 0x40 /* carrier is detected */ | ||
187 | #define F_TMT_OK 0x20 /* send packet successfully */ | ||
188 | #define F_SRT_PKT 0x10 /* short packet error */ | ||
189 | #define F_COL_ERR 0x04 /* collision error */ | ||
190 | #define F_16_COL 0x02 /* 16 collision error */ | ||
191 | #define F_TBUS_ERR 0x01 /* bus read error */ | ||
192 | |||
193 | #define F_PKT_RDY 0x80 /* packet(s) in buffer */ | ||
194 | #define F_BUS_ERR 0x40 /* bus read error */ | ||
195 | #define F_LEN_ERR 0x08 /* short packet */ | ||
196 | #define F_ALG_ERR 0x04 /* frame error */ | ||
197 | #define F_CRC_ERR 0x02 /* CRC error */ | ||
198 | #define F_OVR_FLO 0x01 /* overflow error */ | ||
199 | |||
200 | #define F_BUF_EMP 0x40 /* receive buffer is empty */ | ||
201 | |||
202 | #define F_SKP_PKT 0x05 /* drop packet in buffer */ | ||
203 | |||
204 | /* default bitmaps */ | ||
205 | #define D_TX_INTR ( ENA_TMT_OK ) | ||
206 | #define D_RX_INTR ( ENA_PKT_RDY | ENA_LEN_ERR \ | ||
207 | | ENA_ALG_ERR | ENA_CRC_ERR | ENA_OVR_FLO ) | ||
208 | #define TX_STAT_M ( F_TMT_RDY ) | ||
209 | #define RX_STAT_M ( F_PKT_RDY | F_LEN_ERR \ | ||
210 | | F_ALG_ERR | F_CRC_ERR | F_OVR_FLO ) | ||
211 | |||
212 | /* commands */ | ||
213 | #define D_TX_MODE 0x06 /* no tests, detect carrier */ | ||
214 | #define ID_MATCHED 0x02 /* (RX_MODE) */ | ||
215 | #define RECV_ALL 0x03 /* (RX_MODE) */ | ||
216 | #define CONFIG0_DFL 0x5a /* 16bit bus, 4K x 2 Tx queues */ | ||
217 | #define CONFIG0_DFL_1 0x5e /* 16bit bus, 8K x 2 Tx queues */ | ||
218 | #define CONFIG0_RST 0xda /* Data Link Controller off (CONFIG_0) */ | ||
219 | #define CONFIG0_RST_1 0xde /* Data Link Controller off (CONFIG_0) */ | ||
220 | #define BANK_0 0xa0 /* bank 0 (CONFIG_1) */ | ||
221 | #define BANK_1 0xa4 /* bank 1 (CONFIG_1) */ | ||
222 | #define BANK_2 0xa8 /* bank 2 (CONFIG_1) */ | ||
223 | #define CHIP_OFF 0x80 /* contrl chip power off (CONFIG_1) */ | ||
224 | #define DO_TX 0x80 /* do transmit packet */ | ||
225 | #define SEND_PKT 0x81 /* send a packet */ | ||
226 | #define AUTO_MODE 0x07 /* Auto skip packet on 16 col detected */ | ||
227 | #define MANU_MODE 0x03 /* Stop and skip packet on 16 col */ | ||
228 | #define TDK_AUTO_MODE 0x47 /* Auto skip packet on 16 col detected */ | ||
229 | #define TDK_MANU_MODE 0x43 /* Stop and skip packet on 16 col */ | ||
230 | #define INTR_OFF 0x0d /* LAN controller ignores interrupts */ | ||
231 | #define INTR_ON 0x1d /* LAN controller will catch interrupts */ | ||
232 | |||
233 | #define TX_TIMEOUT ((400*HZ)/1000) | ||
234 | |||
235 | #define BANK_0U 0x20 /* bank 0 (CONFIG_1) */ | ||
236 | #define BANK_1U 0x24 /* bank 1 (CONFIG_1) */ | ||
237 | #define BANK_2U 0x28 /* bank 2 (CONFIG_1) */ | ||
238 | |||
239 | static dev_link_t *fmvj18x_attach(void) | ||
240 | { | ||
241 | local_info_t *lp; | ||
242 | dev_link_t *link; | ||
243 | struct net_device *dev; | ||
244 | client_reg_t client_reg; | ||
245 | int ret; | ||
246 | |||
247 | DEBUG(0, "fmvj18x_attach()\n"); | ||
248 | |||
249 | /* Make up a FMVJ18x specific data structure */ | ||
250 | dev = alloc_etherdev(sizeof(local_info_t)); | ||
251 | if (!dev) | ||
252 | return NULL; | ||
253 | lp = netdev_priv(dev); | ||
254 | link = &lp->link; | ||
255 | link->priv = dev; | ||
256 | |||
257 | /* The io structure describes IO port mapping */ | ||
258 | link->io.NumPorts1 = 32; | ||
259 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
260 | link->io.IOAddrLines = 5; | ||
261 | |||
262 | /* Interrupt setup */ | ||
263 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
264 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
265 | link->irq.Handler = &fjn_interrupt; | ||
266 | link->irq.Instance = dev; | ||
267 | |||
268 | /* General socket configuration */ | ||
269 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
270 | link->conf.Vcc = 50; | ||
271 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
272 | |||
273 | /* The FMVJ18x specific entries in the device structure. */ | ||
274 | SET_MODULE_OWNER(dev); | ||
275 | dev->hard_start_xmit = &fjn_start_xmit; | ||
276 | dev->set_config = &fjn_config; | ||
277 | dev->get_stats = &fjn_get_stats; | ||
278 | dev->set_multicast_list = &set_rx_mode; | ||
279 | dev->open = &fjn_open; | ||
280 | dev->stop = &fjn_close; | ||
281 | #ifdef HAVE_TX_TIMEOUT | ||
282 | dev->tx_timeout = fjn_tx_timeout; | ||
283 | dev->watchdog_timeo = TX_TIMEOUT; | ||
284 | #endif | ||
285 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | ||
286 | |||
287 | /* Register with Card Services */ | ||
288 | link->next = dev_list; | ||
289 | dev_list = link; | ||
290 | client_reg.dev_info = &dev_info; | ||
291 | client_reg.EventMask = | ||
292 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
293 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
294 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
295 | client_reg.event_handler = &fmvj18x_event; | ||
296 | client_reg.Version = 0x0210; | ||
297 | client_reg.event_callback_args.client_data = link; | ||
298 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
299 | if (ret != 0) { | ||
300 | cs_error(link->handle, RegisterClient, ret); | ||
301 | fmvj18x_detach(link); | ||
302 | return NULL; | ||
303 | } | ||
304 | |||
305 | return link; | ||
306 | } /* fmvj18x_attach */ | ||
307 | |||
308 | /*====================================================================*/ | ||
309 | |||
310 | static void fmvj18x_detach(dev_link_t *link) | ||
311 | { | ||
312 | struct net_device *dev = link->priv; | ||
313 | dev_link_t **linkp; | ||
314 | |||
315 | DEBUG(0, "fmvj18x_detach(0x%p)\n", link); | ||
316 | |||
317 | /* Locate device structure */ | ||
318 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
319 | if (*linkp == link) break; | ||
320 | if (*linkp == NULL) | ||
321 | return; | ||
322 | |||
323 | if (link->dev) | ||
324 | unregister_netdev(dev); | ||
325 | |||
326 | if (link->state & DEV_CONFIG) | ||
327 | fmvj18x_release(link); | ||
328 | |||
329 | /* Break the link with Card Services */ | ||
330 | if (link->handle) | ||
331 | pcmcia_deregister_client(link->handle); | ||
332 | |||
333 | /* Unlink device structure, free pieces */ | ||
334 | *linkp = link->next; | ||
335 | free_netdev(dev); | ||
336 | } /* fmvj18x_detach */ | ||
337 | |||
338 | /*====================================================================*/ | ||
339 | |||
340 | #define CS_CHECK(fn, ret) \ | ||
341 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
342 | |||
343 | static int mfc_try_io_port(dev_link_t *link) | ||
344 | { | ||
345 | int i, ret; | ||
346 | static kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | ||
347 | |||
348 | for (i = 0; i < 5; i++) { | ||
349 | link->io.BasePort2 = serial_base[i]; | ||
350 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; | ||
351 | if (link->io.BasePort2 == 0) { | ||
352 | link->io.NumPorts2 = 0; | ||
353 | printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n"); | ||
354 | } | ||
355 | ret = pcmcia_request_io(link->handle, &link->io); | ||
356 | if (ret == CS_SUCCESS) return ret; | ||
357 | } | ||
358 | return ret; | ||
359 | } | ||
360 | |||
361 | static int ungermann_try_io_port(dev_link_t *link) | ||
362 | { | ||
363 | int ret; | ||
364 | kio_addr_t ioaddr; | ||
365 | /* | ||
366 | Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360 | ||
367 | 0x380,0x3c0 only for ioport. | ||
368 | */ | ||
369 | for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) { | ||
370 | link->io.BasePort1 = ioaddr; | ||
371 | ret = pcmcia_request_io(link->handle, &link->io); | ||
372 | if (ret == CS_SUCCESS) { | ||
373 | /* calculate ConfigIndex value */ | ||
374 | link->conf.ConfigIndex = | ||
375 | ((link->io.BasePort1 & 0x0f0) >> 3) | 0x22; | ||
376 | return ret; | ||
377 | } | ||
378 | } | ||
379 | return ret; /* RequestIO failed */ | ||
380 | } | ||
381 | |||
382 | static void fmvj18x_config(dev_link_t *link) | ||
383 | { | ||
384 | client_handle_t handle = link->handle; | ||
385 | struct net_device *dev = link->priv; | ||
386 | local_info_t *lp = netdev_priv(dev); | ||
387 | tuple_t tuple; | ||
388 | cisparse_t parse; | ||
389 | u_short buf[32]; | ||
390 | int i, last_fn, last_ret, ret; | ||
391 | kio_addr_t ioaddr; | ||
392 | cardtype_t cardtype; | ||
393 | char *card_name = "unknown"; | ||
394 | u_char *node_id; | ||
395 | |||
396 | DEBUG(0, "fmvj18x_config(0x%p)\n", link); | ||
397 | |||
398 | /* | ||
399 | This reads the card's CONFIG tuple to find its configuration | ||
400 | registers. | ||
401 | */ | ||
402 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
403 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
404 | tuple.TupleData = (u_char *)buf; | ||
405 | tuple.TupleDataMax = 64; | ||
406 | tuple.TupleOffset = 0; | ||
407 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
408 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | ||
409 | |||
410 | /* Configure card */ | ||
411 | link->state |= DEV_CONFIG; | ||
412 | |||
413 | link->conf.ConfigBase = parse.config.base; | ||
414 | link->conf.Present = parse.config.rmask[0]; | ||
415 | |||
416 | tuple.DesiredTuple = CISTPL_FUNCE; | ||
417 | tuple.TupleOffset = 0; | ||
418 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { | ||
419 | /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ | ||
420 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
421 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
422 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
423 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | ||
424 | link->conf.ConfigIndex = parse.cftable_entry.index; | ||
425 | tuple.DesiredTuple = CISTPL_MANFID; | ||
426 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) | ||
427 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
428 | else | ||
429 | buf[0] = 0xffff; | ||
430 | switch (le16_to_cpu(buf[0])) { | ||
431 | case MANFID_TDK: | ||
432 | cardtype = TDK; | ||
433 | if (le16_to_cpu(buf[1]) == PRODID_TDK_CF010) { | ||
434 | cs_status_t status; | ||
435 | pcmcia_get_status(handle, &status); | ||
436 | if (status.CardState & CS_EVENT_3VCARD) | ||
437 | link->conf.Vcc = 33; /* inserted in 3.3V slot */ | ||
438 | } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410) { | ||
439 | /* MultiFunction Card */ | ||
440 | link->conf.ConfigBase = 0x800; | ||
441 | link->conf.ConfigIndex = 0x47; | ||
442 | link->io.NumPorts2 = 8; | ||
443 | } | ||
444 | break; | ||
445 | case MANFID_CONTEC: | ||
446 | cardtype = CONTEC; | ||
447 | break; | ||
448 | case MANFID_FUJITSU: | ||
449 | if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10302) | ||
450 | /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302), | ||
451 | but these are MBH10304 based card. */ | ||
452 | cardtype = MBH10304; | ||
453 | else if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) | ||
454 | cardtype = MBH10304; | ||
455 | else | ||
456 | cardtype = LA501; | ||
457 | break; | ||
458 | default: | ||
459 | cardtype = MBH10304; | ||
460 | } | ||
461 | } else { | ||
462 | /* old type card */ | ||
463 | tuple.DesiredTuple = CISTPL_MANFID; | ||
464 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) | ||
465 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
466 | else | ||
467 | buf[0] = 0xffff; | ||
468 | switch (le16_to_cpu(buf[0])) { | ||
469 | case MANFID_FUJITSU: | ||
470 | if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) { | ||
471 | cardtype = XXX10304; /* MBH10304 with buggy CIS */ | ||
472 | link->conf.ConfigIndex = 0x20; | ||
473 | } else { | ||
474 | cardtype = MBH10302; /* NextCom NC5310, etc. */ | ||
475 | link->conf.ConfigIndex = 1; | ||
476 | } | ||
477 | break; | ||
478 | case MANFID_UNGERMANN: | ||
479 | cardtype = UNGERMANN; | ||
480 | break; | ||
481 | default: | ||
482 | cardtype = MBH10302; | ||
483 | link->conf.ConfigIndex = 1; | ||
484 | } | ||
485 | } | ||
486 | |||
487 | if (link->io.NumPorts2 != 0) { | ||
488 | link->irq.Attributes = | ||
489 | IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT; | ||
490 | ret = mfc_try_io_port(link); | ||
491 | if (ret != CS_SUCCESS) goto cs_failed; | ||
492 | } else if (cardtype == UNGERMANN) { | ||
493 | ret = ungermann_try_io_port(link); | ||
494 | if (ret != CS_SUCCESS) goto cs_failed; | ||
495 | } else { | ||
496 | CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); | ||
497 | } | ||
498 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | ||
499 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | ||
500 | dev->irq = link->irq.AssignedIRQ; | ||
501 | dev->base_addr = link->io.BasePort1; | ||
502 | |||
503 | if (link->io.BasePort2 != 0) | ||
504 | fmvj18x_setup_mfc(link); | ||
505 | |||
506 | ioaddr = dev->base_addr; | ||
507 | |||
508 | /* Reset controller */ | ||
509 | if (sram_config == 0) | ||
510 | outb(CONFIG0_RST, ioaddr + CONFIG_0); | ||
511 | else | ||
512 | outb(CONFIG0_RST_1, ioaddr + CONFIG_0); | ||
513 | |||
514 | /* Power On chip and select bank 0 */ | ||
515 | if (cardtype == MBH10302) | ||
516 | outb(BANK_0, ioaddr + CONFIG_1); | ||
517 | else | ||
518 | outb(BANK_0U, ioaddr + CONFIG_1); | ||
519 | |||
520 | /* Set hardware address */ | ||
521 | switch (cardtype) { | ||
522 | case MBH10304: | ||
523 | case TDK: | ||
524 | case LA501: | ||
525 | case CONTEC: | ||
526 | tuple.DesiredTuple = CISTPL_FUNCE; | ||
527 | tuple.TupleOffset = 0; | ||
528 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
529 | tuple.TupleOffset = 0; | ||
530 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
531 | if (cardtype == MBH10304) { | ||
532 | /* MBH10304's CIS_FUNCE is corrupted */ | ||
533 | node_id = &(tuple.TupleData[5]); | ||
534 | card_name = "FMV-J182"; | ||
535 | } else { | ||
536 | while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) { | ||
537 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); | ||
538 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
539 | } | ||
540 | node_id = &(tuple.TupleData[2]); | ||
541 | if( cardtype == TDK ) { | ||
542 | card_name = "TDK LAK-CD021"; | ||
543 | } else if( cardtype == LA501 ) { | ||
544 | card_name = "LA501"; | ||
545 | } else { | ||
546 | card_name = "C-NET(PC)C"; | ||
547 | } | ||
548 | } | ||
549 | /* Read MACID from CIS */ | ||
550 | for (i = 0; i < 6; i++) | ||
551 | dev->dev_addr[i] = node_id[i]; | ||
552 | break; | ||
553 | case UNGERMANN: | ||
554 | /* Read MACID from register */ | ||
555 | for (i = 0; i < 6; i++) | ||
556 | dev->dev_addr[i] = inb(ioaddr + UNGERMANN_MAC_ID + i); | ||
557 | card_name = "Access/CARD"; | ||
558 | break; | ||
559 | case XXX10304: | ||
560 | /* Read MACID from Buggy CIS */ | ||
561 | if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) { | ||
562 | printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n"); | ||
563 | goto failed; | ||
564 | } | ||
565 | for (i = 0 ; i < 6; i++) { | ||
566 | dev->dev_addr[i] = tuple.TupleData[i]; | ||
567 | } | ||
568 | card_name = "FMV-J182"; | ||
569 | break; | ||
570 | case MBH10302: | ||
571 | default: | ||
572 | /* Read MACID from register */ | ||
573 | for (i = 0; i < 6; i++) | ||
574 | dev->dev_addr[i] = inb(ioaddr + MAC_ID + i); | ||
575 | card_name = "FMV-J181"; | ||
576 | break; | ||
577 | } | ||
578 | |||
579 | lp->cardtype = cardtype; | ||
580 | link->dev = &lp->node; | ||
581 | link->state &= ~DEV_CONFIG_PENDING; | ||
582 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
583 | |||
584 | if (register_netdev(dev) != 0) { | ||
585 | printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); | ||
586 | link->dev = NULL; | ||
587 | goto failed; | ||
588 | } | ||
589 | |||
590 | strcpy(lp->node.dev_name, dev->name); | ||
591 | |||
592 | /* print current configuration */ | ||
593 | printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, hw_addr ", | ||
594 | dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", | ||
595 | dev->base_addr, dev->irq); | ||
596 | for (i = 0; i < 6; i++) | ||
597 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); | ||
598 | |||
599 | return; | ||
600 | |||
601 | cs_failed: | ||
602 | /* All Card Services errors end up here */ | ||
603 | cs_error(link->handle, last_fn, last_ret); | ||
604 | failed: | ||
605 | fmvj18x_release(link); | ||
606 | link->state &= ~DEV_CONFIG_PENDING; | ||
607 | |||
608 | } /* fmvj18x_config */ | ||
609 | /*====================================================================*/ | ||
610 | |||
611 | static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id) | ||
612 | { | ||
613 | win_req_t req; | ||
614 | memreq_t mem; | ||
615 | u_char __iomem *base; | ||
616 | int i, j; | ||
617 | |||
618 | /* Allocate a small memory window */ | ||
619 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | ||
620 | req.Base = 0; req.Size = 0; | ||
621 | req.AccessSpeed = 0; | ||
622 | i = pcmcia_request_window(&link->handle, &req, &link->win); | ||
623 | if (i != CS_SUCCESS) { | ||
624 | cs_error(link->handle, RequestWindow, i); | ||
625 | return -1; | ||
626 | } | ||
627 | |||
628 | base = ioremap(req.Base, req.Size); | ||
629 | mem.Page = 0; | ||
630 | mem.CardOffset = 0; | ||
631 | pcmcia_map_mem_page(link->win, &mem); | ||
632 | |||
633 | /* | ||
634 | * MBH10304 CISTPL_FUNCE_LAN_NODE_ID format | ||
635 | * 22 0d xx xx xx 04 06 yy yy yy yy yy yy ff | ||
636 | * 'xx' is garbage. | ||
637 | * 'yy' is MAC address. | ||
638 | */ | ||
639 | for (i = 0; i < 0x200; i++) { | ||
640 | if (readb(base+i*2) == 0x22) { | ||
641 | if (readb(base+(i-1)*2) == 0xff | ||
642 | && readb(base+(i+5)*2) == 0x04 | ||
643 | && readb(base+(i+6)*2) == 0x06 | ||
644 | && readb(base+(i+13)*2) == 0xff) | ||
645 | break; | ||
646 | } | ||
647 | } | ||
648 | |||
649 | if (i != 0x200) { | ||
650 | for (j = 0 ; j < 6; j++,i++) { | ||
651 | node_id[j] = readb(base+(i+7)*2); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | iounmap(base); | ||
656 | j = pcmcia_release_window(link->win); | ||
657 | if (j != CS_SUCCESS) | ||
658 | cs_error(link->handle, ReleaseWindow, j); | ||
659 | return (i != 0x200) ? 0 : -1; | ||
660 | |||
661 | } /* fmvj18x_get_hwinfo */ | ||
662 | /*====================================================================*/ | ||
663 | |||
664 | static int fmvj18x_setup_mfc(dev_link_t *link) | ||
665 | { | ||
666 | win_req_t req; | ||
667 | memreq_t mem; | ||
668 | u_char __iomem *base; | ||
669 | int i, j; | ||
670 | struct net_device *dev = link->priv; | ||
671 | kio_addr_t ioaddr; | ||
672 | |||
673 | /* Allocate a small memory window */ | ||
674 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | ||
675 | req.Base = 0; req.Size = 0; | ||
676 | req.AccessSpeed = 0; | ||
677 | i = pcmcia_request_window(&link->handle, &req, &link->win); | ||
678 | if (i != CS_SUCCESS) { | ||
679 | cs_error(link->handle, RequestWindow, i); | ||
680 | return -1; | ||
681 | } | ||
682 | |||
683 | base = ioremap(req.Base, req.Size); | ||
684 | mem.Page = 0; | ||
685 | mem.CardOffset = 0; | ||
686 | pcmcia_map_mem_page(link->win, &mem); | ||
687 | |||
688 | ioaddr = dev->base_addr; | ||
689 | writeb(0x47, base+0x800); /* Config Option Register of LAN */ | ||
690 | writeb(0x0, base+0x802); /* Config and Status Register */ | ||
691 | |||
692 | writeb(ioaddr & 0xff, base+0x80a); /* I/O Base(Low) of LAN */ | ||
693 | writeb((ioaddr >> 8) & 0xff, base+0x80c); /* I/O Base(High) of LAN */ | ||
694 | |||
695 | writeb(0x45, base+0x820); /* Config Option Register of Modem */ | ||
696 | writeb(0x8, base+0x822); /* Config and Status Register */ | ||
697 | |||
698 | iounmap(base); | ||
699 | j = pcmcia_release_window(link->win); | ||
700 | if (j != CS_SUCCESS) | ||
701 | cs_error(link->handle, ReleaseWindow, j); | ||
702 | return 0; | ||
703 | |||
704 | } | ||
705 | /*====================================================================*/ | ||
706 | |||
707 | static void fmvj18x_release(dev_link_t *link) | ||
708 | { | ||
709 | |||
710 | DEBUG(0, "fmvj18x_release(0x%p)\n", link); | ||
711 | |||
712 | /* Don't bother checking to see if these succeed or not */ | ||
713 | pcmcia_release_window(link->win); | ||
714 | pcmcia_release_configuration(link->handle); | ||
715 | pcmcia_release_io(link->handle, &link->io); | ||
716 | pcmcia_release_irq(link->handle, &link->irq); | ||
717 | |||
718 | link->state &= ~DEV_CONFIG; | ||
719 | } | ||
720 | |||
721 | /*====================================================================*/ | ||
722 | |||
723 | static int fmvj18x_event(event_t event, int priority, | ||
724 | event_callback_args_t *args) | ||
725 | { | ||
726 | dev_link_t *link = args->client_data; | ||
727 | struct net_device *dev = link->priv; | ||
728 | |||
729 | DEBUG(1, "fmvj18x_event(0x%06x)\n", event); | ||
730 | |||
731 | switch (event) { | ||
732 | case CS_EVENT_CARD_REMOVAL: | ||
733 | link->state &= ~DEV_PRESENT; | ||
734 | if (link->state & DEV_CONFIG) | ||
735 | netif_device_detach(dev); | ||
736 | break; | ||
737 | case CS_EVENT_CARD_INSERTION: | ||
738 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
739 | fmvj18x_config(link); | ||
740 | break; | ||
741 | case CS_EVENT_PM_SUSPEND: | ||
742 | link->state |= DEV_SUSPEND; | ||
743 | /* Fall through... */ | ||
744 | case CS_EVENT_RESET_PHYSICAL: | ||
745 | if (link->state & DEV_CONFIG) { | ||
746 | if (link->open) | ||
747 | netif_device_detach(dev); | ||
748 | pcmcia_release_configuration(link->handle); | ||
749 | } | ||
750 | break; | ||
751 | case CS_EVENT_PM_RESUME: | ||
752 | link->state &= ~DEV_SUSPEND; | ||
753 | /* Fall through... */ | ||
754 | case CS_EVENT_CARD_RESET: | ||
755 | if (link->state & DEV_CONFIG) { | ||
756 | pcmcia_request_configuration(link->handle, &link->conf); | ||
757 | if (link->open) { | ||
758 | fjn_reset(dev); | ||
759 | netif_device_attach(dev); | ||
760 | } | ||
761 | } | ||
762 | break; | ||
763 | } | ||
764 | return 0; | ||
765 | } /* fmvj18x_event */ | ||
766 | |||
767 | static struct pcmcia_driver fmvj18x_cs_driver = { | ||
768 | .owner = THIS_MODULE, | ||
769 | .drv = { | ||
770 | .name = "fmvj18x_cs", | ||
771 | }, | ||
772 | .attach = fmvj18x_attach, | ||
773 | .detach = fmvj18x_detach, | ||
774 | }; | ||
775 | |||
776 | static int __init init_fmvj18x_cs(void) | ||
777 | { | ||
778 | return pcmcia_register_driver(&fmvj18x_cs_driver); | ||
779 | } | ||
780 | |||
781 | static void __exit exit_fmvj18x_cs(void) | ||
782 | { | ||
783 | pcmcia_unregister_driver(&fmvj18x_cs_driver); | ||
784 | BUG_ON(dev_list != NULL); | ||
785 | } | ||
786 | |||
787 | module_init(init_fmvj18x_cs); | ||
788 | module_exit(exit_fmvj18x_cs); | ||
789 | |||
790 | /*====================================================================*/ | ||
791 | |||
792 | static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
793 | { | ||
794 | struct net_device *dev = dev_id; | ||
795 | local_info_t *lp = netdev_priv(dev); | ||
796 | kio_addr_t ioaddr; | ||
797 | unsigned short tx_stat, rx_stat; | ||
798 | |||
799 | if (lp == NULL) { | ||
800 | printk(KERN_NOTICE "fjn_interrupt(): irq %d for " | ||
801 | "unknown device.\n", irq); | ||
802 | return IRQ_NONE; | ||
803 | } | ||
804 | ioaddr = dev->base_addr; | ||
805 | |||
806 | /* avoid multiple interrupts */ | ||
807 | outw(0x0000, ioaddr + TX_INTR); | ||
808 | |||
809 | /* wait for a while */ | ||
810 | udelay(1); | ||
811 | |||
812 | /* get status */ | ||
813 | tx_stat = inb(ioaddr + TX_STATUS); | ||
814 | rx_stat = inb(ioaddr + RX_STATUS); | ||
815 | |||
816 | /* clear status */ | ||
817 | outb(tx_stat, ioaddr + TX_STATUS); | ||
818 | outb(rx_stat, ioaddr + RX_STATUS); | ||
819 | |||
820 | DEBUG(4, "%s: interrupt, rx_status %02x.\n", dev->name, rx_stat); | ||
821 | DEBUG(4, " tx_status %02x.\n", tx_stat); | ||
822 | |||
823 | if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) { | ||
824 | /* there is packet(s) in rx buffer */ | ||
825 | fjn_rx(dev); | ||
826 | } | ||
827 | if (tx_stat & F_TMT_RDY) { | ||
828 | lp->stats.tx_packets += lp->sent ; | ||
829 | lp->sent = 0 ; | ||
830 | if (lp->tx_queue) { | ||
831 | outb(DO_TX | lp->tx_queue, ioaddr + TX_START); | ||
832 | lp->sent = lp->tx_queue ; | ||
833 | lp->tx_queue = 0; | ||
834 | lp->tx_queue_len = 0; | ||
835 | dev->trans_start = jiffies; | ||
836 | } else { | ||
837 | lp->tx_started = 0; | ||
838 | } | ||
839 | netif_wake_queue(dev); | ||
840 | } | ||
841 | DEBUG(4, "%s: exiting interrupt,\n", dev->name); | ||
842 | DEBUG(4, " tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat); | ||
843 | |||
844 | outb(D_TX_INTR, ioaddr + TX_INTR); | ||
845 | outb(D_RX_INTR, ioaddr + RX_INTR); | ||
846 | return IRQ_HANDLED; | ||
847 | |||
848 | } /* fjn_interrupt */ | ||
849 | |||
850 | /*====================================================================*/ | ||
851 | |||
852 | static void fjn_tx_timeout(struct net_device *dev) | ||
853 | { | ||
854 | struct local_info_t *lp = netdev_priv(dev); | ||
855 | kio_addr_t ioaddr = dev->base_addr; | ||
856 | |||
857 | printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n", | ||
858 | dev->name, htons(inw(ioaddr + TX_STATUS)), | ||
859 | inb(ioaddr + TX_STATUS) & F_TMT_RDY | ||
860 | ? "IRQ conflict" : "network cable problem"); | ||
861 | printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x " | ||
862 | "%04x %04x %04x %04x %04x.\n", | ||
863 | dev->name, htons(inw(ioaddr + 0)), | ||
864 | htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)), | ||
865 | htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)), | ||
866 | htons(inw(ioaddr +10)), htons(inw(ioaddr +12)), | ||
867 | htons(inw(ioaddr +14))); | ||
868 | lp->stats.tx_errors++; | ||
869 | /* ToDo: We should try to restart the adaptor... */ | ||
870 | local_irq_disable(); | ||
871 | fjn_reset(dev); | ||
872 | |||
873 | lp->tx_started = 0; | ||
874 | lp->tx_queue = 0; | ||
875 | lp->tx_queue_len = 0; | ||
876 | lp->sent = 0; | ||
877 | lp->open_time = jiffies; | ||
878 | local_irq_enable(); | ||
879 | netif_wake_queue(dev); | ||
880 | } | ||
881 | |||
882 | static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
883 | { | ||
884 | struct local_info_t *lp = netdev_priv(dev); | ||
885 | kio_addr_t ioaddr = dev->base_addr; | ||
886 | short length = skb->len; | ||
887 | |||
888 | if (length < ETH_ZLEN) | ||
889 | { | ||
890 | skb = skb_padto(skb, ETH_ZLEN); | ||
891 | if (skb == NULL) | ||
892 | return 0; | ||
893 | length = ETH_ZLEN; | ||
894 | } | ||
895 | |||
896 | netif_stop_queue(dev); | ||
897 | |||
898 | { | ||
899 | unsigned char *buf = skb->data; | ||
900 | |||
901 | if (length > ETH_FRAME_LEN) { | ||
902 | printk(KERN_NOTICE "%s: Attempting to send a large packet" | ||
903 | " (%d bytes).\n", dev->name, length); | ||
904 | return 1; | ||
905 | } | ||
906 | |||
907 | DEBUG(4, "%s: Transmitting a packet of length %lu.\n", | ||
908 | dev->name, (unsigned long)skb->len); | ||
909 | lp->stats.tx_bytes += skb->len; | ||
910 | |||
911 | /* Disable both interrupts. */ | ||
912 | outw(0x0000, ioaddr + TX_INTR); | ||
913 | |||
914 | /* wait for a while */ | ||
915 | udelay(1); | ||
916 | |||
917 | outw(length, ioaddr + DATAPORT); | ||
918 | outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); | ||
919 | |||
920 | lp->tx_queue++; | ||
921 | lp->tx_queue_len += ((length+3) & ~1); | ||
922 | |||
923 | if (lp->tx_started == 0) { | ||
924 | /* If the Tx is idle, always trigger a transmit. */ | ||
925 | outb(DO_TX | lp->tx_queue, ioaddr + TX_START); | ||
926 | lp->sent = lp->tx_queue ; | ||
927 | lp->tx_queue = 0; | ||
928 | lp->tx_queue_len = 0; | ||
929 | dev->trans_start = jiffies; | ||
930 | lp->tx_started = 1; | ||
931 | netif_start_queue(dev); | ||
932 | } else { | ||
933 | if( sram_config == 0 ) { | ||
934 | if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) ) | ||
935 | /* Yes, there is room for one more packet. */ | ||
936 | netif_start_queue(dev); | ||
937 | } else { | ||
938 | if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) && | ||
939 | lp->tx_queue < 127 ) | ||
940 | /* Yes, there is room for one more packet. */ | ||
941 | netif_start_queue(dev); | ||
942 | } | ||
943 | } | ||
944 | |||
945 | /* Re-enable interrupts */ | ||
946 | outb(D_TX_INTR, ioaddr + TX_INTR); | ||
947 | outb(D_RX_INTR, ioaddr + RX_INTR); | ||
948 | } | ||
949 | dev_kfree_skb (skb); | ||
950 | |||
951 | return 0; | ||
952 | } /* fjn_start_xmit */ | ||
953 | |||
954 | /*====================================================================*/ | ||
955 | |||
956 | static void fjn_reset(struct net_device *dev) | ||
957 | { | ||
958 | struct local_info_t *lp = netdev_priv(dev); | ||
959 | kio_addr_t ioaddr = dev->base_addr; | ||
960 | int i; | ||
961 | |||
962 | DEBUG(4, "fjn_reset(%s) called.\n",dev->name); | ||
963 | |||
964 | /* Reset controller */ | ||
965 | if( sram_config == 0 ) | ||
966 | outb(CONFIG0_RST, ioaddr + CONFIG_0); | ||
967 | else | ||
968 | outb(CONFIG0_RST_1, ioaddr + CONFIG_0); | ||
969 | |||
970 | /* Power On chip and select bank 0 */ | ||
971 | if (lp->cardtype == MBH10302) | ||
972 | outb(BANK_0, ioaddr + CONFIG_1); | ||
973 | else | ||
974 | outb(BANK_0U, ioaddr + CONFIG_1); | ||
975 | |||
976 | /* Set Tx modes */ | ||
977 | outb(D_TX_MODE, ioaddr + TX_MODE); | ||
978 | /* set Rx modes */ | ||
979 | outb(ID_MATCHED, ioaddr + RX_MODE); | ||
980 | |||
981 | /* Set hardware address */ | ||
982 | for (i = 0; i < 6; i++) | ||
983 | outb(dev->dev_addr[i], ioaddr + NODE_ID + i); | ||
984 | |||
985 | /* Switch to bank 1 */ | ||
986 | if (lp->cardtype == MBH10302) | ||
987 | outb(BANK_1, ioaddr + CONFIG_1); | ||
988 | else | ||
989 | outb(BANK_1U, ioaddr + CONFIG_1); | ||
990 | |||
991 | /* set the multicast table to accept none. */ | ||
992 | for (i = 0; i < 6; i++) | ||
993 | outb(0x00, ioaddr + MAR_ADR + i); | ||
994 | |||
995 | /* Switch to bank 2 (runtime mode) */ | ||
996 | if (lp->cardtype == MBH10302) | ||
997 | outb(BANK_2, ioaddr + CONFIG_1); | ||
998 | else | ||
999 | outb(BANK_2U, ioaddr + CONFIG_1); | ||
1000 | |||
1001 | /* set 16col ctrl bits */ | ||
1002 | if( lp->cardtype == TDK || lp->cardtype == CONTEC) | ||
1003 | outb(TDK_AUTO_MODE, ioaddr + COL_CTRL); | ||
1004 | else | ||
1005 | outb(AUTO_MODE, ioaddr + COL_CTRL); | ||
1006 | |||
1007 | /* clear Reserved Regs */ | ||
1008 | outb(0x00, ioaddr + BMPR12); | ||
1009 | outb(0x00, ioaddr + BMPR13); | ||
1010 | |||
1011 | /* reset Skip packet reg. */ | ||
1012 | outb(0x01, ioaddr + RX_SKIP); | ||
1013 | |||
1014 | /* Enable Tx and Rx */ | ||
1015 | if( sram_config == 0 ) | ||
1016 | outb(CONFIG0_DFL, ioaddr + CONFIG_0); | ||
1017 | else | ||
1018 | outb(CONFIG0_DFL_1, ioaddr + CONFIG_0); | ||
1019 | |||
1020 | /* Init receive pointer ? */ | ||
1021 | inw(ioaddr + DATAPORT); | ||
1022 | inw(ioaddr + DATAPORT); | ||
1023 | |||
1024 | /* Clear all status */ | ||
1025 | outb(0xff, ioaddr + TX_STATUS); | ||
1026 | outb(0xff, ioaddr + RX_STATUS); | ||
1027 | |||
1028 | if (lp->cardtype == MBH10302) | ||
1029 | outb(INTR_OFF, ioaddr + LAN_CTRL); | ||
1030 | |||
1031 | /* Turn on Rx interrupts */ | ||
1032 | outb(D_TX_INTR, ioaddr + TX_INTR); | ||
1033 | outb(D_RX_INTR, ioaddr + RX_INTR); | ||
1034 | |||
1035 | /* Turn on interrupts from LAN card controller */ | ||
1036 | if (lp->cardtype == MBH10302) | ||
1037 | outb(INTR_ON, ioaddr + LAN_CTRL); | ||
1038 | } /* fjn_reset */ | ||
1039 | |||
1040 | /*====================================================================*/ | ||
1041 | |||
1042 | static void fjn_rx(struct net_device *dev) | ||
1043 | { | ||
1044 | struct local_info_t *lp = netdev_priv(dev); | ||
1045 | kio_addr_t ioaddr = dev->base_addr; | ||
1046 | int boguscount = 10; /* 5 -> 10: by agy 19940922 */ | ||
1047 | |||
1048 | DEBUG(4, "%s: in rx_packet(), rx_status %02x.\n", | ||
1049 | dev->name, inb(ioaddr + RX_STATUS)); | ||
1050 | |||
1051 | while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) { | ||
1052 | u_short status = inw(ioaddr + DATAPORT); | ||
1053 | |||
1054 | DEBUG(4, "%s: Rxing packet mode %02x status %04x.\n", | ||
1055 | dev->name, inb(ioaddr + RX_MODE), status); | ||
1056 | #ifndef final_version | ||
1057 | if (status == 0) { | ||
1058 | outb(F_SKP_PKT, ioaddr + RX_SKIP); | ||
1059 | break; | ||
1060 | } | ||
1061 | #endif | ||
1062 | if ((status & 0xF0) != 0x20) { /* There was an error. */ | ||
1063 | lp->stats.rx_errors++; | ||
1064 | if (status & F_LEN_ERR) lp->stats.rx_length_errors++; | ||
1065 | if (status & F_ALG_ERR) lp->stats.rx_frame_errors++; | ||
1066 | if (status & F_CRC_ERR) lp->stats.rx_crc_errors++; | ||
1067 | if (status & F_OVR_FLO) lp->stats.rx_over_errors++; | ||
1068 | } else { | ||
1069 | u_short pkt_len = inw(ioaddr + DATAPORT); | ||
1070 | /* Malloc up new buffer. */ | ||
1071 | struct sk_buff *skb; | ||
1072 | |||
1073 | if (pkt_len > 1550) { | ||
1074 | printk(KERN_NOTICE "%s: The FMV-18x claimed a very " | ||
1075 | "large packet, size %d.\n", dev->name, pkt_len); | ||
1076 | outb(F_SKP_PKT, ioaddr + RX_SKIP); | ||
1077 | lp->stats.rx_errors++; | ||
1078 | break; | ||
1079 | } | ||
1080 | skb = dev_alloc_skb(pkt_len+2); | ||
1081 | if (skb == NULL) { | ||
1082 | printk(KERN_NOTICE "%s: Memory squeeze, dropping " | ||
1083 | "packet (len %d).\n", dev->name, pkt_len); | ||
1084 | outb(F_SKP_PKT, ioaddr + RX_SKIP); | ||
1085 | lp->stats.rx_dropped++; | ||
1086 | break; | ||
1087 | } | ||
1088 | skb->dev = dev; | ||
1089 | |||
1090 | skb_reserve(skb, 2); | ||
1091 | insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), | ||
1092 | (pkt_len + 1) >> 1); | ||
1093 | skb->protocol = eth_type_trans(skb, dev); | ||
1094 | |||
1095 | #ifdef PCMCIA_DEBUG | ||
1096 | if (pc_debug > 5) { | ||
1097 | int i; | ||
1098 | printk(KERN_DEBUG "%s: Rxed packet of length %d: ", | ||
1099 | dev->name, pkt_len); | ||
1100 | for (i = 0; i < 14; i++) | ||
1101 | printk(" %02x", skb->data[i]); | ||
1102 | printk(".\n"); | ||
1103 | } | ||
1104 | #endif | ||
1105 | |||
1106 | netif_rx(skb); | ||
1107 | dev->last_rx = jiffies; | ||
1108 | lp->stats.rx_packets++; | ||
1109 | lp->stats.rx_bytes += pkt_len; | ||
1110 | } | ||
1111 | if (--boguscount <= 0) | ||
1112 | break; | ||
1113 | } | ||
1114 | |||
1115 | /* If any worth-while packets have been received, dev_rint() | ||
1116 | has done a netif_wake_queue() for us and will work on them | ||
1117 | when we get to the bottom-half routine. */ | ||
1118 | /* | ||
1119 | if (lp->cardtype != TDK) { | ||
1120 | int i; | ||
1121 | for (i = 0; i < 20; i++) { | ||
1122 | if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP) | ||
1123 | break; | ||
1124 | (void)inw(ioaddr + DATAPORT); /+ dummy status read +/ | ||
1125 | outb(F_SKP_PKT, ioaddr + RX_SKIP); | ||
1126 | } | ||
1127 | |||
1128 | if (i > 0) | ||
1129 | DEBUG(5, "%s: Exint Rx packet with mode %02x after " | ||
1130 | "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i); | ||
1131 | } | ||
1132 | */ | ||
1133 | |||
1134 | return; | ||
1135 | } /* fjn_rx */ | ||
1136 | |||
1137 | /*====================================================================*/ | ||
1138 | |||
1139 | static void netdev_get_drvinfo(struct net_device *dev, | ||
1140 | struct ethtool_drvinfo *info) | ||
1141 | { | ||
1142 | strcpy(info->driver, DRV_NAME); | ||
1143 | strcpy(info->version, DRV_VERSION); | ||
1144 | sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr); | ||
1145 | } | ||
1146 | |||
1147 | #ifdef PCMCIA_DEBUG | ||
1148 | static u32 netdev_get_msglevel(struct net_device *dev) | ||
1149 | { | ||
1150 | return pc_debug; | ||
1151 | } | ||
1152 | |||
1153 | static void netdev_set_msglevel(struct net_device *dev, u32 level) | ||
1154 | { | ||
1155 | pc_debug = level; | ||
1156 | } | ||
1157 | #endif /* PCMCIA_DEBUG */ | ||
1158 | |||
1159 | static struct ethtool_ops netdev_ethtool_ops = { | ||
1160 | .get_drvinfo = netdev_get_drvinfo, | ||
1161 | #ifdef PCMCIA_DEBUG | ||
1162 | .get_msglevel = netdev_get_msglevel, | ||
1163 | .set_msglevel = netdev_set_msglevel, | ||
1164 | #endif /* PCMCIA_DEBUG */ | ||
1165 | }; | ||
1166 | |||
1167 | static int fjn_config(struct net_device *dev, struct ifmap *map){ | ||
1168 | return 0; | ||
1169 | } | ||
1170 | |||
1171 | static int fjn_open(struct net_device *dev) | ||
1172 | { | ||
1173 | struct local_info_t *lp = netdev_priv(dev); | ||
1174 | dev_link_t *link = &lp->link; | ||
1175 | |||
1176 | DEBUG(4, "fjn_open('%s').\n", dev->name); | ||
1177 | |||
1178 | if (!DEV_OK(link)) | ||
1179 | return -ENODEV; | ||
1180 | |||
1181 | link->open++; | ||
1182 | |||
1183 | fjn_reset(dev); | ||
1184 | |||
1185 | lp->tx_started = 0; | ||
1186 | lp->tx_queue = 0; | ||
1187 | lp->tx_queue_len = 0; | ||
1188 | lp->open_time = jiffies; | ||
1189 | netif_start_queue(dev); | ||
1190 | |||
1191 | return 0; | ||
1192 | } /* fjn_open */ | ||
1193 | |||
1194 | /*====================================================================*/ | ||
1195 | |||
1196 | static int fjn_close(struct net_device *dev) | ||
1197 | { | ||
1198 | struct local_info_t *lp = netdev_priv(dev); | ||
1199 | dev_link_t *link = &lp->link; | ||
1200 | kio_addr_t ioaddr = dev->base_addr; | ||
1201 | |||
1202 | DEBUG(4, "fjn_close('%s').\n", dev->name); | ||
1203 | |||
1204 | lp->open_time = 0; | ||
1205 | netif_stop_queue(dev); | ||
1206 | |||
1207 | /* Set configuration register 0 to disable Tx and Rx. */ | ||
1208 | if( sram_config == 0 ) | ||
1209 | outb(CONFIG0_RST ,ioaddr + CONFIG_0); | ||
1210 | else | ||
1211 | outb(CONFIG0_RST_1 ,ioaddr + CONFIG_0); | ||
1212 | |||
1213 | /* Update the statistics -- ToDo. */ | ||
1214 | |||
1215 | /* Power-down the chip. Green, green, green! */ | ||
1216 | outb(CHIP_OFF ,ioaddr + CONFIG_1); | ||
1217 | |||
1218 | /* Set the ethernet adaptor disable IRQ */ | ||
1219 | if (lp->cardtype == MBH10302) | ||
1220 | outb(INTR_OFF, ioaddr + LAN_CTRL); | ||
1221 | |||
1222 | link->open--; | ||
1223 | |||
1224 | return 0; | ||
1225 | } /* fjn_close */ | ||
1226 | |||
1227 | /*====================================================================*/ | ||
1228 | |||
1229 | static struct net_device_stats *fjn_get_stats(struct net_device *dev) | ||
1230 | { | ||
1231 | local_info_t *lp = netdev_priv(dev); | ||
1232 | return &lp->stats; | ||
1233 | } /* fjn_get_stats */ | ||
1234 | |||
1235 | /*====================================================================*/ | ||
1236 | |||
1237 | /* | ||
1238 | Set the multicast/promiscuous mode for this adaptor. | ||
1239 | */ | ||
1240 | |||
1241 | static void set_rx_mode(struct net_device *dev) | ||
1242 | { | ||
1243 | kio_addr_t ioaddr = dev->base_addr; | ||
1244 | struct local_info_t *lp = netdev_priv(dev); | ||
1245 | u_char mc_filter[8]; /* Multicast hash filter */ | ||
1246 | u_long flags; | ||
1247 | int i; | ||
1248 | |||
1249 | if (dev->flags & IFF_PROMISC) { | ||
1250 | /* Unconditionally log net taps. */ | ||
1251 | printk("%s: Promiscuous mode enabled.\n", dev->name); | ||
1252 | memset(mc_filter, 0xff, sizeof(mc_filter)); | ||
1253 | outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */ | ||
1254 | } else if (dev->mc_count > MC_FILTERBREAK | ||
1255 | || (dev->flags & IFF_ALLMULTI)) { | ||
1256 | /* Too many to filter perfectly -- accept all multicasts. */ | ||
1257 | memset(mc_filter, 0xff, sizeof(mc_filter)); | ||
1258 | outb(2, ioaddr + RX_MODE); /* Use normal mode. */ | ||
1259 | } else if (dev->mc_count == 0) { | ||
1260 | memset(mc_filter, 0x00, sizeof(mc_filter)); | ||
1261 | outb(1, ioaddr + RX_MODE); /* Ignore almost all multicasts. */ | ||
1262 | } else { | ||
1263 | struct dev_mc_list *mclist; | ||
1264 | int i; | ||
1265 | |||
1266 | memset(mc_filter, 0, sizeof(mc_filter)); | ||
1267 | for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; | ||
1268 | i++, mclist = mclist->next) { | ||
1269 | unsigned int bit = | ||
1270 | ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f; | ||
1271 | mc_filter[bit >> 3] |= (1 << bit); | ||
1272 | } | ||
1273 | } | ||
1274 | |||
1275 | local_irq_save(flags); | ||
1276 | if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) { | ||
1277 | int saved_bank = inb(ioaddr + CONFIG_1); | ||
1278 | /* Switch to bank 1 and set the multicast table. */ | ||
1279 | outb(0xe4, ioaddr + CONFIG_1); | ||
1280 | for (i = 0; i < 8; i++) | ||
1281 | outb(mc_filter[i], ioaddr + 8 + i); | ||
1282 | memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter)); | ||
1283 | outb(saved_bank, ioaddr + CONFIG_1); | ||
1284 | } | ||
1285 | local_irq_restore(flags); | ||
1286 | } | ||
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c new file mode 100644 index 000000000000..3107ccfe8f3d --- /dev/null +++ b/drivers/net/pcmcia/ibmtr_cs.c | |||
@@ -0,0 +1,535 @@ | |||
1 | /*====================================================================== | ||
2 | |||
3 | A PCMCIA token-ring driver for IBM-based cards | ||
4 | |||
5 | This driver supports the IBM PCMCIA Token-Ring Card. | ||
6 | Written by Steve Kipisz, kipisz@vnet.ibm.com or | ||
7 | bungy@ibm.net | ||
8 | |||
9 | Written 1995,1996. | ||
10 | |||
11 | This code is based on pcnet_cs.c from David Hinds. | ||
12 | |||
13 | V2.2.0 February 1999 - Mike Phillips phillim@amtrak.com | ||
14 | |||
15 | Linux V2.2.x presented significant changes to the underlying | ||
16 | ibmtr.c code. Mainly the code became a lot more organized and | ||
17 | modular. | ||
18 | |||
19 | This caused the old PCMCIA Token Ring driver to give up and go | ||
20 | home early. Instead of just patching the old code to make it | ||
21 | work, the PCMCIA code has been streamlined, updated and possibly | ||
22 | improved. | ||
23 | |||
24 | This code now only contains code required for the Card Services. | ||
25 | All we do here is set the card up enough so that the real ibmtr.c | ||
26 | driver can find it and work with it properly. | ||
27 | |||
28 | i.e. We set up the io port, irq, mmio memory and shared ram | ||
29 | memory. This enables ibmtr_probe in ibmtr.c to find the card and | ||
30 | configure it as though it was a normal ISA and/or PnP card. | ||
31 | |||
32 | CHANGES | ||
33 | |||
34 | v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com) | ||
35 | Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c | ||
36 | |||
37 | v2.2.7 May 1999 Mike Phillips (phillim@amtrak.com) | ||
38 | Updated to version 2.2.7 to match the first version of the kernel | ||
39 | that the modification to ibmtr.c were incorporated into. | ||
40 | |||
41 | v2.2.17 July 2000 Burt Silverman (burts@us.ibm.com) | ||
42 | Address translation feature of PCMCIA controller is usable so | ||
43 | memory windows can be placed in High memory (meaning above | ||
44 | 0xFFFFF.) | ||
45 | |||
46 | ======================================================================*/ | ||
47 | |||
48 | #include <linux/kernel.h> | ||
49 | #include <linux/init.h> | ||
50 | #include <linux/ptrace.h> | ||
51 | #include <linux/slab.h> | ||
52 | #include <linux/string.h> | ||
53 | #include <linux/timer.h> | ||
54 | #include <linux/module.h> | ||
55 | #include <linux/ethtool.h> | ||
56 | #include <linux/netdevice.h> | ||
57 | #include <linux/trdevice.h> | ||
58 | #include <linux/ibmtr.h> | ||
59 | |||
60 | #include <pcmcia/version.h> | ||
61 | #include <pcmcia/cs_types.h> | ||
62 | #include <pcmcia/cs.h> | ||
63 | #include <pcmcia/cistpl.h> | ||
64 | #include <pcmcia/ds.h> | ||
65 | |||
66 | #include <asm/uaccess.h> | ||
67 | #include <asm/io.h> | ||
68 | #include <asm/system.h> | ||
69 | |||
70 | #define PCMCIA | ||
71 | #include "../tokenring/ibmtr.c" | ||
72 | |||
73 | #ifdef PCMCIA_DEBUG | ||
74 | static int pc_debug = PCMCIA_DEBUG; | ||
75 | module_param(pc_debug, int, 0); | ||
76 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) | ||
77 | static char *version = | ||
78 | "ibmtr_cs.c 1.10 1996/01/06 05:19:00 (Steve Kipisz)\n" | ||
79 | " 2.2.7 1999/05/03 12:00:00 (Mike Phillips)\n" | ||
80 | " 2.4.2 2001/30/28 Midnight (Burt Silverman)\n"; | ||
81 | #else | ||
82 | #define DEBUG(n, args...) | ||
83 | #endif | ||
84 | |||
85 | /*====================================================================*/ | ||
86 | |||
87 | /* Parameters that can be set with 'insmod' */ | ||
88 | |||
89 | /* MMIO base address */ | ||
90 | static u_long mmiobase = 0xce000; | ||
91 | |||
92 | /* SRAM base address */ | ||
93 | static u_long srambase = 0xd0000; | ||
94 | |||
95 | /* SRAM size 8,16,32,64 */ | ||
96 | static u_long sramsize = 64; | ||
97 | |||
98 | /* Ringspeed 4,16 */ | ||
99 | static int ringspeed = 16; | ||
100 | |||
101 | module_param(mmiobase, ulong, 0); | ||
102 | module_param(srambase, ulong, 0); | ||
103 | module_param(sramsize, ulong, 0); | ||
104 | module_param(ringspeed, int, 0); | ||
105 | MODULE_LICENSE("GPL"); | ||
106 | |||
107 | /*====================================================================*/ | ||
108 | |||
109 | static void ibmtr_config(dev_link_t *link); | ||
110 | static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase); | ||
111 | static void ibmtr_release(dev_link_t *link); | ||
112 | static int ibmtr_event(event_t event, int priority, | ||
113 | event_callback_args_t *args); | ||
114 | |||
115 | static dev_info_t dev_info = "ibmtr_cs"; | ||
116 | |||
117 | static dev_link_t *ibmtr_attach(void); | ||
118 | static void ibmtr_detach(dev_link_t *); | ||
119 | |||
120 | static dev_link_t *dev_list; | ||
121 | |||
122 | extern int ibmtr_probe_card(struct net_device *dev); | ||
123 | extern irqreturn_t tok_interrupt (int irq, void *dev_id, struct pt_regs *regs); | ||
124 | |||
125 | /*====================================================================*/ | ||
126 | |||
127 | typedef struct ibmtr_dev_t { | ||
128 | dev_link_t link; | ||
129 | struct net_device *dev; | ||
130 | dev_node_t node; | ||
131 | window_handle_t sram_win_handle; | ||
132 | struct tok_info *ti; | ||
133 | } ibmtr_dev_t; | ||
134 | |||
135 | static void netdev_get_drvinfo(struct net_device *dev, | ||
136 | struct ethtool_drvinfo *info) | ||
137 | { | ||
138 | strcpy(info->driver, "ibmtr_cs"); | ||
139 | } | ||
140 | |||
141 | static struct ethtool_ops netdev_ethtool_ops = { | ||
142 | .get_drvinfo = netdev_get_drvinfo, | ||
143 | }; | ||
144 | |||
145 | /*====================================================================== | ||
146 | |||
147 | ibmtr_attach() creates an "instance" of the driver, allocating | ||
148 | local data structures for one device. The device is registered | ||
149 | with Card Services. | ||
150 | |||
151 | ======================================================================*/ | ||
152 | |||
153 | static dev_link_t *ibmtr_attach(void) | ||
154 | { | ||
155 | ibmtr_dev_t *info; | ||
156 | dev_link_t *link; | ||
157 | struct net_device *dev; | ||
158 | client_reg_t client_reg; | ||
159 | int ret; | ||
160 | |||
161 | DEBUG(0, "ibmtr_attach()\n"); | ||
162 | |||
163 | /* Create new token-ring device */ | ||
164 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
165 | if (!info) return NULL; | ||
166 | memset(info,0,sizeof(*info)); | ||
167 | dev = alloc_trdev(sizeof(struct tok_info)); | ||
168 | if (!dev) { | ||
169 | kfree(info); | ||
170 | return NULL; | ||
171 | } | ||
172 | |||
173 | link = &info->link; | ||
174 | link->priv = info; | ||
175 | info->ti = netdev_priv(dev); | ||
176 | |||
177 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
178 | link->io.NumPorts1 = 4; | ||
179 | link->io.IOAddrLines = 16; | ||
180 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
181 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
182 | link->irq.Handler = &tok_interrupt; | ||
183 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
184 | link->conf.Vcc = 50; | ||
185 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
186 | link->conf.Present = PRESENT_OPTION; | ||
187 | |||
188 | link->irq.Instance = info->dev = dev; | ||
189 | |||
190 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | ||
191 | |||
192 | /* Register with Card Services */ | ||
193 | link->next = dev_list; | ||
194 | dev_list = link; | ||
195 | client_reg.dev_info = &dev_info; | ||
196 | client_reg.EventMask = | ||
197 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
198 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
199 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
200 | client_reg.event_handler = &ibmtr_event; | ||
201 | client_reg.Version = 0x0210; | ||
202 | client_reg.event_callback_args.client_data = link; | ||
203 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
204 | if (ret != 0) { | ||
205 | cs_error(link->handle, RegisterClient, ret); | ||
206 | goto out_detach; | ||
207 | } | ||
208 | |||
209 | out: | ||
210 | return link; | ||
211 | |||
212 | out_detach: | ||
213 | ibmtr_detach(link); | ||
214 | link = NULL; | ||
215 | goto out; | ||
216 | } /* ibmtr_attach */ | ||
217 | |||
218 | /*====================================================================== | ||
219 | |||
220 | This deletes a driver "instance". The device is de-registered | ||
221 | with Card Services. If it has been released, all local data | ||
222 | structures are freed. Otherwise, the structures will be freed | ||
223 | when the device is released. | ||
224 | |||
225 | ======================================================================*/ | ||
226 | |||
227 | static void ibmtr_detach(dev_link_t *link) | ||
228 | { | ||
229 | struct ibmtr_dev_t *info = link->priv; | ||
230 | dev_link_t **linkp; | ||
231 | struct net_device *dev; | ||
232 | |||
233 | DEBUG(0, "ibmtr_detach(0x%p)\n", link); | ||
234 | |||
235 | /* Locate device structure */ | ||
236 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
237 | if (*linkp == link) break; | ||
238 | if (*linkp == NULL) | ||
239 | return; | ||
240 | |||
241 | dev = info->dev; | ||
242 | |||
243 | if (link->dev) | ||
244 | unregister_netdev(dev); | ||
245 | |||
246 | { | ||
247 | struct tok_info *ti = netdev_priv(dev); | ||
248 | del_timer_sync(&(ti->tr_timer)); | ||
249 | } | ||
250 | if (link->state & DEV_CONFIG) | ||
251 | ibmtr_release(link); | ||
252 | |||
253 | if (link->handle) | ||
254 | pcmcia_deregister_client(link->handle); | ||
255 | |||
256 | /* Unlink device structure, free bits */ | ||
257 | *linkp = link->next; | ||
258 | free_netdev(dev); | ||
259 | kfree(info); | ||
260 | } /* ibmtr_detach */ | ||
261 | |||
262 | /*====================================================================== | ||
263 | |||
264 | ibmtr_config() is scheduled to run after a CARD_INSERTION event | ||
265 | is received, to configure the PCMCIA socket, and to make the | ||
266 | token-ring device available to the system. | ||
267 | |||
268 | ======================================================================*/ | ||
269 | |||
270 | #define CS_CHECK(fn, ret) \ | ||
271 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
272 | |||
273 | static void ibmtr_config(dev_link_t *link) | ||
274 | { | ||
275 | client_handle_t handle = link->handle; | ||
276 | ibmtr_dev_t *info = link->priv; | ||
277 | struct net_device *dev = info->dev; | ||
278 | struct tok_info *ti = netdev_priv(dev); | ||
279 | tuple_t tuple; | ||
280 | cisparse_t parse; | ||
281 | win_req_t req; | ||
282 | memreq_t mem; | ||
283 | int i, last_ret, last_fn; | ||
284 | u_char buf[64]; | ||
285 | |||
286 | DEBUG(0, "ibmtr_config(0x%p)\n", link); | ||
287 | |||
288 | tuple.Attributes = 0; | ||
289 | tuple.TupleData = buf; | ||
290 | tuple.TupleDataMax = 64; | ||
291 | tuple.TupleOffset = 0; | ||
292 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
293 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
294 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
295 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | ||
296 | link->conf.ConfigBase = parse.config.base; | ||
297 | |||
298 | /* Configure card */ | ||
299 | link->state |= DEV_CONFIG; | ||
300 | |||
301 | link->conf.ConfigIndex = 0x61; | ||
302 | |||
303 | /* Determine if this is PRIMARY or ALTERNATE. */ | ||
304 | |||
305 | /* Try PRIMARY card at 0xA20-0xA23 */ | ||
306 | link->io.BasePort1 = 0xA20; | ||
307 | i = pcmcia_request_io(link->handle, &link->io); | ||
308 | if (i != CS_SUCCESS) { | ||
309 | /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ | ||
310 | link->io.BasePort1 = 0xA24; | ||
311 | CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); | ||
312 | } | ||
313 | dev->base_addr = link->io.BasePort1; | ||
314 | |||
315 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | ||
316 | dev->irq = link->irq.AssignedIRQ; | ||
317 | ti->irq = link->irq.AssignedIRQ; | ||
318 | ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); | ||
319 | |||
320 | /* Allocate the MMIO memory window */ | ||
321 | req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; | ||
322 | req.Attributes |= WIN_USE_WAIT; | ||
323 | req.Base = 0; | ||
324 | req.Size = 0x2000; | ||
325 | req.AccessSpeed = 250; | ||
326 | CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); | ||
327 | |||
328 | mem.CardOffset = mmiobase; | ||
329 | mem.Page = 0; | ||
330 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); | ||
331 | ti->mmio = ioremap(req.Base, req.Size); | ||
332 | |||
333 | /* Allocate the SRAM memory window */ | ||
334 | req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; | ||
335 | req.Attributes |= WIN_USE_WAIT; | ||
336 | req.Base = 0; | ||
337 | req.Size = sramsize * 1024; | ||
338 | req.AccessSpeed = 250; | ||
339 | CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle)); | ||
340 | |||
341 | mem.CardOffset = srambase; | ||
342 | mem.Page = 0; | ||
343 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(info->sram_win_handle, &mem)); | ||
344 | |||
345 | ti->sram_base = mem.CardOffset >> 12; | ||
346 | ti->sram_virt = ioremap(req.Base, req.Size); | ||
347 | ti->sram_phys = req.Base; | ||
348 | |||
349 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | ||
350 | |||
351 | /* Set up the Token-Ring Controller Configuration Register and | ||
352 | turn on the card. Check the "Local Area Network Credit Card | ||
353 | Adapters Technical Reference" SC30-3585 for this info. */ | ||
354 | ibmtr_hw_setup(dev, mmiobase); | ||
355 | |||
356 | link->dev = &info->node; | ||
357 | link->state &= ~DEV_CONFIG_PENDING; | ||
358 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
359 | |||
360 | i = ibmtr_probe_card(dev); | ||
361 | if (i != 0) { | ||
362 | printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n"); | ||
363 | link->dev = NULL; | ||
364 | goto failed; | ||
365 | } | ||
366 | |||
367 | strcpy(info->node.dev_name, dev->name); | ||
368 | |||
369 | printk(KERN_INFO "%s: port %#3lx, irq %d,", | ||
370 | dev->name, dev->base_addr, dev->irq); | ||
371 | printk (" mmio %#5lx,", (u_long)ti->mmio); | ||
372 | printk (" sram %#5lx,", (u_long)ti->sram_base << 12); | ||
373 | printk ("\n" KERN_INFO " hwaddr="); | ||
374 | for (i = 0; i < TR_ALEN; i++) | ||
375 | printk("%02X", dev->dev_addr[i]); | ||
376 | printk("\n"); | ||
377 | return; | ||
378 | |||
379 | cs_failed: | ||
380 | cs_error(link->handle, last_fn, last_ret); | ||
381 | failed: | ||
382 | ibmtr_release(link); | ||
383 | } /* ibmtr_config */ | ||
384 | |||
385 | /*====================================================================== | ||
386 | |||
387 | After a card is removed, ibmtr_release() will unregister the net | ||
388 | device, and release the PCMCIA configuration. If the device is | ||
389 | still open, this will be postponed until it is closed. | ||
390 | |||
391 | ======================================================================*/ | ||
392 | |||
393 | static void ibmtr_release(dev_link_t *link) | ||
394 | { | ||
395 | ibmtr_dev_t *info = link->priv; | ||
396 | struct net_device *dev = info->dev; | ||
397 | |||
398 | DEBUG(0, "ibmtr_release(0x%p)\n", link); | ||
399 | |||
400 | pcmcia_release_configuration(link->handle); | ||
401 | pcmcia_release_io(link->handle, &link->io); | ||
402 | pcmcia_release_irq(link->handle, &link->irq); | ||
403 | if (link->win) { | ||
404 | struct tok_info *ti = netdev_priv(dev); | ||
405 | iounmap(ti->mmio); | ||
406 | pcmcia_release_window(link->win); | ||
407 | pcmcia_release_window(info->sram_win_handle); | ||
408 | } | ||
409 | |||
410 | link->state &= ~DEV_CONFIG; | ||
411 | } | ||
412 | |||
413 | /*====================================================================== | ||
414 | |||
415 | The card status event handler. Mostly, this schedules other | ||
416 | stuff to run after an event is received. A CARD_REMOVAL event | ||
417 | also sets some flags to discourage the net drivers from trying | ||
418 | to talk to the card any more. | ||
419 | |||
420 | ======================================================================*/ | ||
421 | |||
422 | static int ibmtr_event(event_t event, int priority, | ||
423 | event_callback_args_t *args) | ||
424 | { | ||
425 | dev_link_t *link = args->client_data; | ||
426 | ibmtr_dev_t *info = link->priv; | ||
427 | struct net_device *dev = info->dev; | ||
428 | |||
429 | DEBUG(1, "ibmtr_event(0x%06x)\n", event); | ||
430 | |||
431 | switch (event) { | ||
432 | case CS_EVENT_CARD_REMOVAL: | ||
433 | link->state &= ~DEV_PRESENT; | ||
434 | if (link->state & DEV_CONFIG) { | ||
435 | /* set flag to bypass normal interrupt code */ | ||
436 | struct tok_info *priv = netdev_priv(dev); | ||
437 | priv->sram_phys |= 1; | ||
438 | netif_device_detach(dev); | ||
439 | } | ||
440 | break; | ||
441 | case CS_EVENT_CARD_INSERTION: | ||
442 | link->state |= DEV_PRESENT; | ||
443 | ibmtr_config(link); | ||
444 | break; | ||
445 | case CS_EVENT_PM_SUSPEND: | ||
446 | link->state |= DEV_SUSPEND; | ||
447 | /* Fall through... */ | ||
448 | case CS_EVENT_RESET_PHYSICAL: | ||
449 | if (link->state & DEV_CONFIG) { | ||
450 | if (link->open) | ||
451 | netif_device_detach(dev); | ||
452 | pcmcia_release_configuration(link->handle); | ||
453 | } | ||
454 | break; | ||
455 | case CS_EVENT_PM_RESUME: | ||
456 | link->state &= ~DEV_SUSPEND; | ||
457 | /* Fall through... */ | ||
458 | case CS_EVENT_CARD_RESET: | ||
459 | if (link->state & DEV_CONFIG) { | ||
460 | pcmcia_request_configuration(link->handle, &link->conf); | ||
461 | if (link->open) { | ||
462 | ibmtr_probe(dev); /* really? */ | ||
463 | netif_device_attach(dev); | ||
464 | } | ||
465 | } | ||
466 | break; | ||
467 | } | ||
468 | return 0; | ||
469 | } /* ibmtr_event */ | ||
470 | |||
471 | /*====================================================================*/ | ||
472 | |||
473 | static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase) | ||
474 | { | ||
475 | int i; | ||
476 | |||
477 | /* Bizarre IBM behavior, there are 16 bits of information we | ||
478 | need to set, but the card only allows us to send 4 bits at a | ||
479 | time. For each byte sent to base_addr, bits 7-4 tell the | ||
480 | card which part of the 16 bits we are setting, bits 3-0 contain | ||
481 | the actual information */ | ||
482 | |||
483 | /* First nibble provides 4 bits of mmio */ | ||
484 | i = (mmiobase >> 16) & 0x0F; | ||
485 | outb(i, dev->base_addr); | ||
486 | |||
487 | /* Second nibble provides 3 bits of mmio */ | ||
488 | i = 0x10 | ((mmiobase >> 12) & 0x0E); | ||
489 | outb(i, dev->base_addr); | ||
490 | |||
491 | /* Third nibble, hard-coded values */ | ||
492 | i = 0x26; | ||
493 | outb(i, dev->base_addr); | ||
494 | |||
495 | /* Fourth nibble sets shared ram page size */ | ||
496 | |||
497 | /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */ | ||
498 | i = (sramsize >> 4) & 0x07; | ||
499 | i = ((i == 4) ? 3 : i) << 2; | ||
500 | i |= 0x30; | ||
501 | |||
502 | if (ringspeed == 16) | ||
503 | i |= 2; | ||
504 | if (dev->base_addr == 0xA24) | ||
505 | i |= 1; | ||
506 | outb(i, dev->base_addr); | ||
507 | |||
508 | /* 0x40 will release the card for use */ | ||
509 | outb(0x40, dev->base_addr); | ||
510 | |||
511 | return; | ||
512 | } | ||
513 | |||
514 | static struct pcmcia_driver ibmtr_cs_driver = { | ||
515 | .owner = THIS_MODULE, | ||
516 | .drv = { | ||
517 | .name = "ibmtr_cs", | ||
518 | }, | ||
519 | .attach = ibmtr_attach, | ||
520 | .detach = ibmtr_detach, | ||
521 | }; | ||
522 | |||
523 | static int __init init_ibmtr_cs(void) | ||
524 | { | ||
525 | return pcmcia_register_driver(&ibmtr_cs_driver); | ||
526 | } | ||
527 | |||
528 | static void __exit exit_ibmtr_cs(void) | ||
529 | { | ||
530 | pcmcia_unregister_driver(&ibmtr_cs_driver); | ||
531 | BUG_ON(dev_list != NULL); | ||
532 | } | ||
533 | |||
534 | module_init(init_ibmtr_cs); | ||
535 | module_exit(exit_ibmtr_cs); | ||
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c new file mode 100644 index 000000000000..4603807fcafb --- /dev/null +++ b/drivers/net/pcmcia/nmclan_cs.c | |||
@@ -0,0 +1,1699 @@ | |||
1 | /* ---------------------------------------------------------------------------- | ||
2 | Linux PCMCIA ethernet adapter driver for the New Media Ethernet LAN. | ||
3 | nmclan_cs.c,v 0.16 1995/07/01 06:42:17 rpao Exp rpao | ||
4 | |||
5 | The Ethernet LAN uses the Advanced Micro Devices (AMD) Am79C940 Media | ||
6 | Access Controller for Ethernet (MACE). It is essentially the Am2150 | ||
7 | PCMCIA Ethernet card contained in the Am2150 Demo Kit. | ||
8 | |||
9 | Written by Roger C. Pao <rpao@paonet.org> | ||
10 | Copyright 1995 Roger C. Pao | ||
11 | Linux 2.5 cleanups Copyright Red Hat 2003 | ||
12 | |||
13 | This software may be used and distributed according to the terms of | ||
14 | the GNU General Public License. | ||
15 | |||
16 | Ported to Linux 1.3.* network driver environment by | ||
17 | Matti Aarnio <mea@utu.fi> | ||
18 | |||
19 | References | ||
20 | |||
21 | Am2150 Technical Reference Manual, Revision 1.0, August 17, 1993 | ||
22 | Am79C940 (MACE) Data Sheet, 1994 | ||
23 | Am79C90 (C-LANCE) Data Sheet, 1994 | ||
24 | Linux PCMCIA Programmer's Guide v1.17 | ||
25 | /usr/src/linux/net/inet/dev.c, Linux kernel 1.2.8 | ||
26 | |||
27 | Eric Mears, New Media Corporation | ||
28 | Tom Pollard, New Media Corporation | ||
29 | Dean Siasoyco, New Media Corporation | ||
30 | Ken Lesniak, Silicon Graphics, Inc. <lesniak@boston.sgi.com> | ||
31 | Donald Becker <becker@scyld.com> | ||
32 | David Hinds <dahinds@users.sourceforge.net> | ||
33 | |||
34 | The Linux client driver is based on the 3c589_cs.c client driver by | ||
35 | David Hinds. | ||
36 | |||
37 | The Linux network driver outline is based on the 3c589_cs.c driver, | ||
38 | the 8390.c driver, and the example skeleton.c kernel code, which are | ||
39 | by Donald Becker. | ||
40 | |||
41 | The Am2150 network driver hardware interface code is based on the | ||
42 | OS/9000 driver for the New Media Ethernet LAN by Eric Mears. | ||
43 | |||
44 | Special thanks for testing and help in debugging this driver goes | ||
45 | to Ken Lesniak. | ||
46 | |||
47 | ------------------------------------------------------------------------------- | ||
48 | Driver Notes and Issues | ||
49 | ------------------------------------------------------------------------------- | ||
50 | |||
51 | 1. Developed on a Dell 320SLi | ||
52 | PCMCIA Card Services 2.6.2 | ||
53 | Linux dell 1.2.10 #1 Thu Jun 29 20:23:41 PDT 1995 i386 | ||
54 | |||
55 | 2. rc.pcmcia may require loading pcmcia_core with io_speed=300: | ||
56 | 'insmod pcmcia_core.o io_speed=300'. | ||
57 | This will avoid problems with fast systems which causes rx_framecnt | ||
58 | to return random values. | ||
59 | |||
60 | 3. If hot extraction does not work for you, use 'ifconfig eth0 down' | ||
61 | before extraction. | ||
62 | |||
63 | 4. There is a bad slow-down problem in this driver. | ||
64 | |||
65 | 5. Future: Multicast processing. In the meantime, do _not_ compile your | ||
66 | kernel with multicast ip enabled. | ||
67 | |||
68 | ------------------------------------------------------------------------------- | ||
69 | History | ||
70 | ------------------------------------------------------------------------------- | ||
71 | Log: nmclan_cs.c,v | ||
72 | * 2.5.75-ac1 2003/07/11 Alan Cox <alan@redhat.com> | ||
73 | * Fixed hang on card eject as we probe it | ||
74 | * Cleaned up to use new style locking. | ||
75 | * | ||
76 | * Revision 0.16 1995/07/01 06:42:17 rpao | ||
77 | * Bug fix: nmclan_reset() called CardServices incorrectly. | ||
78 | * | ||
79 | * Revision 0.15 1995/05/24 08:09:47 rpao | ||
80 | * Re-implement MULTI_TX dev->tbusy handling. | ||
81 | * | ||
82 | * Revision 0.14 1995/05/23 03:19:30 rpao | ||
83 | * Added, in nmclan_config(), "tuple.Attributes = 0;". | ||
84 | * Modified MACE ID check to ignore chip revision level. | ||
85 | * Avoid tx_free_frames race condition between _start_xmit and _interrupt. | ||
86 | * | ||
87 | * Revision 0.13 1995/05/18 05:56:34 rpao | ||
88 | * Statistics changes. | ||
89 | * Bug fix: nmclan_reset did not enable TX and RX: call restore_multicast_list. | ||
90 | * Bug fix: mace_interrupt checks ~MACE_IMR_DEFAULT. Fixes driver lockup. | ||
91 | * | ||
92 | * Revision 0.12 1995/05/14 00:12:23 rpao | ||
93 | * Statistics overhaul. | ||
94 | * | ||
95 | |||
96 | 95/05/13 rpao V0.10a | ||
97 | Bug fix: MACE statistics counters used wrong I/O ports. | ||
98 | Bug fix: mace_interrupt() needed to allow statistics to be | ||
99 | processed without RX or TX interrupts pending. | ||
100 | 95/05/11 rpao V0.10 | ||
101 | Multiple transmit request processing. | ||
102 | Modified statistics to use MACE counters where possible. | ||
103 | 95/05/10 rpao V0.09 Bug fix: Must use IO_DATA_PATH_WIDTH_AUTO. | ||
104 | *Released | ||
105 | 95/05/10 rpao V0.08 | ||
106 | Bug fix: Make all non-exported functions private by using | ||
107 | static keyword. | ||
108 | Bug fix: Test IntrCnt _before_ reading MACE_IR. | ||
109 | 95/05/10 rpao V0.07 Statistics. | ||
110 | 95/05/09 rpao V0.06 Fix rx_framecnt problem by addition of PCIC wait states. | ||
111 | |||
112 | ---------------------------------------------------------------------------- */ | ||
113 | |||
114 | #define DRV_NAME "nmclan_cs" | ||
115 | #define DRV_VERSION "0.16" | ||
116 | |||
117 | |||
118 | /* ---------------------------------------------------------------------------- | ||
119 | Conditional Compilation Options | ||
120 | ---------------------------------------------------------------------------- */ | ||
121 | |||
122 | #define MULTI_TX 0 | ||
123 | #define RESET_ON_TIMEOUT 1 | ||
124 | #define TX_INTERRUPTABLE 1 | ||
125 | #define RESET_XILINX 0 | ||
126 | |||
127 | /* ---------------------------------------------------------------------------- | ||
128 | Include Files | ||
129 | ---------------------------------------------------------------------------- */ | ||
130 | |||
131 | #include <linux/module.h> | ||
132 | #include <linux/kernel.h> | ||
133 | #include <linux/init.h> | ||
134 | #include <linux/ptrace.h> | ||
135 | #include <linux/slab.h> | ||
136 | #include <linux/string.h> | ||
137 | #include <linux/timer.h> | ||
138 | #include <linux/interrupt.h> | ||
139 | #include <linux/in.h> | ||
140 | #include <linux/delay.h> | ||
141 | #include <linux/ethtool.h> | ||
142 | #include <linux/netdevice.h> | ||
143 | #include <linux/etherdevice.h> | ||
144 | #include <linux/skbuff.h> | ||
145 | #include <linux/if_arp.h> | ||
146 | #include <linux/ioport.h> | ||
147 | #include <linux/bitops.h> | ||
148 | |||
149 | #include <pcmcia/version.h> | ||
150 | #include <pcmcia/cs_types.h> | ||
151 | #include <pcmcia/cs.h> | ||
152 | #include <pcmcia/cisreg.h> | ||
153 | #include <pcmcia/cistpl.h> | ||
154 | #include <pcmcia/ds.h> | ||
155 | |||
156 | #include <asm/uaccess.h> | ||
157 | #include <asm/io.h> | ||
158 | #include <asm/system.h> | ||
159 | |||
160 | /* ---------------------------------------------------------------------------- | ||
161 | Defines | ||
162 | ---------------------------------------------------------------------------- */ | ||
163 | |||
164 | #define ETHER_ADDR_LEN ETH_ALEN | ||
165 | /* 6 bytes in an Ethernet Address */ | ||
166 | #define MACE_LADRF_LEN 8 | ||
167 | /* 8 bytes in Logical Address Filter */ | ||
168 | |||
169 | /* Loop Control Defines */ | ||
170 | #define MACE_MAX_IR_ITERATIONS 10 | ||
171 | #define MACE_MAX_RX_ITERATIONS 12 | ||
172 | /* | ||
173 | TBD: Dean brought this up, and I assumed the hardware would | ||
174 | handle it: | ||
175 | |||
176 | If MACE_MAX_RX_ITERATIONS is > 1, rx_framecnt may still be | ||
177 | non-zero when the isr exits. We may not get another interrupt | ||
178 | to process the remaining packets for some time. | ||
179 | */ | ||
180 | |||
181 | /* | ||
182 | The Am2150 has a Xilinx XC3042 field programmable gate array (FPGA) | ||
183 | which manages the interface between the MACE and the PCMCIA bus. It | ||
184 | also includes buffer management for the 32K x 8 SRAM to control up to | ||
185 | four transmit and 12 receive frames at a time. | ||
186 | */ | ||
187 | #define AM2150_MAX_TX_FRAMES 4 | ||
188 | #define AM2150_MAX_RX_FRAMES 12 | ||
189 | |||
190 | /* Am2150 Ethernet Card I/O Mapping */ | ||
191 | #define AM2150_RCV 0x00 | ||
192 | #define AM2150_XMT 0x04 | ||
193 | #define AM2150_XMT_SKIP 0x09 | ||
194 | #define AM2150_RCV_NEXT 0x0A | ||
195 | #define AM2150_RCV_FRAME_COUNT 0x0B | ||
196 | #define AM2150_MACE_BANK 0x0C | ||
197 | #define AM2150_MACE_BASE 0x10 | ||
198 | |||
199 | /* MACE Registers */ | ||
200 | #define MACE_RCVFIFO 0 | ||
201 | #define MACE_XMTFIFO 1 | ||
202 | #define MACE_XMTFC 2 | ||
203 | #define MACE_XMTFS 3 | ||
204 | #define MACE_XMTRC 4 | ||
205 | #define MACE_RCVFC 5 | ||
206 | #define MACE_RCVFS 6 | ||
207 | #define MACE_FIFOFC 7 | ||
208 | #define MACE_IR 8 | ||
209 | #define MACE_IMR 9 | ||
210 | #define MACE_PR 10 | ||
211 | #define MACE_BIUCC 11 | ||
212 | #define MACE_FIFOCC 12 | ||
213 | #define MACE_MACCC 13 | ||
214 | #define MACE_PLSCC 14 | ||
215 | #define MACE_PHYCC 15 | ||
216 | #define MACE_CHIPIDL 16 | ||
217 | #define MACE_CHIPIDH 17 | ||
218 | #define MACE_IAC 18 | ||
219 | /* Reserved */ | ||
220 | #define MACE_LADRF 20 | ||
221 | #define MACE_PADR 21 | ||
222 | /* Reserved */ | ||
223 | /* Reserved */ | ||
224 | #define MACE_MPC 24 | ||
225 | /* Reserved */ | ||
226 | #define MACE_RNTPC 26 | ||
227 | #define MACE_RCVCC 27 | ||
228 | /* Reserved */ | ||
229 | #define MACE_UTR 29 | ||
230 | #define MACE_RTR1 30 | ||
231 | #define MACE_RTR2 31 | ||
232 | |||
233 | /* MACE Bit Masks */ | ||
234 | #define MACE_XMTRC_EXDEF 0x80 | ||
235 | #define MACE_XMTRC_XMTRC 0x0F | ||
236 | |||
237 | #define MACE_XMTFS_XMTSV 0x80 | ||
238 | #define MACE_XMTFS_UFLO 0x40 | ||
239 | #define MACE_XMTFS_LCOL 0x20 | ||
240 | #define MACE_XMTFS_MORE 0x10 | ||
241 | #define MACE_XMTFS_ONE 0x08 | ||
242 | #define MACE_XMTFS_DEFER 0x04 | ||
243 | #define MACE_XMTFS_LCAR 0x02 | ||
244 | #define MACE_XMTFS_RTRY 0x01 | ||
245 | |||
246 | #define MACE_RCVFS_RCVSTS 0xF000 | ||
247 | #define MACE_RCVFS_OFLO 0x8000 | ||
248 | #define MACE_RCVFS_CLSN 0x4000 | ||
249 | #define MACE_RCVFS_FRAM 0x2000 | ||
250 | #define MACE_RCVFS_FCS 0x1000 | ||
251 | |||
252 | #define MACE_FIFOFC_RCVFC 0xF0 | ||
253 | #define MACE_FIFOFC_XMTFC 0x0F | ||
254 | |||
255 | #define MACE_IR_JAB 0x80 | ||
256 | #define MACE_IR_BABL 0x40 | ||
257 | #define MACE_IR_CERR 0x20 | ||
258 | #define MACE_IR_RCVCCO 0x10 | ||
259 | #define MACE_IR_RNTPCO 0x08 | ||
260 | #define MACE_IR_MPCO 0x04 | ||
261 | #define MACE_IR_RCVINT 0x02 | ||
262 | #define MACE_IR_XMTINT 0x01 | ||
263 | |||
264 | #define MACE_MACCC_PROM 0x80 | ||
265 | #define MACE_MACCC_DXMT2PD 0x40 | ||
266 | #define MACE_MACCC_EMBA 0x20 | ||
267 | #define MACE_MACCC_RESERVED 0x10 | ||
268 | #define MACE_MACCC_DRCVPA 0x08 | ||
269 | #define MACE_MACCC_DRCVBC 0x04 | ||
270 | #define MACE_MACCC_ENXMT 0x02 | ||
271 | #define MACE_MACCC_ENRCV 0x01 | ||
272 | |||
273 | #define MACE_PHYCC_LNKFL 0x80 | ||
274 | #define MACE_PHYCC_DLNKTST 0x40 | ||
275 | #define MACE_PHYCC_REVPOL 0x20 | ||
276 | #define MACE_PHYCC_DAPC 0x10 | ||
277 | #define MACE_PHYCC_LRT 0x08 | ||
278 | #define MACE_PHYCC_ASEL 0x04 | ||
279 | #define MACE_PHYCC_RWAKE 0x02 | ||
280 | #define MACE_PHYCC_AWAKE 0x01 | ||
281 | |||
282 | #define MACE_IAC_ADDRCHG 0x80 | ||
283 | #define MACE_IAC_PHYADDR 0x04 | ||
284 | #define MACE_IAC_LOGADDR 0x02 | ||
285 | |||
286 | #define MACE_UTR_RTRE 0x80 | ||
287 | #define MACE_UTR_RTRD 0x40 | ||
288 | #define MACE_UTR_RPA 0x20 | ||
289 | #define MACE_UTR_FCOLL 0x10 | ||
290 | #define MACE_UTR_RCVFCSE 0x08 | ||
291 | #define MACE_UTR_LOOP_INCL_MENDEC 0x06 | ||
292 | #define MACE_UTR_LOOP_NO_MENDEC 0x04 | ||
293 | #define MACE_UTR_LOOP_EXTERNAL 0x02 | ||
294 | #define MACE_UTR_LOOP_NONE 0x00 | ||
295 | #define MACE_UTR_RESERVED 0x01 | ||
296 | |||
297 | /* Switch MACE register bank (only 0 and 1 are valid) */ | ||
298 | #define MACEBANK(win_num) outb((win_num), ioaddr + AM2150_MACE_BANK) | ||
299 | |||
300 | #define MACE_IMR_DEFAULT \ | ||
301 | (0xFF - \ | ||
302 | ( \ | ||
303 | MACE_IR_CERR | \ | ||
304 | MACE_IR_RCVCCO | \ | ||
305 | MACE_IR_RNTPCO | \ | ||
306 | MACE_IR_MPCO | \ | ||
307 | MACE_IR_RCVINT | \ | ||
308 | MACE_IR_XMTINT \ | ||
309 | ) \ | ||
310 | ) | ||
311 | #undef MACE_IMR_DEFAULT | ||
312 | #define MACE_IMR_DEFAULT 0x00 /* New statistics handling: grab everything */ | ||
313 | |||
314 | #define TX_TIMEOUT ((400*HZ)/1000) | ||
315 | |||
316 | /* ---------------------------------------------------------------------------- | ||
317 | Type Definitions | ||
318 | ---------------------------------------------------------------------------- */ | ||
319 | |||
320 | typedef struct _mace_statistics { | ||
321 | /* MACE_XMTFS */ | ||
322 | int xmtsv; | ||
323 | int uflo; | ||
324 | int lcol; | ||
325 | int more; | ||
326 | int one; | ||
327 | int defer; | ||
328 | int lcar; | ||
329 | int rtry; | ||
330 | |||
331 | /* MACE_XMTRC */ | ||
332 | int exdef; | ||
333 | int xmtrc; | ||
334 | |||
335 | /* RFS1--Receive Status (RCVSTS) */ | ||
336 | int oflo; | ||
337 | int clsn; | ||
338 | int fram; | ||
339 | int fcs; | ||
340 | |||
341 | /* RFS2--Runt Packet Count (RNTPC) */ | ||
342 | int rfs_rntpc; | ||
343 | |||
344 | /* RFS3--Receive Collision Count (RCVCC) */ | ||
345 | int rfs_rcvcc; | ||
346 | |||
347 | /* MACE_IR */ | ||
348 | int jab; | ||
349 | int babl; | ||
350 | int cerr; | ||
351 | int rcvcco; | ||
352 | int rntpco; | ||
353 | int mpco; | ||
354 | |||
355 | /* MACE_MPC */ | ||
356 | int mpc; | ||
357 | |||
358 | /* MACE_RNTPC */ | ||
359 | int rntpc; | ||
360 | |||
361 | /* MACE_RCVCC */ | ||
362 | int rcvcc; | ||
363 | } mace_statistics; | ||
364 | |||
365 | typedef struct _mace_private { | ||
366 | dev_link_t link; | ||
367 | dev_node_t node; | ||
368 | struct net_device_stats linux_stats; /* Linux statistics counters */ | ||
369 | mace_statistics mace_stats; /* MACE chip statistics counters */ | ||
370 | |||
371 | /* restore_multicast_list() state variables */ | ||
372 | int multicast_ladrf[MACE_LADRF_LEN]; /* Logical address filter */ | ||
373 | int multicast_num_addrs; | ||
374 | |||
375 | char tx_free_frames; /* Number of free transmit frame buffers */ | ||
376 | char tx_irq_disabled; /* MACE TX interrupt disabled */ | ||
377 | |||
378 | spinlock_t bank_lock; /* Must be held if you step off bank 0 */ | ||
379 | } mace_private; | ||
380 | |||
381 | /* ---------------------------------------------------------------------------- | ||
382 | Private Global Variables | ||
383 | ---------------------------------------------------------------------------- */ | ||
384 | |||
385 | #ifdef PCMCIA_DEBUG | ||
386 | static char rcsid[] = | ||
387 | "nmclan_cs.c,v 0.16 1995/07/01 06:42:17 rpao Exp rpao"; | ||
388 | static char *version = | ||
389 | DRV_NAME " " DRV_VERSION " (Roger C. Pao)"; | ||
390 | #endif | ||
391 | |||
392 | static dev_info_t dev_info="nmclan_cs"; | ||
393 | static dev_link_t *dev_list; | ||
394 | |||
395 | static char *if_names[]={ | ||
396 | "Auto", "10baseT", "BNC", | ||
397 | }; | ||
398 | |||
399 | /* ---------------------------------------------------------------------------- | ||
400 | Parameters | ||
401 | These are the parameters that can be set during loading with | ||
402 | 'insmod'. | ||
403 | ---------------------------------------------------------------------------- */ | ||
404 | |||
405 | MODULE_DESCRIPTION("New Media PCMCIA ethernet driver"); | ||
406 | MODULE_LICENSE("GPL"); | ||
407 | |||
408 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) | ||
409 | |||
410 | /* 0=auto, 1=10baseT, 2 = 10base2, default=auto */ | ||
411 | INT_MODULE_PARM(if_port, 0); | ||
412 | |||
413 | #ifdef PCMCIA_DEBUG | ||
414 | INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); | ||
415 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) | ||
416 | #else | ||
417 | #define DEBUG(n, args...) | ||
418 | #endif | ||
419 | |||
420 | /* ---------------------------------------------------------------------------- | ||
421 | Function Prototypes | ||
422 | ---------------------------------------------------------------------------- */ | ||
423 | |||
424 | static void nmclan_config(dev_link_t *link); | ||
425 | static void nmclan_release(dev_link_t *link); | ||
426 | static int nmclan_event(event_t event, int priority, | ||
427 | event_callback_args_t *args); | ||
428 | |||
429 | static void nmclan_reset(struct net_device *dev); | ||
430 | static int mace_config(struct net_device *dev, struct ifmap *map); | ||
431 | static int mace_open(struct net_device *dev); | ||
432 | static int mace_close(struct net_device *dev); | ||
433 | static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
434 | static void mace_tx_timeout(struct net_device *dev); | ||
435 | static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); | ||
436 | static struct net_device_stats *mace_get_stats(struct net_device *dev); | ||
437 | static int mace_rx(struct net_device *dev, unsigned char RxCnt); | ||
438 | static void restore_multicast_list(struct net_device *dev); | ||
439 | static void set_multicast_list(struct net_device *dev); | ||
440 | static struct ethtool_ops netdev_ethtool_ops; | ||
441 | |||
442 | |||
443 | static dev_link_t *nmclan_attach(void); | ||
444 | static void nmclan_detach(dev_link_t *); | ||
445 | |||
446 | /* ---------------------------------------------------------------------------- | ||
447 | nmclan_attach | ||
448 | Creates an "instance" of the driver, allocating local data | ||
449 | structures for one device. The device is registered with Card | ||
450 | Services. | ||
451 | ---------------------------------------------------------------------------- */ | ||
452 | |||
453 | static dev_link_t *nmclan_attach(void) | ||
454 | { | ||
455 | mace_private *lp; | ||
456 | dev_link_t *link; | ||
457 | struct net_device *dev; | ||
458 | client_reg_t client_reg; | ||
459 | int ret; | ||
460 | |||
461 | DEBUG(0, "nmclan_attach()\n"); | ||
462 | DEBUG(1, "%s\n", rcsid); | ||
463 | |||
464 | /* Create new ethernet device */ | ||
465 | dev = alloc_etherdev(sizeof(mace_private)); | ||
466 | if (!dev) | ||
467 | return NULL; | ||
468 | lp = netdev_priv(dev); | ||
469 | link = &lp->link; | ||
470 | link->priv = dev; | ||
471 | |||
472 | spin_lock_init(&lp->bank_lock); | ||
473 | link->io.NumPorts1 = 32; | ||
474 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
475 | link->io.IOAddrLines = 5; | ||
476 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
477 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
478 | link->irq.Handler = &mace_interrupt; | ||
479 | link->irq.Instance = dev; | ||
480 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
481 | link->conf.Vcc = 50; | ||
482 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
483 | link->conf.ConfigIndex = 1; | ||
484 | link->conf.Present = PRESENT_OPTION; | ||
485 | |||
486 | lp->tx_free_frames=AM2150_MAX_TX_FRAMES; | ||
487 | |||
488 | SET_MODULE_OWNER(dev); | ||
489 | dev->hard_start_xmit = &mace_start_xmit; | ||
490 | dev->set_config = &mace_config; | ||
491 | dev->get_stats = &mace_get_stats; | ||
492 | dev->set_multicast_list = &set_multicast_list; | ||
493 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | ||
494 | dev->open = &mace_open; | ||
495 | dev->stop = &mace_close; | ||
496 | #ifdef HAVE_TX_TIMEOUT | ||
497 | dev->tx_timeout = mace_tx_timeout; | ||
498 | dev->watchdog_timeo = TX_TIMEOUT; | ||
499 | #endif | ||
500 | |||
501 | /* Register with Card Services */ | ||
502 | link->next = dev_list; | ||
503 | dev_list = link; | ||
504 | client_reg.dev_info = &dev_info; | ||
505 | client_reg.EventMask = | ||
506 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
507 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
508 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
509 | client_reg.event_handler = &nmclan_event; | ||
510 | client_reg.Version = 0x0210; | ||
511 | client_reg.event_callback_args.client_data = link; | ||
512 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
513 | if (ret != 0) { | ||
514 | cs_error(link->handle, RegisterClient, ret); | ||
515 | nmclan_detach(link); | ||
516 | return NULL; | ||
517 | } | ||
518 | |||
519 | return link; | ||
520 | } /* nmclan_attach */ | ||
521 | |||
522 | /* ---------------------------------------------------------------------------- | ||
523 | nmclan_detach | ||
524 | This deletes a driver "instance". The device is de-registered | ||
525 | with Card Services. If it has been released, all local data | ||
526 | structures are freed. Otherwise, the structures will be freed | ||
527 | when the device is released. | ||
528 | ---------------------------------------------------------------------------- */ | ||
529 | |||
530 | static void nmclan_detach(dev_link_t *link) | ||
531 | { | ||
532 | struct net_device *dev = link->priv; | ||
533 | dev_link_t **linkp; | ||
534 | |||
535 | DEBUG(0, "nmclan_detach(0x%p)\n", link); | ||
536 | |||
537 | /* Locate device structure */ | ||
538 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
539 | if (*linkp == link) break; | ||
540 | if (*linkp == NULL) | ||
541 | return; | ||
542 | |||
543 | if (link->dev) | ||
544 | unregister_netdev(dev); | ||
545 | |||
546 | if (link->state & DEV_CONFIG) | ||
547 | nmclan_release(link); | ||
548 | |||
549 | if (link->handle) | ||
550 | pcmcia_deregister_client(link->handle); | ||
551 | |||
552 | /* Unlink device structure, free bits */ | ||
553 | *linkp = link->next; | ||
554 | free_netdev(dev); | ||
555 | } /* nmclan_detach */ | ||
556 | |||
557 | /* ---------------------------------------------------------------------------- | ||
558 | mace_read | ||
559 | Reads a MACE register. This is bank independent; however, the | ||
560 | caller must ensure that this call is not interruptable. We are | ||
561 | assuming that during normal operation, the MACE is always in | ||
562 | bank 0. | ||
563 | ---------------------------------------------------------------------------- */ | ||
564 | static int mace_read(mace_private *lp, kio_addr_t ioaddr, int reg) | ||
565 | { | ||
566 | int data = 0xFF; | ||
567 | unsigned long flags; | ||
568 | |||
569 | switch (reg >> 4) { | ||
570 | case 0: /* register 0-15 */ | ||
571 | data = inb(ioaddr + AM2150_MACE_BASE + reg); | ||
572 | break; | ||
573 | case 1: /* register 16-31 */ | ||
574 | spin_lock_irqsave(&lp->bank_lock, flags); | ||
575 | MACEBANK(1); | ||
576 | data = inb(ioaddr + AM2150_MACE_BASE + (reg & 0x0F)); | ||
577 | MACEBANK(0); | ||
578 | spin_unlock_irqrestore(&lp->bank_lock, flags); | ||
579 | break; | ||
580 | } | ||
581 | return (data & 0xFF); | ||
582 | } /* mace_read */ | ||
583 | |||
584 | /* ---------------------------------------------------------------------------- | ||
585 | mace_write | ||
586 | Writes to a MACE register. This is bank independent; however, | ||
587 | the caller must ensure that this call is not interruptable. We | ||
588 | are assuming that during normal operation, the MACE is always in | ||
589 | bank 0. | ||
590 | ---------------------------------------------------------------------------- */ | ||
591 | static void mace_write(mace_private *lp, kio_addr_t ioaddr, int reg, int data) | ||
592 | { | ||
593 | unsigned long flags; | ||
594 | |||
595 | switch (reg >> 4) { | ||
596 | case 0: /* register 0-15 */ | ||
597 | outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + reg); | ||
598 | break; | ||
599 | case 1: /* register 16-31 */ | ||
600 | spin_lock_irqsave(&lp->bank_lock, flags); | ||
601 | MACEBANK(1); | ||
602 | outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + (reg & 0x0F)); | ||
603 | MACEBANK(0); | ||
604 | spin_unlock_irqrestore(&lp->bank_lock, flags); | ||
605 | break; | ||
606 | } | ||
607 | } /* mace_write */ | ||
608 | |||
609 | /* ---------------------------------------------------------------------------- | ||
610 | mace_init | ||
611 | Resets the MACE chip. | ||
612 | ---------------------------------------------------------------------------- */ | ||
613 | static int mace_init(mace_private *lp, kio_addr_t ioaddr, char *enet_addr) | ||
614 | { | ||
615 | int i; | ||
616 | int ct = 0; | ||
617 | |||
618 | /* MACE Software reset */ | ||
619 | mace_write(lp, ioaddr, MACE_BIUCC, 1); | ||
620 | while (mace_read(lp, ioaddr, MACE_BIUCC) & 0x01) { | ||
621 | /* Wait for reset bit to be cleared automatically after <= 200ns */; | ||
622 | if(++ct > 500) | ||
623 | { | ||
624 | printk(KERN_ERR "mace: reset failed, card removed ?\n"); | ||
625 | return -1; | ||
626 | } | ||
627 | udelay(1); | ||
628 | } | ||
629 | mace_write(lp, ioaddr, MACE_BIUCC, 0); | ||
630 | |||
631 | /* The Am2150 requires that the MACE FIFOs operate in burst mode. */ | ||
632 | mace_write(lp, ioaddr, MACE_FIFOCC, 0x0F); | ||
633 | |||
634 | mace_write(lp,ioaddr, MACE_RCVFC, 0); /* Disable Auto Strip Receive */ | ||
635 | mace_write(lp, ioaddr, MACE_IMR, 0xFF); /* Disable all interrupts until _open */ | ||
636 | |||
637 | /* | ||
638 | * Bit 2-1 PORTSEL[1-0] Port Select. | ||
639 | * 00 AUI/10Base-2 | ||
640 | * 01 10Base-T | ||
641 | * 10 DAI Port (reserved in Am2150) | ||
642 | * 11 GPSI | ||
643 | * For this card, only the first two are valid. | ||
644 | * So, PLSCC should be set to | ||
645 | * 0x00 for 10Base-2 | ||
646 | * 0x02 for 10Base-T | ||
647 | * Or just set ASEL in PHYCC below! | ||
648 | */ | ||
649 | switch (if_port) { | ||
650 | case 1: | ||
651 | mace_write(lp, ioaddr, MACE_PLSCC, 0x02); | ||
652 | break; | ||
653 | case 2: | ||
654 | mace_write(lp, ioaddr, MACE_PLSCC, 0x00); | ||
655 | break; | ||
656 | default: | ||
657 | mace_write(lp, ioaddr, MACE_PHYCC, /* ASEL */ 4); | ||
658 | /* ASEL Auto Select. When set, the PORTSEL[1-0] bits are overridden, | ||
659 | and the MACE device will automatically select the operating media | ||
660 | interface port. */ | ||
661 | break; | ||
662 | } | ||
663 | |||
664 | mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_PHYADDR); | ||
665 | /* Poll ADDRCHG bit */ | ||
666 | ct = 0; | ||
667 | while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG) | ||
668 | { | ||
669 | if(++ ct > 500) | ||
670 | { | ||
671 | printk(KERN_ERR "mace: ADDRCHG timeout, card removed ?\n"); | ||
672 | return -1; | ||
673 | } | ||
674 | } | ||
675 | /* Set PADR register */ | ||
676 | for (i = 0; i < ETHER_ADDR_LEN; i++) | ||
677 | mace_write(lp, ioaddr, MACE_PADR, enet_addr[i]); | ||
678 | |||
679 | /* MAC Configuration Control Register should be written last */ | ||
680 | /* Let set_multicast_list set this. */ | ||
681 | /* mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); */ | ||
682 | mace_write(lp, ioaddr, MACE_MACCC, 0x00); | ||
683 | return 0; | ||
684 | } /* mace_init */ | ||
685 | |||
686 | /* ---------------------------------------------------------------------------- | ||
687 | nmclan_config | ||
688 | This routine is scheduled to run after a CARD_INSERTION event | ||
689 | is received, to configure the PCMCIA socket, and to make the | ||
690 | ethernet device available to the system. | ||
691 | ---------------------------------------------------------------------------- */ | ||
692 | |||
693 | #define CS_CHECK(fn, ret) \ | ||
694 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
695 | |||
696 | static void nmclan_config(dev_link_t *link) | ||
697 | { | ||
698 | client_handle_t handle = link->handle; | ||
699 | struct net_device *dev = link->priv; | ||
700 | mace_private *lp = netdev_priv(dev); | ||
701 | tuple_t tuple; | ||
702 | cisparse_t parse; | ||
703 | u_char buf[64]; | ||
704 | int i, last_ret, last_fn; | ||
705 | kio_addr_t ioaddr; | ||
706 | |||
707 | DEBUG(0, "nmclan_config(0x%p)\n", link); | ||
708 | |||
709 | tuple.Attributes = 0; | ||
710 | tuple.TupleData = buf; | ||
711 | tuple.TupleDataMax = 64; | ||
712 | tuple.TupleOffset = 0; | ||
713 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
714 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
715 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
716 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | ||
717 | link->conf.ConfigBase = parse.config.base; | ||
718 | |||
719 | /* Configure card */ | ||
720 | link->state |= DEV_CONFIG; | ||
721 | |||
722 | CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io)); | ||
723 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | ||
724 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | ||
725 | dev->irq = link->irq.AssignedIRQ; | ||
726 | dev->base_addr = link->io.BasePort1; | ||
727 | |||
728 | ioaddr = dev->base_addr; | ||
729 | |||
730 | /* Read the ethernet address from the CIS. */ | ||
731 | tuple.DesiredTuple = 0x80 /* CISTPL_CFTABLE_ENTRY_MISC */; | ||
732 | tuple.TupleData = buf; | ||
733 | tuple.TupleDataMax = 64; | ||
734 | tuple.TupleOffset = 0; | ||
735 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
736 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
737 | memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); | ||
738 | |||
739 | /* Verify configuration by reading the MACE ID. */ | ||
740 | { | ||
741 | char sig[2]; | ||
742 | |||
743 | sig[0] = mace_read(lp, ioaddr, MACE_CHIPIDL); | ||
744 | sig[1] = mace_read(lp, ioaddr, MACE_CHIPIDH); | ||
745 | if ((sig[0] == 0x40) && ((sig[1] & 0x0F) == 0x09)) { | ||
746 | DEBUG(0, "nmclan_cs configured: mace id=%x %x\n", | ||
747 | sig[0], sig[1]); | ||
748 | } else { | ||
749 | printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should" | ||
750 | " be 0x40 0x?9\n", sig[0], sig[1]); | ||
751 | link->state &= ~DEV_CONFIG_PENDING; | ||
752 | return; | ||
753 | } | ||
754 | } | ||
755 | |||
756 | if(mace_init(lp, ioaddr, dev->dev_addr) == -1) | ||
757 | goto failed; | ||
758 | |||
759 | /* The if_port symbol can be set when the module is loaded */ | ||
760 | if (if_port <= 2) | ||
761 | dev->if_port = if_port; | ||
762 | else | ||
763 | printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n"); | ||
764 | |||
765 | link->dev = &lp->node; | ||
766 | link->state &= ~DEV_CONFIG_PENDING; | ||
767 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
768 | |||
769 | i = register_netdev(dev); | ||
770 | if (i != 0) { | ||
771 | printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n"); | ||
772 | link->dev = NULL; | ||
773 | goto failed; | ||
774 | } | ||
775 | |||
776 | strcpy(lp->node.dev_name, dev->name); | ||
777 | |||
778 | printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port, hw_addr ", | ||
779 | dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]); | ||
780 | for (i = 0; i < 6; i++) | ||
781 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); | ||
782 | return; | ||
783 | |||
784 | cs_failed: | ||
785 | cs_error(link->handle, last_fn, last_ret); | ||
786 | failed: | ||
787 | nmclan_release(link); | ||
788 | return; | ||
789 | |||
790 | } /* nmclan_config */ | ||
791 | |||
792 | /* ---------------------------------------------------------------------------- | ||
793 | nmclan_release | ||
794 | After a card is removed, nmclan_release() will unregister the | ||
795 | net device, and release the PCMCIA configuration. If the device | ||
796 | is still open, this will be postponed until it is closed. | ||
797 | ---------------------------------------------------------------------------- */ | ||
798 | static void nmclan_release(dev_link_t *link) | ||
799 | { | ||
800 | |||
801 | DEBUG(0, "nmclan_release(0x%p)\n", link); | ||
802 | |||
803 | pcmcia_release_configuration(link->handle); | ||
804 | pcmcia_release_io(link->handle, &link->io); | ||
805 | pcmcia_release_irq(link->handle, &link->irq); | ||
806 | |||
807 | link->state &= ~DEV_CONFIG; | ||
808 | } | ||
809 | |||
810 | /* ---------------------------------------------------------------------------- | ||
811 | nmclan_event | ||
812 | The card status event handler. Mostly, this schedules other | ||
813 | stuff to run after an event is received. A CARD_REMOVAL event | ||
814 | also sets some flags to discourage the net drivers from trying | ||
815 | to talk to the card any more. | ||
816 | ---------------------------------------------------------------------------- */ | ||
817 | static int nmclan_event(event_t event, int priority, | ||
818 | event_callback_args_t *args) | ||
819 | { | ||
820 | dev_link_t *link = args->client_data; | ||
821 | struct net_device *dev = link->priv; | ||
822 | |||
823 | DEBUG(1, "nmclan_event(0x%06x)\n", event); | ||
824 | |||
825 | switch (event) { | ||
826 | case CS_EVENT_CARD_REMOVAL: | ||
827 | link->state &= ~DEV_PRESENT; | ||
828 | if (link->state & DEV_CONFIG) | ||
829 | netif_device_detach(dev); | ||
830 | break; | ||
831 | case CS_EVENT_CARD_INSERTION: | ||
832 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
833 | nmclan_config(link); | ||
834 | break; | ||
835 | case CS_EVENT_PM_SUSPEND: | ||
836 | link->state |= DEV_SUSPEND; | ||
837 | /* Fall through... */ | ||
838 | case CS_EVENT_RESET_PHYSICAL: | ||
839 | if (link->state & DEV_CONFIG) { | ||
840 | if (link->open) | ||
841 | netif_device_detach(dev); | ||
842 | pcmcia_release_configuration(link->handle); | ||
843 | } | ||
844 | break; | ||
845 | case CS_EVENT_PM_RESUME: | ||
846 | link->state &= ~DEV_SUSPEND; | ||
847 | /* Fall through... */ | ||
848 | case CS_EVENT_CARD_RESET: | ||
849 | if (link->state & DEV_CONFIG) { | ||
850 | pcmcia_request_configuration(link->handle, &link->conf); | ||
851 | if (link->open) { | ||
852 | nmclan_reset(dev); | ||
853 | netif_device_attach(dev); | ||
854 | } | ||
855 | } | ||
856 | break; | ||
857 | case CS_EVENT_RESET_REQUEST: | ||
858 | return 1; | ||
859 | break; | ||
860 | } | ||
861 | return 0; | ||
862 | } /* nmclan_event */ | ||
863 | |||
864 | /* ---------------------------------------------------------------------------- | ||
865 | nmclan_reset | ||
866 | Reset and restore all of the Xilinx and MACE registers. | ||
867 | ---------------------------------------------------------------------------- */ | ||
868 | static void nmclan_reset(struct net_device *dev) | ||
869 | { | ||
870 | mace_private *lp = netdev_priv(dev); | ||
871 | |||
872 | #if RESET_XILINX | ||
873 | dev_link_t *link = &lp->link; | ||
874 | conf_reg_t reg; | ||
875 | u_long OrigCorValue; | ||
876 | |||
877 | /* Save original COR value */ | ||
878 | reg.Function = 0; | ||
879 | reg.Action = CS_READ; | ||
880 | reg.Offset = CISREG_COR; | ||
881 | reg.Value = 0; | ||
882 | pcmcia_access_configuration_register(link->handle, ®); | ||
883 | OrigCorValue = reg.Value; | ||
884 | |||
885 | /* Reset Xilinx */ | ||
886 | reg.Action = CS_WRITE; | ||
887 | reg.Offset = CISREG_COR; | ||
888 | DEBUG(1, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n", | ||
889 | OrigCorValue); | ||
890 | reg.Value = COR_SOFT_RESET; | ||
891 | pcmcia_access_configuration_register(link->handle, ®); | ||
892 | /* Need to wait for 20 ms for PCMCIA to finish reset. */ | ||
893 | |||
894 | /* Restore original COR configuration index */ | ||
895 | reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK); | ||
896 | pcmcia_access_configuration_register(link->handle, ®); | ||
897 | /* Xilinx is now completely reset along with the MACE chip. */ | ||
898 | lp->tx_free_frames=AM2150_MAX_TX_FRAMES; | ||
899 | |||
900 | #endif /* #if RESET_XILINX */ | ||
901 | |||
902 | /* Xilinx is now completely reset along with the MACE chip. */ | ||
903 | lp->tx_free_frames=AM2150_MAX_TX_FRAMES; | ||
904 | |||
905 | /* Reinitialize the MACE chip for operation. */ | ||
906 | mace_init(lp, dev->base_addr, dev->dev_addr); | ||
907 | mace_write(lp, dev->base_addr, MACE_IMR, MACE_IMR_DEFAULT); | ||
908 | |||
909 | /* Restore the multicast list and enable TX and RX. */ | ||
910 | restore_multicast_list(dev); | ||
911 | } /* nmclan_reset */ | ||
912 | |||
913 | /* ---------------------------------------------------------------------------- | ||
914 | mace_config | ||
915 | [Someone tell me what this is supposed to do? Is if_port a defined | ||
916 | standard? If so, there should be defines to indicate 1=10Base-T, | ||
917 | 2=10Base-2, etc. including limited automatic detection.] | ||
918 | ---------------------------------------------------------------------------- */ | ||
919 | static int mace_config(struct net_device *dev, struct ifmap *map) | ||
920 | { | ||
921 | if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { | ||
922 | if (map->port <= 2) { | ||
923 | dev->if_port = map->port; | ||
924 | printk(KERN_INFO "%s: switched to %s port\n", dev->name, | ||
925 | if_names[dev->if_port]); | ||
926 | } else | ||
927 | return -EINVAL; | ||
928 | } | ||
929 | return 0; | ||
930 | } /* mace_config */ | ||
931 | |||
932 | /* ---------------------------------------------------------------------------- | ||
933 | mace_open | ||
934 | Open device driver. | ||
935 | ---------------------------------------------------------------------------- */ | ||
936 | static int mace_open(struct net_device *dev) | ||
937 | { | ||
938 | kio_addr_t ioaddr = dev->base_addr; | ||
939 | mace_private *lp = netdev_priv(dev); | ||
940 | dev_link_t *link = &lp->link; | ||
941 | |||
942 | if (!DEV_OK(link)) | ||
943 | return -ENODEV; | ||
944 | |||
945 | link->open++; | ||
946 | |||
947 | MACEBANK(0); | ||
948 | |||
949 | netif_start_queue(dev); | ||
950 | nmclan_reset(dev); | ||
951 | |||
952 | return 0; /* Always succeed */ | ||
953 | } /* mace_open */ | ||
954 | |||
955 | /* ---------------------------------------------------------------------------- | ||
956 | mace_close | ||
957 | Closes device driver. | ||
958 | ---------------------------------------------------------------------------- */ | ||
959 | static int mace_close(struct net_device *dev) | ||
960 | { | ||
961 | kio_addr_t ioaddr = dev->base_addr; | ||
962 | mace_private *lp = netdev_priv(dev); | ||
963 | dev_link_t *link = &lp->link; | ||
964 | |||
965 | DEBUG(2, "%s: shutting down ethercard.\n", dev->name); | ||
966 | |||
967 | /* Mask off all interrupts from the MACE chip. */ | ||
968 | outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR); | ||
969 | |||
970 | link->open--; | ||
971 | netif_stop_queue(dev); | ||
972 | |||
973 | return 0; | ||
974 | } /* mace_close */ | ||
975 | |||
976 | static void netdev_get_drvinfo(struct net_device *dev, | ||
977 | struct ethtool_drvinfo *info) | ||
978 | { | ||
979 | strcpy(info->driver, DRV_NAME); | ||
980 | strcpy(info->version, DRV_VERSION); | ||
981 | sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr); | ||
982 | } | ||
983 | |||
984 | #ifdef PCMCIA_DEBUG | ||
985 | static u32 netdev_get_msglevel(struct net_device *dev) | ||
986 | { | ||
987 | return pc_debug; | ||
988 | } | ||
989 | |||
990 | static void netdev_set_msglevel(struct net_device *dev, u32 level) | ||
991 | { | ||
992 | pc_debug = level; | ||
993 | } | ||
994 | #endif /* PCMCIA_DEBUG */ | ||
995 | |||
996 | static struct ethtool_ops netdev_ethtool_ops = { | ||
997 | .get_drvinfo = netdev_get_drvinfo, | ||
998 | #ifdef PCMCIA_DEBUG | ||
999 | .get_msglevel = netdev_get_msglevel, | ||
1000 | .set_msglevel = netdev_set_msglevel, | ||
1001 | #endif /* PCMCIA_DEBUG */ | ||
1002 | }; | ||
1003 | |||
1004 | /* ---------------------------------------------------------------------------- | ||
1005 | mace_start_xmit | ||
1006 | This routine begins the packet transmit function. When completed, | ||
1007 | it will generate a transmit interrupt. | ||
1008 | |||
1009 | According to /usr/src/linux/net/inet/dev.c, if _start_xmit | ||
1010 | returns 0, the "packet is now solely the responsibility of the | ||
1011 | driver." If _start_xmit returns non-zero, the "transmission | ||
1012 | failed, put skb back into a list." | ||
1013 | ---------------------------------------------------------------------------- */ | ||
1014 | |||
1015 | static void mace_tx_timeout(struct net_device *dev) | ||
1016 | { | ||
1017 | mace_private *lp = netdev_priv(dev); | ||
1018 | dev_link_t *link = &lp->link; | ||
1019 | |||
1020 | printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name); | ||
1021 | #if RESET_ON_TIMEOUT | ||
1022 | printk("resetting card\n"); | ||
1023 | pcmcia_reset_card(link->handle, NULL); | ||
1024 | #else /* #if RESET_ON_TIMEOUT */ | ||
1025 | printk("NOT resetting card\n"); | ||
1026 | #endif /* #if RESET_ON_TIMEOUT */ | ||
1027 | dev->trans_start = jiffies; | ||
1028 | netif_wake_queue(dev); | ||
1029 | } | ||
1030 | |||
1031 | static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
1032 | { | ||
1033 | mace_private *lp = netdev_priv(dev); | ||
1034 | kio_addr_t ioaddr = dev->base_addr; | ||
1035 | |||
1036 | netif_stop_queue(dev); | ||
1037 | |||
1038 | DEBUG(3, "%s: mace_start_xmit(length = %ld) called.\n", | ||
1039 | dev->name, (long)skb->len); | ||
1040 | |||
1041 | #if (!TX_INTERRUPTABLE) | ||
1042 | /* Disable MACE TX interrupts. */ | ||
1043 | outb(MACE_IMR_DEFAULT | MACE_IR_XMTINT, | ||
1044 | ioaddr + AM2150_MACE_BASE + MACE_IMR); | ||
1045 | lp->tx_irq_disabled=1; | ||
1046 | #endif /* #if (!TX_INTERRUPTABLE) */ | ||
1047 | |||
1048 | { | ||
1049 | /* This block must not be interrupted by another transmit request! | ||
1050 | mace_tx_timeout will take care of timer-based retransmissions from | ||
1051 | the upper layers. The interrupt handler is guaranteed never to | ||
1052 | service a transmit interrupt while we are in here. | ||
1053 | */ | ||
1054 | |||
1055 | lp->linux_stats.tx_bytes += skb->len; | ||
1056 | lp->tx_free_frames--; | ||
1057 | |||
1058 | /* WARNING: Write the _exact_ number of bytes written in the header! */ | ||
1059 | /* Put out the word header [must be an outw()] . . . */ | ||
1060 | outw(skb->len, ioaddr + AM2150_XMT); | ||
1061 | /* . . . and the packet [may be any combination of outw() and outb()] */ | ||
1062 | outsw(ioaddr + AM2150_XMT, skb->data, skb->len >> 1); | ||
1063 | if (skb->len & 1) { | ||
1064 | /* Odd byte transfer */ | ||
1065 | outb(skb->data[skb->len-1], ioaddr + AM2150_XMT); | ||
1066 | } | ||
1067 | |||
1068 | dev->trans_start = jiffies; | ||
1069 | |||
1070 | #if MULTI_TX | ||
1071 | if (lp->tx_free_frames > 0) | ||
1072 | netif_start_queue(dev); | ||
1073 | #endif /* #if MULTI_TX */ | ||
1074 | } | ||
1075 | |||
1076 | #if (!TX_INTERRUPTABLE) | ||
1077 | /* Re-enable MACE TX interrupts. */ | ||
1078 | lp->tx_irq_disabled=0; | ||
1079 | outb(MACE_IMR_DEFAULT, ioaddr + AM2150_MACE_BASE + MACE_IMR); | ||
1080 | #endif /* #if (!TX_INTERRUPTABLE) */ | ||
1081 | |||
1082 | dev_kfree_skb(skb); | ||
1083 | |||
1084 | return 0; | ||
1085 | } /* mace_start_xmit */ | ||
1086 | |||
1087 | /* ---------------------------------------------------------------------------- | ||
1088 | mace_interrupt | ||
1089 | The interrupt handler. | ||
1090 | ---------------------------------------------------------------------------- */ | ||
1091 | static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
1092 | { | ||
1093 | struct net_device *dev = (struct net_device *) dev_id; | ||
1094 | mace_private *lp = netdev_priv(dev); | ||
1095 | kio_addr_t ioaddr = dev->base_addr; | ||
1096 | int status; | ||
1097 | int IntrCnt = MACE_MAX_IR_ITERATIONS; | ||
1098 | |||
1099 | if (dev == NULL) { | ||
1100 | DEBUG(2, "mace_interrupt(): irq 0x%X for unknown device.\n", | ||
1101 | irq); | ||
1102 | return IRQ_NONE; | ||
1103 | } | ||
1104 | |||
1105 | if (lp->tx_irq_disabled) { | ||
1106 | printk( | ||
1107 | (lp->tx_irq_disabled? | ||
1108 | KERN_NOTICE "%s: Interrupt with tx_irq_disabled " | ||
1109 | "[isr=%02X, imr=%02X]\n": | ||
1110 | KERN_NOTICE "%s: Re-entering the interrupt handler " | ||
1111 | "[isr=%02X, imr=%02X]\n"), | ||
1112 | dev->name, | ||
1113 | inb(ioaddr + AM2150_MACE_BASE + MACE_IR), | ||
1114 | inb(ioaddr + AM2150_MACE_BASE + MACE_IMR) | ||
1115 | ); | ||
1116 | /* WARNING: MACE_IR has been read! */ | ||
1117 | return IRQ_NONE; | ||
1118 | } | ||
1119 | |||
1120 | if (!netif_device_present(dev)) { | ||
1121 | DEBUG(2, "%s: interrupt from dead card\n", dev->name); | ||
1122 | return IRQ_NONE; | ||
1123 | } | ||
1124 | |||
1125 | do { | ||
1126 | /* WARNING: MACE_IR is a READ/CLEAR port! */ | ||
1127 | status = inb(ioaddr + AM2150_MACE_BASE + MACE_IR); | ||
1128 | |||
1129 | DEBUG(3, "mace_interrupt: irq 0x%X status 0x%X.\n", irq, status); | ||
1130 | |||
1131 | if (status & MACE_IR_RCVINT) { | ||
1132 | mace_rx(dev, MACE_MAX_RX_ITERATIONS); | ||
1133 | } | ||
1134 | |||
1135 | if (status & MACE_IR_XMTINT) { | ||
1136 | unsigned char fifofc; | ||
1137 | unsigned char xmtrc; | ||
1138 | unsigned char xmtfs; | ||
1139 | |||
1140 | fifofc = inb(ioaddr + AM2150_MACE_BASE + MACE_FIFOFC); | ||
1141 | if ((fifofc & MACE_FIFOFC_XMTFC)==0) { | ||
1142 | lp->linux_stats.tx_errors++; | ||
1143 | outb(0xFF, ioaddr + AM2150_XMT_SKIP); | ||
1144 | } | ||
1145 | |||
1146 | /* Transmit Retry Count (XMTRC, reg 4) */ | ||
1147 | xmtrc = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTRC); | ||
1148 | if (xmtrc & MACE_XMTRC_EXDEF) lp->mace_stats.exdef++; | ||
1149 | lp->mace_stats.xmtrc += (xmtrc & MACE_XMTRC_XMTRC); | ||
1150 | |||
1151 | if ( | ||
1152 | (xmtfs = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTFS)) & | ||
1153 | MACE_XMTFS_XMTSV /* Transmit Status Valid */ | ||
1154 | ) { | ||
1155 | lp->mace_stats.xmtsv++; | ||
1156 | |||
1157 | if (xmtfs & ~MACE_XMTFS_XMTSV) { | ||
1158 | if (xmtfs & MACE_XMTFS_UFLO) { | ||
1159 | /* Underflow. Indicates that the Transmit FIFO emptied before | ||
1160 | the end of frame was reached. */ | ||
1161 | lp->mace_stats.uflo++; | ||
1162 | } | ||
1163 | if (xmtfs & MACE_XMTFS_LCOL) { | ||
1164 | /* Late Collision */ | ||
1165 | lp->mace_stats.lcol++; | ||
1166 | } | ||
1167 | if (xmtfs & MACE_XMTFS_MORE) { | ||
1168 | /* MORE than one retry was needed */ | ||
1169 | lp->mace_stats.more++; | ||
1170 | } | ||
1171 | if (xmtfs & MACE_XMTFS_ONE) { | ||
1172 | /* Exactly ONE retry occurred */ | ||
1173 | lp->mace_stats.one++; | ||
1174 | } | ||
1175 | if (xmtfs & MACE_XMTFS_DEFER) { | ||
1176 | /* Transmission was defered */ | ||
1177 | lp->mace_stats.defer++; | ||
1178 | } | ||
1179 | if (xmtfs & MACE_XMTFS_LCAR) { | ||
1180 | /* Loss of carrier */ | ||
1181 | lp->mace_stats.lcar++; | ||
1182 | } | ||
1183 | if (xmtfs & MACE_XMTFS_RTRY) { | ||
1184 | /* Retry error: transmit aborted after 16 attempts */ | ||
1185 | lp->mace_stats.rtry++; | ||
1186 | } | ||
1187 | } /* if (xmtfs & ~MACE_XMTFS_XMTSV) */ | ||
1188 | |||
1189 | } /* if (xmtfs & MACE_XMTFS_XMTSV) */ | ||
1190 | |||
1191 | lp->linux_stats.tx_packets++; | ||
1192 | lp->tx_free_frames++; | ||
1193 | netif_wake_queue(dev); | ||
1194 | } /* if (status & MACE_IR_XMTINT) */ | ||
1195 | |||
1196 | if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) { | ||
1197 | if (status & MACE_IR_JAB) { | ||
1198 | /* Jabber Error. Excessive transmit duration (20-150ms). */ | ||
1199 | lp->mace_stats.jab++; | ||
1200 | } | ||
1201 | if (status & MACE_IR_BABL) { | ||
1202 | /* Babble Error. >1518 bytes transmitted. */ | ||
1203 | lp->mace_stats.babl++; | ||
1204 | } | ||
1205 | if (status & MACE_IR_CERR) { | ||
1206 | /* Collision Error. CERR indicates the absence of the | ||
1207 | Signal Quality Error Test message after a packet | ||
1208 | transmission. */ | ||
1209 | lp->mace_stats.cerr++; | ||
1210 | } | ||
1211 | if (status & MACE_IR_RCVCCO) { | ||
1212 | /* Receive Collision Count Overflow; */ | ||
1213 | lp->mace_stats.rcvcco++; | ||
1214 | } | ||
1215 | if (status & MACE_IR_RNTPCO) { | ||
1216 | /* Runt Packet Count Overflow */ | ||
1217 | lp->mace_stats.rntpco++; | ||
1218 | } | ||
1219 | if (status & MACE_IR_MPCO) { | ||
1220 | /* Missed Packet Count Overflow */ | ||
1221 | lp->mace_stats.mpco++; | ||
1222 | } | ||
1223 | } /* if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) */ | ||
1224 | |||
1225 | } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt)); | ||
1226 | |||
1227 | return IRQ_HANDLED; | ||
1228 | } /* mace_interrupt */ | ||
1229 | |||
1230 | /* ---------------------------------------------------------------------------- | ||
1231 | mace_rx | ||
1232 | Receives packets. | ||
1233 | ---------------------------------------------------------------------------- */ | ||
1234 | static int mace_rx(struct net_device *dev, unsigned char RxCnt) | ||
1235 | { | ||
1236 | mace_private *lp = netdev_priv(dev); | ||
1237 | kio_addr_t ioaddr = dev->base_addr; | ||
1238 | unsigned char rx_framecnt; | ||
1239 | unsigned short rx_status; | ||
1240 | |||
1241 | while ( | ||
1242 | ((rx_framecnt = inb(ioaddr + AM2150_RCV_FRAME_COUNT)) > 0) && | ||
1243 | (rx_framecnt <= 12) && /* rx_framecnt==0xFF if card is extracted. */ | ||
1244 | (RxCnt--) | ||
1245 | ) { | ||
1246 | rx_status = inw(ioaddr + AM2150_RCV); | ||
1247 | |||
1248 | DEBUG(3, "%s: in mace_rx(), framecnt 0x%X, rx_status" | ||
1249 | " 0x%X.\n", dev->name, rx_framecnt, rx_status); | ||
1250 | |||
1251 | if (rx_status & MACE_RCVFS_RCVSTS) { /* Error, update stats. */ | ||
1252 | lp->linux_stats.rx_errors++; | ||
1253 | if (rx_status & MACE_RCVFS_OFLO) { | ||
1254 | lp->mace_stats.oflo++; | ||
1255 | } | ||
1256 | if (rx_status & MACE_RCVFS_CLSN) { | ||
1257 | lp->mace_stats.clsn++; | ||
1258 | } | ||
1259 | if (rx_status & MACE_RCVFS_FRAM) { | ||
1260 | lp->mace_stats.fram++; | ||
1261 | } | ||
1262 | if (rx_status & MACE_RCVFS_FCS) { | ||
1263 | lp->mace_stats.fcs++; | ||
1264 | } | ||
1265 | } else { | ||
1266 | short pkt_len = (rx_status & ~MACE_RCVFS_RCVSTS) - 4; | ||
1267 | /* Auto Strip is off, always subtract 4 */ | ||
1268 | struct sk_buff *skb; | ||
1269 | |||
1270 | lp->mace_stats.rfs_rntpc += inb(ioaddr + AM2150_RCV); | ||
1271 | /* runt packet count */ | ||
1272 | lp->mace_stats.rfs_rcvcc += inb(ioaddr + AM2150_RCV); | ||
1273 | /* rcv collision count */ | ||
1274 | |||
1275 | DEBUG(3, " receiving packet size 0x%X rx_status" | ||
1276 | " 0x%X.\n", pkt_len, rx_status); | ||
1277 | |||
1278 | skb = dev_alloc_skb(pkt_len+2); | ||
1279 | |||
1280 | if (skb != NULL) { | ||
1281 | skb->dev = dev; | ||
1282 | |||
1283 | skb_reserve(skb, 2); | ||
1284 | insw(ioaddr + AM2150_RCV, skb_put(skb, pkt_len), pkt_len>>1); | ||
1285 | if (pkt_len & 1) | ||
1286 | *(skb->tail-1) = inb(ioaddr + AM2150_RCV); | ||
1287 | skb->protocol = eth_type_trans(skb, dev); | ||
1288 | |||
1289 | netif_rx(skb); /* Send the packet to the upper (protocol) layers. */ | ||
1290 | |||
1291 | dev->last_rx = jiffies; | ||
1292 | lp->linux_stats.rx_packets++; | ||
1293 | lp->linux_stats.rx_bytes += skb->len; | ||
1294 | outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */ | ||
1295 | continue; | ||
1296 | } else { | ||
1297 | DEBUG(1, "%s: couldn't allocate a sk_buff of size" | ||
1298 | " %d.\n", dev->name, pkt_len); | ||
1299 | lp->linux_stats.rx_dropped++; | ||
1300 | } | ||
1301 | } | ||
1302 | outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */ | ||
1303 | } /* while */ | ||
1304 | |||
1305 | return 0; | ||
1306 | } /* mace_rx */ | ||
1307 | |||
1308 | /* ---------------------------------------------------------------------------- | ||
1309 | pr_linux_stats | ||
1310 | ---------------------------------------------------------------------------- */ | ||
1311 | static void pr_linux_stats(struct net_device_stats *pstats) | ||
1312 | { | ||
1313 | DEBUG(2, "pr_linux_stats\n"); | ||
1314 | DEBUG(2, " rx_packets=%-7ld tx_packets=%ld\n", | ||
1315 | (long)pstats->rx_packets, (long)pstats->tx_packets); | ||
1316 | DEBUG(2, " rx_errors=%-7ld tx_errors=%ld\n", | ||
1317 | (long)pstats->rx_errors, (long)pstats->tx_errors); | ||
1318 | DEBUG(2, " rx_dropped=%-7ld tx_dropped=%ld\n", | ||
1319 | (long)pstats->rx_dropped, (long)pstats->tx_dropped); | ||
1320 | DEBUG(2, " multicast=%-7ld collisions=%ld\n", | ||
1321 | (long)pstats->multicast, (long)pstats->collisions); | ||
1322 | |||
1323 | DEBUG(2, " rx_length_errors=%-7ld rx_over_errors=%ld\n", | ||
1324 | (long)pstats->rx_length_errors, (long)pstats->rx_over_errors); | ||
1325 | DEBUG(2, " rx_crc_errors=%-7ld rx_frame_errors=%ld\n", | ||
1326 | (long)pstats->rx_crc_errors, (long)pstats->rx_frame_errors); | ||
1327 | DEBUG(2, " rx_fifo_errors=%-7ld rx_missed_errors=%ld\n", | ||
1328 | (long)pstats->rx_fifo_errors, (long)pstats->rx_missed_errors); | ||
1329 | |||
1330 | DEBUG(2, " tx_aborted_errors=%-7ld tx_carrier_errors=%ld\n", | ||
1331 | (long)pstats->tx_aborted_errors, (long)pstats->tx_carrier_errors); | ||
1332 | DEBUG(2, " tx_fifo_errors=%-7ld tx_heartbeat_errors=%ld\n", | ||
1333 | (long)pstats->tx_fifo_errors, (long)pstats->tx_heartbeat_errors); | ||
1334 | DEBUG(2, " tx_window_errors=%ld\n", | ||
1335 | (long)pstats->tx_window_errors); | ||
1336 | } /* pr_linux_stats */ | ||
1337 | |||
1338 | /* ---------------------------------------------------------------------------- | ||
1339 | pr_mace_stats | ||
1340 | ---------------------------------------------------------------------------- */ | ||
1341 | static void pr_mace_stats(mace_statistics *pstats) | ||
1342 | { | ||
1343 | DEBUG(2, "pr_mace_stats\n"); | ||
1344 | |||
1345 | DEBUG(2, " xmtsv=%-7d uflo=%d\n", | ||
1346 | pstats->xmtsv, pstats->uflo); | ||
1347 | DEBUG(2, " lcol=%-7d more=%d\n", | ||
1348 | pstats->lcol, pstats->more); | ||
1349 | DEBUG(2, " one=%-7d defer=%d\n", | ||
1350 | pstats->one, pstats->defer); | ||
1351 | DEBUG(2, " lcar=%-7d rtry=%d\n", | ||
1352 | pstats->lcar, pstats->rtry); | ||
1353 | |||
1354 | /* MACE_XMTRC */ | ||
1355 | DEBUG(2, " exdef=%-7d xmtrc=%d\n", | ||
1356 | pstats->exdef, pstats->xmtrc); | ||
1357 | |||
1358 | /* RFS1--Receive Status (RCVSTS) */ | ||
1359 | DEBUG(2, " oflo=%-7d clsn=%d\n", | ||
1360 | pstats->oflo, pstats->clsn); | ||
1361 | DEBUG(2, " fram=%-7d fcs=%d\n", | ||
1362 | pstats->fram, pstats->fcs); | ||
1363 | |||
1364 | /* RFS2--Runt Packet Count (RNTPC) */ | ||
1365 | /* RFS3--Receive Collision Count (RCVCC) */ | ||
1366 | DEBUG(2, " rfs_rntpc=%-7d rfs_rcvcc=%d\n", | ||
1367 | pstats->rfs_rntpc, pstats->rfs_rcvcc); | ||
1368 | |||
1369 | /* MACE_IR */ | ||
1370 | DEBUG(2, " jab=%-7d babl=%d\n", | ||
1371 | pstats->jab, pstats->babl); | ||
1372 | DEBUG(2, " cerr=%-7d rcvcco=%d\n", | ||
1373 | pstats->cerr, pstats->rcvcco); | ||
1374 | DEBUG(2, " rntpco=%-7d mpco=%d\n", | ||
1375 | pstats->rntpco, pstats->mpco); | ||
1376 | |||
1377 | /* MACE_MPC */ | ||
1378 | DEBUG(2, " mpc=%d\n", pstats->mpc); | ||
1379 | |||
1380 | /* MACE_RNTPC */ | ||
1381 | DEBUG(2, " rntpc=%d\n", pstats->rntpc); | ||
1382 | |||
1383 | /* MACE_RCVCC */ | ||
1384 | DEBUG(2, " rcvcc=%d\n", pstats->rcvcc); | ||
1385 | |||
1386 | } /* pr_mace_stats */ | ||
1387 | |||
1388 | /* ---------------------------------------------------------------------------- | ||
1389 | update_stats | ||
1390 | Update statistics. We change to register window 1, so this | ||
1391 | should be run single-threaded if the device is active. This is | ||
1392 | expected to be a rare operation, and it's simpler for the rest | ||
1393 | of the driver to assume that window 0 is always valid rather | ||
1394 | than use a special window-state variable. | ||
1395 | |||
1396 | oflo & uflo should _never_ occur since it would mean the Xilinx | ||
1397 | was not able to transfer data between the MACE FIFO and the | ||
1398 | card's SRAM fast enough. If this happens, something is | ||
1399 | seriously wrong with the hardware. | ||
1400 | ---------------------------------------------------------------------------- */ | ||
1401 | static void update_stats(kio_addr_t ioaddr, struct net_device *dev) | ||
1402 | { | ||
1403 | mace_private *lp = netdev_priv(dev); | ||
1404 | |||
1405 | lp->mace_stats.rcvcc += mace_read(lp, ioaddr, MACE_RCVCC); | ||
1406 | lp->mace_stats.rntpc += mace_read(lp, ioaddr, MACE_RNTPC); | ||
1407 | lp->mace_stats.mpc += mace_read(lp, ioaddr, MACE_MPC); | ||
1408 | /* At this point, mace_stats is fully updated for this call. | ||
1409 | We may now update the linux_stats. */ | ||
1410 | |||
1411 | /* The MACE has no equivalent for linux_stats field which are commented | ||
1412 | out. */ | ||
1413 | |||
1414 | /* lp->linux_stats.multicast; */ | ||
1415 | lp->linux_stats.collisions = | ||
1416 | lp->mace_stats.rcvcco * 256 + lp->mace_stats.rcvcc; | ||
1417 | /* Collision: The MACE may retry sending a packet 15 times | ||
1418 | before giving up. The retry count is in XMTRC. | ||
1419 | Does each retry constitute a collision? | ||
1420 | If so, why doesn't the RCVCC record these collisions? */ | ||
1421 | |||
1422 | /* detailed rx_errors: */ | ||
1423 | lp->linux_stats.rx_length_errors = | ||
1424 | lp->mace_stats.rntpco * 256 + lp->mace_stats.rntpc; | ||
1425 | /* lp->linux_stats.rx_over_errors */ | ||
1426 | lp->linux_stats.rx_crc_errors = lp->mace_stats.fcs; | ||
1427 | lp->linux_stats.rx_frame_errors = lp->mace_stats.fram; | ||
1428 | lp->linux_stats.rx_fifo_errors = lp->mace_stats.oflo; | ||
1429 | lp->linux_stats.rx_missed_errors = | ||
1430 | lp->mace_stats.mpco * 256 + lp->mace_stats.mpc; | ||
1431 | |||
1432 | /* detailed tx_errors */ | ||
1433 | lp->linux_stats.tx_aborted_errors = lp->mace_stats.rtry; | ||
1434 | lp->linux_stats.tx_carrier_errors = lp->mace_stats.lcar; | ||
1435 | /* LCAR usually results from bad cabling. */ | ||
1436 | lp->linux_stats.tx_fifo_errors = lp->mace_stats.uflo; | ||
1437 | lp->linux_stats.tx_heartbeat_errors = lp->mace_stats.cerr; | ||
1438 | /* lp->linux_stats.tx_window_errors; */ | ||
1439 | |||
1440 | return; | ||
1441 | } /* update_stats */ | ||
1442 | |||
1443 | /* ---------------------------------------------------------------------------- | ||
1444 | mace_get_stats | ||
1445 | Gathers ethernet statistics from the MACE chip. | ||
1446 | ---------------------------------------------------------------------------- */ | ||
1447 | static struct net_device_stats *mace_get_stats(struct net_device *dev) | ||
1448 | { | ||
1449 | mace_private *lp = netdev_priv(dev); | ||
1450 | |||
1451 | update_stats(dev->base_addr, dev); | ||
1452 | |||
1453 | DEBUG(1, "%s: updating the statistics.\n", dev->name); | ||
1454 | pr_linux_stats(&lp->linux_stats); | ||
1455 | pr_mace_stats(&lp->mace_stats); | ||
1456 | |||
1457 | return &lp->linux_stats; | ||
1458 | } /* net_device_stats */ | ||
1459 | |||
1460 | /* ---------------------------------------------------------------------------- | ||
1461 | updateCRC | ||
1462 | Modified from Am79C90 data sheet. | ||
1463 | ---------------------------------------------------------------------------- */ | ||
1464 | |||
1465 | #ifdef BROKEN_MULTICAST | ||
1466 | |||
1467 | static void updateCRC(int *CRC, int bit) | ||
1468 | { | ||
1469 | int poly[]={ | ||
1470 | 1,1,1,0, 1,1,0,1, | ||
1471 | 1,0,1,1, 1,0,0,0, | ||
1472 | 1,0,0,0, 0,0,1,1, | ||
1473 | 0,0,1,0, 0,0,0,0 | ||
1474 | }; /* CRC polynomial. poly[n] = coefficient of the x**n term of the | ||
1475 | CRC generator polynomial. */ | ||
1476 | |||
1477 | int j; | ||
1478 | |||
1479 | /* shift CRC and control bit (CRC[32]) */ | ||
1480 | for (j = 32; j > 0; j--) | ||
1481 | CRC[j] = CRC[j-1]; | ||
1482 | CRC[0] = 0; | ||
1483 | |||
1484 | /* If bit XOR(control bit) = 1, set CRC = CRC XOR polynomial. */ | ||
1485 | if (bit ^ CRC[32]) | ||
1486 | for (j = 0; j < 32; j++) | ||
1487 | CRC[j] ^= poly[j]; | ||
1488 | } /* updateCRC */ | ||
1489 | |||
1490 | /* ---------------------------------------------------------------------------- | ||
1491 | BuildLAF | ||
1492 | Build logical address filter. | ||
1493 | Modified from Am79C90 data sheet. | ||
1494 | |||
1495 | Input | ||
1496 | ladrf: logical address filter (contents initialized to 0) | ||
1497 | adr: ethernet address | ||
1498 | ---------------------------------------------------------------------------- */ | ||
1499 | static void BuildLAF(int *ladrf, int *adr) | ||
1500 | { | ||
1501 | int CRC[33]={1}; /* CRC register, 1 word/bit + extra control bit */ | ||
1502 | |||
1503 | int i, byte; /* temporary array indices */ | ||
1504 | int hashcode; /* the output object */ | ||
1505 | |||
1506 | CRC[32]=0; | ||
1507 | |||
1508 | for (byte = 0; byte < 6; byte++) | ||
1509 | for (i = 0; i < 8; i++) | ||
1510 | updateCRC(CRC, (adr[byte] >> i) & 1); | ||
1511 | |||
1512 | hashcode = 0; | ||
1513 | for (i = 0; i < 6; i++) | ||
1514 | hashcode = (hashcode << 1) + CRC[i]; | ||
1515 | |||
1516 | byte = hashcode >> 3; | ||
1517 | ladrf[byte] |= (1 << (hashcode & 7)); | ||
1518 | |||
1519 | #ifdef PCMCIA_DEBUG | ||
1520 | if (pc_debug > 2) { | ||
1521 | printk(KERN_DEBUG " adr ="); | ||
1522 | for (i = 0; i < 6; i++) | ||
1523 | printk(" %02X", adr[i]); | ||
1524 | printk("\n" KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63]" | ||
1525 | " =", hashcode); | ||
1526 | for (i = 0; i < 8; i++) | ||
1527 | printk(" %02X", ladrf[i]); | ||
1528 | printk("\n"); | ||
1529 | } | ||
1530 | #endif | ||
1531 | } /* BuildLAF */ | ||
1532 | |||
1533 | /* ---------------------------------------------------------------------------- | ||
1534 | restore_multicast_list | ||
1535 | Restores the multicast filter for MACE chip to the last | ||
1536 | set_multicast_list() call. | ||
1537 | |||
1538 | Input | ||
1539 | multicast_num_addrs | ||
1540 | multicast_ladrf[] | ||
1541 | ---------------------------------------------------------------------------- */ | ||
1542 | static void restore_multicast_list(struct net_device *dev) | ||
1543 | { | ||
1544 | mace_private *lp = netdev_priv(dev); | ||
1545 | int num_addrs = lp->multicast_num_addrs; | ||
1546 | int *ladrf = lp->multicast_ladrf; | ||
1547 | kio_addr_t ioaddr = dev->base_addr; | ||
1548 | int i; | ||
1549 | |||
1550 | DEBUG(2, "%s: restoring Rx mode to %d addresses.\n", | ||
1551 | dev->name, num_addrs); | ||
1552 | |||
1553 | if (num_addrs > 0) { | ||
1554 | |||
1555 | DEBUG(1, "Attempt to restore multicast list detected.\n"); | ||
1556 | |||
1557 | mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_LOGADDR); | ||
1558 | /* Poll ADDRCHG bit */ | ||
1559 | while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG) | ||
1560 | ; | ||
1561 | /* Set LADRF register */ | ||
1562 | for (i = 0; i < MACE_LADRF_LEN; i++) | ||
1563 | mace_write(lp, ioaddr, MACE_LADRF, ladrf[i]); | ||
1564 | |||
1565 | mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_RCVFCSE | MACE_UTR_LOOP_EXTERNAL); | ||
1566 | mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); | ||
1567 | |||
1568 | } else if (num_addrs < 0) { | ||
1569 | |||
1570 | /* Promiscuous mode: receive all packets */ | ||
1571 | mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); | ||
1572 | mace_write(lp, ioaddr, MACE_MACCC, | ||
1573 | MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV | ||
1574 | ); | ||
1575 | |||
1576 | } else { | ||
1577 | |||
1578 | /* Normal mode */ | ||
1579 | mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); | ||
1580 | mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); | ||
1581 | |||
1582 | } | ||
1583 | } /* restore_multicast_list */ | ||
1584 | |||
1585 | /* ---------------------------------------------------------------------------- | ||
1586 | set_multicast_list | ||
1587 | Set or clear the multicast filter for this adaptor. | ||
1588 | |||
1589 | Input | ||
1590 | num_addrs == -1 Promiscuous mode, receive all packets | ||
1591 | num_addrs == 0 Normal mode, clear multicast list | ||
1592 | num_addrs > 0 Multicast mode, receive normal and MC packets, and do | ||
1593 | best-effort filtering. | ||
1594 | Output | ||
1595 | multicast_num_addrs | ||
1596 | multicast_ladrf[] | ||
1597 | ---------------------------------------------------------------------------- */ | ||
1598 | |||
1599 | static void set_multicast_list(struct net_device *dev) | ||
1600 | { | ||
1601 | mace_private *lp = netdev_priv(dev); | ||
1602 | int adr[ETHER_ADDR_LEN] = {0}; /* Ethernet address */ | ||
1603 | int i; | ||
1604 | struct dev_mc_list *dmi = dev->mc_list; | ||
1605 | |||
1606 | #ifdef PCMCIA_DEBUG | ||
1607 | if (pc_debug > 1) { | ||
1608 | static int old; | ||
1609 | if (dev->mc_count != old) { | ||
1610 | old = dev->mc_count; | ||
1611 | DEBUG(0, "%s: setting Rx mode to %d addresses.\n", | ||
1612 | dev->name, old); | ||
1613 | } | ||
1614 | } | ||
1615 | #endif | ||
1616 | |||
1617 | /* Set multicast_num_addrs. */ | ||
1618 | lp->multicast_num_addrs = dev->mc_count; | ||
1619 | |||
1620 | /* Set multicast_ladrf. */ | ||
1621 | if (num_addrs > 0) { | ||
1622 | /* Calculate multicast logical address filter */ | ||
1623 | memset(lp->multicast_ladrf, 0, MACE_LADRF_LEN); | ||
1624 | for (i = 0; i < dev->mc_count; i++) { | ||
1625 | memcpy(adr, dmi->dmi_addr, ETHER_ADDR_LEN); | ||
1626 | dmi = dmi->next; | ||
1627 | BuildLAF(lp->multicast_ladrf, adr); | ||
1628 | } | ||
1629 | } | ||
1630 | |||
1631 | restore_multicast_list(dev); | ||
1632 | |||
1633 | } /* set_multicast_list */ | ||
1634 | |||
1635 | #endif /* BROKEN_MULTICAST */ | ||
1636 | |||
1637 | static void restore_multicast_list(struct net_device *dev) | ||
1638 | { | ||
1639 | kio_addr_t ioaddr = dev->base_addr; | ||
1640 | mace_private *lp = netdev_priv(dev); | ||
1641 | |||
1642 | DEBUG(2, "%s: restoring Rx mode to %d addresses.\n", dev->name, | ||
1643 | lp->multicast_num_addrs); | ||
1644 | |||
1645 | if (dev->flags & IFF_PROMISC) { | ||
1646 | /* Promiscuous mode: receive all packets */ | ||
1647 | mace_write(lp,ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); | ||
1648 | mace_write(lp, ioaddr, MACE_MACCC, | ||
1649 | MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV | ||
1650 | ); | ||
1651 | } else { | ||
1652 | /* Normal mode */ | ||
1653 | mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); | ||
1654 | mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); | ||
1655 | } | ||
1656 | } /* restore_multicast_list */ | ||
1657 | |||
1658 | static void set_multicast_list(struct net_device *dev) | ||
1659 | { | ||
1660 | mace_private *lp = netdev_priv(dev); | ||
1661 | |||
1662 | #ifdef PCMCIA_DEBUG | ||
1663 | if (pc_debug > 1) { | ||
1664 | static int old; | ||
1665 | if (dev->mc_count != old) { | ||
1666 | old = dev->mc_count; | ||
1667 | DEBUG(0, "%s: setting Rx mode to %d addresses.\n", | ||
1668 | dev->name, old); | ||
1669 | } | ||
1670 | } | ||
1671 | #endif | ||
1672 | |||
1673 | lp->multicast_num_addrs = dev->mc_count; | ||
1674 | restore_multicast_list(dev); | ||
1675 | |||
1676 | } /* set_multicast_list */ | ||
1677 | |||
1678 | static struct pcmcia_driver nmclan_cs_driver = { | ||
1679 | .owner = THIS_MODULE, | ||
1680 | .drv = { | ||
1681 | .name = "nmclan_cs", | ||
1682 | }, | ||
1683 | .attach = nmclan_attach, | ||
1684 | .detach = nmclan_detach, | ||
1685 | }; | ||
1686 | |||
1687 | static int __init init_nmclan_cs(void) | ||
1688 | { | ||
1689 | return pcmcia_register_driver(&nmclan_cs_driver); | ||
1690 | } | ||
1691 | |||
1692 | static void __exit exit_nmclan_cs(void) | ||
1693 | { | ||
1694 | pcmcia_unregister_driver(&nmclan_cs_driver); | ||
1695 | BUG_ON(dev_list != NULL); | ||
1696 | } | ||
1697 | |||
1698 | module_init(init_nmclan_cs); | ||
1699 | module_exit(exit_nmclan_cs); | ||
diff --git a/drivers/net/pcmcia/ositech.h b/drivers/net/pcmcia/ositech.h new file mode 100644 index 000000000000..4126efc355bd --- /dev/null +++ b/drivers/net/pcmcia/ositech.h | |||
@@ -0,0 +1,358 @@ | |||
1 | /* | ||
2 | This file contains the firmware of Seven of Diamonds from OSITECH. | ||
3 | (Special thanks to Kevin MacPherson of OSITECH) | ||
4 | |||
5 | This software may be used and distributed according to the terms of | ||
6 | the GNU General Public License, incorporated herein by reference. | ||
7 | */ | ||
8 | |||
9 | static const u_char __Xilinx7OD[] = { | ||
10 | 0xFF, 0x04, 0xA0, 0x36, 0xF3, 0xEC, 0xFF, 0xFF, 0xFF, 0xDF, 0xFB, 0xFF, | ||
11 | 0xF3, 0xFF, 0xFF, 0xFF, | ||
12 | 0xEF, 0x3F, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7F, 0xFE, 0xFF, | ||
13 | 0xCE, 0xFE, 0xFE, 0xFE, | ||
14 | 0xFE, 0xDE, 0xBD, 0xDD, 0xFD, 0xFF, 0xFD, 0xCF, 0xF7, 0xBF, 0x7F, 0xFF, | ||
15 | 0x7F, 0x3F, 0xFE, 0xBF, | ||
16 | 0xFF, 0xFF, 0xFF, 0xBC, 0xFF, 0xFF, 0xBD, 0xB5, 0x7F, 0x7F, 0xBF, 0xBF, | ||
17 | 0x7F, 0xFF, 0xEF, 0xFF, | ||
18 | 0xFF, 0xFF, 0xFB, 0xFF, 0xF7, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDE, | ||
19 | 0xFE, 0xFE, 0xFA, 0xDE, | ||
20 | 0xBD, 0xFD, 0xED, 0xFD, 0xFD, 0xCF, 0xEF, 0xEF, 0xEF, 0xEF, 0xC7, 0xDF, | ||
21 | 0xDF, 0xDF, 0xDF, 0xDF, | ||
22 | 0xFF, 0x7E, 0xFE, 0xFD, 0x7D, 0x6D, 0xEE, 0xFE, 0x7C, 0xFB, 0xF4, 0xFB, | ||
23 | 0xCF, 0xDB, 0xDF, 0xFF, | ||
24 | 0xFF, 0xBB, 0x7F, 0xFF, 0x7F, 0xFF, 0xF7, 0xFF, 0x9E, 0xBF, 0x3B, 0xBF, | ||
25 | 0xBF, 0x7F, 0x7F, 0x7F, | ||
26 | 0x7E, 0x6F, 0xDF, 0xEF, 0xF5, 0xF6, 0xFD, 0xF6, 0xF5, 0xED, 0xEB, 0xFF, | ||
27 | 0xEF, 0xEF, 0xEF, 0x7E, | ||
28 | 0x7F, 0x7F, 0x6F, 0x7F, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xEF, 0xBF, | ||
29 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
30 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0x1F, 0x1F, 0xEE, 0xFF, 0xBC, | ||
31 | 0xB7, 0xFF, 0xDF, 0xFF, | ||
32 | 0xDF, 0xEF, 0x3B, 0xE3, 0xD3, 0xFF, 0xFB, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, | ||
33 | 0xFF, 0xBA, 0xBF, 0x2D, | ||
34 | 0xDB, 0xBD, 0xFD, 0xDB, 0xDF, 0xFA, 0xFB, 0xFF, 0xEF, 0xFB, 0xDB, 0xF3, | ||
35 | 0xFF, 0xDF, 0xFD, 0x7F, | ||
36 | 0xEF, 0xFB, 0xFF, 0xFF, 0xBE, 0xBF, 0x27, 0xBA, 0xFE, 0xFB, 0xDF, 0xFF, | ||
37 | 0xF6, 0xFF, 0xFF, 0xEF, | ||
38 | 0xFB, 0xDB, 0xF3, 0xD9, 0x9A, 0x3F, 0xFF, 0xAF, 0xBF, 0xFF, 0xFF, 0xBE, | ||
39 | 0x3F, 0x37, 0xBD, 0x96, | ||
40 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0xFB, 0xF3, 0xF3, 0xEB, 0xFF, | ||
41 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
42 | 0xFF, 0xF7, 0xFA, 0xBC, 0xAE, 0xFE, 0xBE, 0xFE, 0xBB, 0x7F, 0xFD, 0xFF, | ||
43 | 0x7F, 0xEF, 0xF7, 0xFB, | ||
44 | 0xBB, 0xD7, 0xF7, 0x7F, 0xFF, 0xF7, 0xFF, 0xFF, 0xF7, 0xBC, 0xED, 0xFD, | ||
45 | 0xBD, 0x9D, 0x7D, 0x7B, | ||
46 | 0xFB, 0x7B, 0x7B, 0xFB, 0xAF, 0xFF, 0xFE, 0xFD, 0xFD, 0xFE, 0xFE, 0xFF, | ||
47 | 0xFF, 0xFF, 0xFF, 0xF7, | ||
48 | 0xAA, 0xB9, 0xBF, 0x8F, 0xBF, 0xDF, 0xFF, 0x7F, 0xFF, 0xFF, 0x7F, 0xCF, | ||
49 | 0xFB, 0xEB, 0xCB, 0xEB, | ||
50 | 0xEE, 0xFF, 0xFF, 0xD7, 0xFF, 0xFF, 0xFF, 0x3E, 0x33, 0x3F, 0x1C, 0x7C, | ||
51 | 0xFC, 0xFF, 0xFF, 0xFF, | ||
52 | 0xFF, 0xFF, 0xCF, 0xD3, 0xF3, 0xE3, 0xF3, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, | ||
53 | 0xFF, 0xEB, 0xFE, 0x35, | ||
54 | 0x3F, 0x3D, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xEF, 0x6F, 0xE3, | ||
55 | 0xE3, 0xE3, 0xEF, 0xFF, | ||
56 | 0xFF, 0xDF, 0xFF, 0xFF, 0xF7, 0xFE, 0x3E, 0x5E, 0xFE, 0xFF, 0xFF, 0xFF, | ||
57 | 0xFF, 0xFD, 0xFF, 0xFF, | ||
58 | 0xAF, 0xCF, 0xF2, 0xCB, 0xCF, 0x8E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, | ||
59 | 0xFC, 0x3E, 0x1F, 0x9E, | ||
60 | 0xAD, 0xFD, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xEF, 0xFF, 0xB3, 0xF7, 0xE7, | ||
61 | 0xF7, 0xFA, 0xFF, 0xFF, | ||
62 | 0xFF, 0xFF, 0xFF, 0xEE, 0xEB, 0xAB, 0xAF, 0x9F, 0xE3, 0x7F, 0xFF, 0xDE, | ||
63 | 0xFF, 0x7F, 0xEE, 0xFF, | ||
64 | 0xFF, 0xFB, 0x3A, 0xFA, 0xFF, 0xF2, 0x77, 0xFF, 0xFF, 0xF7, 0xFE, 0xFF, | ||
65 | 0xFE, 0xBD, 0xAE, 0xDE, | ||
66 | 0x7D, 0x7D, 0xFD, 0xFF, 0xBF, 0xEE, 0xFF, 0xFD, 0xFF, 0xDB, 0xFB, 0xFF, | ||
67 | 0xF7, 0xEF, 0xFB, 0xFF, | ||
68 | 0xFF, 0xFE, 0xFF, 0x2D, 0xAF, 0xB9, 0xFD, 0x79, 0xFB, 0xFA, 0xFF, 0xBF, | ||
69 | 0xEF, 0xFF, 0xFF, 0x91, | ||
70 | 0xFA, 0xFB, 0xDF, 0xF7, 0xF7, 0xFF, 0xFF, 0xFF, 0xFC, 0xCF, 0x37, 0xBF, | ||
71 | 0xBF, 0xFF, 0x7F, 0x7F, | ||
72 | 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xF3, 0xFB, 0xFB, 0xFF, 0xF5, 0xEF, | ||
73 | 0xFF, 0xFF, 0xF7, 0xFA, | ||
74 | 0xFF, 0xFF, 0xEE, 0xFA, 0xFE, 0xFB, 0x55, 0xDD, 0xFF, 0x7F, 0xAF, 0xFE, | ||
75 | 0xFF, 0xFB, 0xFB, 0xF5, | ||
76 | 0xFF, 0xF7, 0xEF, 0xFF, 0xFF, 0xFF, 0xBE, 0xBD, 0xBD, 0xBD, 0xBD, 0x7D, | ||
77 | 0x7B, 0x7B, 0x7B, 0x7B, | ||
78 | 0xFB, 0xAE, 0xFF, 0xFD, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
79 | 0xF7, 0xDA, 0xB7, 0x61, | ||
80 | 0xFF, 0xB9, 0x59, 0xF3, 0x73, 0xF3, 0xDF, 0x7F, 0x6F, 0xDF, 0xEF, 0xF7, | ||
81 | 0xEB, 0xEB, 0xD7, 0xFF, | ||
82 | 0xD7, 0xFF, 0xFF, 0xF7, 0xFE, 0x7F, 0xFB, 0x3E, 0x38, 0x73, 0xF6, 0x7F, | ||
83 | 0xFC, 0xFF, 0xFF, 0xCF, | ||
84 | 0xFF, 0xB7, 0xFB, 0xB3, 0xB3, 0x67, 0xFF, 0xE7, 0xFD, 0xFF, 0xEF, 0xF6, | ||
85 | 0x7F, 0xB7, 0xBC, 0xF5, | ||
86 | 0x7B, 0xF6, 0xF7, 0xF5, 0xFF, 0xFF, 0xEF, 0xFF, 0xF7, 0xFF, 0xF7, 0xCE, | ||
87 | 0xE7, 0xFF, 0x9F, 0xFF, | ||
88 | 0xFF, 0xF5, 0xFE, 0x7D, 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
89 | 0xFF, 0xEF, 0xFF, 0xF6, | ||
90 | 0xCB, 0xDB, 0xEE, 0xFE, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xBE, | ||
91 | 0x1E, 0x3E, 0xFE, 0xFF, | ||
92 | 0x7D, 0xFE, 0xFF, 0xFF, 0xEF, 0xBF, 0xE7, 0xFF, 0xE3, 0xE3, 0xFF, 0xDF, | ||
93 | 0xE7, 0xFF, 0xFF, 0xFF, | ||
94 | 0xB8, 0xEF, 0xB7, 0x2F, 0xEE, 0xFF, 0xDF, 0xFF, 0xBF, 0xFF, 0x7F, 0xEF, | ||
95 | 0xEB, 0xBF, 0xA3, 0xD3, | ||
96 | 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBE, 0xFD, 0x3F, 0xCF, 0xFD, | ||
97 | 0xFB, 0xFF, 0xFF, 0xFF, | ||
98 | 0xFF, 0xFF, 0xAF, 0xFB, 0xBF, 0xBB, 0xBF, 0xDB, 0xFD, 0xFB, 0xFF, 0xFF, | ||
99 | 0xFF, 0xFF, 0x3E, 0xFE, | ||
100 | 0x3F, 0xBA, 0xBA, 0xFE, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xEF, 0xC3, 0x7F, | ||
101 | 0xB2, 0x9B, 0xFF, 0xFF, | ||
102 | 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0x3C, 0xFF, 0x3F, 0x3C, 0xFF, 0xFE, 0xFF, | ||
103 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
104 | 0xAF, 0xF3, 0xFE, 0xF3, 0xE3, 0xEB, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xF7, | ||
105 | 0x9A, 0xFE, 0xAF, 0x9E, | ||
106 | 0xBE, 0xFE, 0xFF, 0xDF, 0xFF, 0xFF, 0x7B, 0xEF, 0xF7, 0xBF, 0xFB, 0xFB, | ||
107 | 0xFB, 0xFF, 0xFF, 0x7F, | ||
108 | 0xFF, 0xFF, 0xFF, 0xBC, 0xBD, 0xFD, 0xBD, 0xDD, 0x7D, 0x7B, 0x7B, 0x7B, | ||
109 | 0x7B, 0xFB, 0xAE, 0xFF, | ||
110 | 0xFF, 0xFF, 0xFE, 0xFE, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xF7, 0x9A, 0xFF, | ||
111 | 0x9F, 0xFF, 0xAF, 0xEF, | ||
112 | 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xCF, 0xF3, 0xFF, 0xEB, 0xFF, 0xEB, 0xFF, | ||
113 | 0xFF, 0xBF, 0xFF, 0xFF, | ||
114 | 0xEF, 0xFE, 0xFF, 0x37, 0xFC, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
115 | 0xCF, 0xEF, 0xFD, 0xF3, | ||
116 | 0xFF, 0xEE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6E, 0xFD, 0x2F, 0xFD, | ||
117 | 0xFF, 0xFD, 0xFF, 0xFF, | ||
118 | 0xFF, 0xFF, 0xFF, 0xEF, 0xCF, 0xFF, 0xF3, 0xBF, 0x69, 0xFF, 0xFF, 0xFF, | ||
119 | 0xFF, 0xFF, 0xFF, 0xFE, | ||
120 | 0xFB, 0x9F, 0xFF, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x87, | ||
121 | 0xFE, 0xDA, 0xEF, 0xCF, | ||
122 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEF, 0xBF, 0xEF, 0xEF, 0xFD, | ||
123 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
124 | 0xFF, 0xEF, 0xFD, 0xFF, 0x7B, 0xFF, 0xEB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, | ||
125 | 0xEB, 0xF8, 0xFF, 0xEF, | ||
126 | 0xAF, 0xFF, 0xFF, 0xBD, 0xFF, 0xFF, 0xFF, 0x7F, 0xEE, 0x7F, 0xEF, 0xFF, | ||
127 | 0xBB, 0xFF, 0xBF, 0xFB, | ||
128 | 0xFF, 0xFF, 0xFF, 0xF7, 0xF6, 0xFB, 0xBD, 0xFD, 0xDD, 0xF5, 0xFF, 0xFF, | ||
129 | 0xFF, 0xFF, 0xFF, 0xAF, | ||
130 | 0xFF, 0x5F, 0xF5, 0xDF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, | ||
131 | 0xF3, 0xFF, 0xDE, 0xFE, | ||
132 | 0xEF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xDE, 0xDF, 0x5F, 0xDF, | ||
133 | 0xFD, 0xFF, 0xFF, 0xFF, | ||
134 | 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE, 0xFE, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, | ||
135 | 0xFF, 0xAF, 0xFF, 0xFF, | ||
136 | 0xEF, 0xED, 0xFF, 0xDF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xDA, 0xBD, 0xBE, | ||
137 | 0xAE, 0xFE, 0x7F, 0xFD, | ||
138 | 0xDF, 0xFF, 0xFF, 0x7F, 0xEF, 0xFF, 0xFB, 0xFB, 0xFB, 0x7F, 0xF7, 0xFF, | ||
139 | 0xFF, 0xFF, 0xFF, 0xF7, | ||
140 | 0xBC, 0xFD, 0xBD, 0xBD, 0xBD, 0xFD, 0x7B, 0x7B, 0x7B, 0x7B, 0xFB, 0xAE, | ||
141 | 0xFF, 0xFF, 0xFD, 0xFF, | ||
142 | 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x9F, 0xBF, 0xBF, 0xCF, | ||
143 | 0x7F, 0xFF, 0xFF, 0xFF, | ||
144 | 0xFF, 0xFF, 0xAF, 0xFF, 0xEB, 0xEB, 0xEB, 0xFF, 0xD7, 0xFE, 0xFF, 0xFF, | ||
145 | 0xBF, 0xE7, 0xFE, 0xBF, | ||
146 | 0x7F, 0xFC, 0xFF, 0xFF, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFB, | ||
147 | 0xFB, 0xFF, 0xFF, 0xDD, | ||
148 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBD, 0xDF, 0x9D, 0xFD, 0xDF, 0xB9, | ||
149 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
150 | 0xEF, 0xFF, 0xFB, 0xEF, 0xEB, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
151 | 0xF6, 0x9F, 0xFF, 0xFC, | ||
152 | 0xFE, 0xFB, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xDF, 0xFA, 0xCD, 0xCF, | ||
153 | 0xBF, 0x9F, 0xFF, 0xFF, | ||
154 | 0xFF, 0xFF, 0xF7, 0xFE, 0xBF, 0xFF, 0xDF, 0xEF, 0x5F, 0xFF, 0xFF, 0xFF, | ||
155 | 0xFF, 0x7F, 0x6F, 0xFF, | ||
156 | 0xBB, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0xFF, | ||
157 | 0x5F, 0xFF, 0xBF, 0xBF, | ||
158 | 0xF9, 0xFF, 0xFF, 0xFF, 0x7F, 0x6E, 0x7B, 0xFF, 0xEF, 0xFD, 0xEB, 0xDF, | ||
159 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
160 | 0xF7, 0xB6, 0x3E, 0xFC, 0xFD, 0xBF, 0x7E, 0xFB, 0xFF, 0xFF, 0xFF, 0xF7, | ||
161 | 0xEF, 0xF7, 0xF3, 0xF7, | ||
162 | 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6E, 0x35, 0x79, 0xFF, | ||
163 | 0xBF, 0xFC, 0xFF, 0xFF, | ||
164 | 0xFF, 0xFF, 0xFF, 0xEF, 0xFB, 0x53, 0xDF, 0xFF, 0xEB, 0xBF, 0xFF, 0xFF, | ||
165 | 0xFF, 0xFF, 0xFF, 0xBC, | ||
166 | 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xF5, | ||
167 | 0xFF, 0xF7, 0xFF, 0xFB, | ||
168 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0xAA, 0xEE, 0xFE, 0x3F, 0x7D, | ||
169 | 0xFD, 0xFF, 0xFF, 0xFF, | ||
170 | 0x7F, 0xAF, 0x77, 0xFB, 0xFB, 0xFF, 0xFB, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, | ||
171 | 0xF7, 0xBE, 0xBD, 0xBD, | ||
172 | 0xBD, 0xBD, 0xFD, 0x7B, 0x7B, 0x7B, 0x7B, 0xFB, 0xAE, 0xFF, 0xEF, 0xFF, | ||
173 | 0xFF, 0xFF, 0xFF, 0xFC, | ||
174 | 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0xD9, 0xB8, 0xFF, 0xFF, 0x79, 0xFF, 0xFF, | ||
175 | 0xFF, 0xFF, 0xFF, 0xCF, | ||
176 | 0xFB, 0xFF, 0xEB, 0xFF, 0xEB, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xDE, | ||
177 | 0xF8, 0xFB, 0xFE, 0x3F, | ||
178 | 0xFB, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xAD, 0xBF, 0xFA, 0xFF, 0x73, | ||
179 | 0xDF, 0xFF, 0xFF, 0xFF, | ||
180 | 0xFF, 0xFF, 0x3A, 0xF5, 0xB7, 0xFC, 0x3F, 0xF9, 0xFD, 0xFF, 0xFF, 0xFF, | ||
181 | 0x7F, 0xEF, 0xF3, 0xFF, | ||
182 | 0xBF, 0xFE, 0xF3, 0x9F, 0xFE, 0xFF, 0xFF, 0xFF, 0xF7, 0x3E, 0xFF, 0xFF, | ||
183 | 0xFF, 0xBF, 0xFF, 0xFF, | ||
184 | 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xD3, 0xFE, 0xDB, 0xFF, 0xDB, 0xDF, 0xFF, | ||
185 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
186 | 0x3E, 0xFF, 0xBF, 0xFF, 0x7F, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, | ||
187 | 0xF3, 0xFF, 0xED, 0xFF, | ||
188 | 0xF7, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xF6, 0x3C, 0xFE, 0xFF, 0xFF, | ||
189 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
190 | 0xFF, 0x9F, 0xEF, 0xEF, 0xD1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
191 | 0xFF, 0xFF, 0x7E, 0xBF, | ||
192 | 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0xEF, 0xDF, 0xF1, | ||
193 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
194 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x3E, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, | ||
195 | 0xFF, 0xFF, 0xFF, 0xBF, | ||
196 | 0xEF, 0xFD, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, | ||
197 | 0xFC, 0x3E, 0xFE, 0xFF, | ||
198 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2E, 0xEF, 0xF3, 0xFF, 0xFF, | ||
199 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
200 | 0xFF, 0xFF, 0xF7, 0xBA, 0xBE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
201 | 0xFF, 0x7F, 0xAF, 0xFB, | ||
202 | 0xFB, 0xFD, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xF2, 0xD6, 0xED, | ||
203 | 0xBD, 0xBD, 0xBD, 0x7D, | ||
204 | 0x7B, 0x7B, 0x7B, 0x7B, 0xFB, 0xAF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
205 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
206 | 0xFF, 0x92, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, | ||
207 | 0xAF, 0xEB, 0xEB, 0xFF, | ||
208 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFE, 0x2E, 0xFE, 0xFF, | ||
209 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
210 | 0xFF, 0xFF, 0xFF, 0x4F, 0xEF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
211 | 0xFF, 0xFF, 0xFF, 0xFE, | ||
212 | 0x3C, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xCE, | ||
213 | 0xC3, 0xFD, 0xFF, 0xFF, | ||
214 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, | ||
215 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
216 | 0xFF, 0xEF, 0xCF, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
217 | 0xF7, 0xEE, 0x3E, 0xFF, | ||
218 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xEF, 0xDF, 0xE2, 0xFF, | ||
219 | 0xFF, 0xFF, 0xFB, 0xFF, | ||
220 | 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xBE, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
221 | 0xFF, 0xFF, 0x7F, 0xEE, | ||
222 | 0x5F, 0xE6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, | ||
223 | 0x7D, 0xFF, 0xFF, 0xFF, | ||
224 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xF3, 0xFB, 0xFF, 0xFF, 0xFF, | ||
225 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
226 | 0xBF, 0xF7, 0x36, 0xBE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
227 | 0xFF, 0xEF, 0xD3, 0xF6, | ||
228 | 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x7F, 0xEE, | ||
229 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
230 | 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xEF, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
231 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
232 | 0xBA, 0xBE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, | ||
233 | 0xFB, 0xFA, 0xFF, 0xFF, | ||
234 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xD6, 0xFD, 0xBD, 0xBD, 0xBD, | ||
235 | 0x7D, 0x7B, 0x7B, 0x7B, | ||
236 | 0x7B, 0xFB, 0xAE, 0xFF, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
237 | 0xFF, 0xF7, 0xBA, 0xBF, | ||
238 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xEF, 0xEB, 0x6B, | ||
239 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
240 | 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFE, 0xBE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, | ||
241 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
242 | 0x4F, 0xEF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, | ||
243 | 0x3E, 0x6E, 0xFC, 0xFF, | ||
244 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xC3, 0xC9, 0xFF, 0xFF, | ||
245 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
246 | 0xFF, 0xFF, 0xFF, 0x3E, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
247 | 0xFF, 0xFF, 0xEF, 0xFB, | ||
248 | 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, | ||
249 | 0xFE, 0xFF, 0xFF, 0xFF, | ||
250 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xEF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFB, | ||
251 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
252 | 0xFF, 0xF6, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, | ||
253 | 0xEF, 0xFF, 0xFF, 0xFF, | ||
254 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFE, 0xFF, 0xF7, 0xFF, | ||
255 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
256 | 0xFF, 0x7F, 0xFA, 0xEF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
257 | 0xFF, 0xE7, 0xFF, 0xFE, | ||
258 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xEF, 0xBF, | ||
259 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
260 | 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0xFF, 0xFC, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, | ||
261 | 0xFF, 0xFF, 0xFF, 0x7F, | ||
262 | 0xFE, 0xAE, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, | ||
263 | 0xF7, 0xFA, 0xFF, 0xFD, | ||
264 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xAF, 0xFF, 0xFF, 0xFF, | ||
265 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
266 | 0xFF, 0xFF, 0xFF, 0xF7, 0xBE, 0xBD, 0xBD, 0xBD, 0xBD, 0x7D, 0x7B, 0x7B, | ||
267 | 0x7B, 0x7B, 0xFB, 0xAF, | ||
268 | 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, | ||
269 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
270 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
271 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
272 | 0xFF, 0xE7, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
273 | 0xFF, 0xCF, 0xFE, 0xFF, | ||
274 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDF, 0xFF, | ||
275 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
276 | 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
277 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
278 | 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, | ||
279 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
280 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, | ||
281 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
282 | 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, | ||
283 | 0xFF, 0xE7, 0xF2, 0xFC, | ||
284 | 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xAE, 0xEF, 0xFF, | ||
285 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
286 | 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x7E, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
287 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
288 | 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, | ||
289 | 0xFE, 0xFE, 0xFF, 0xFF, | ||
290 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xEF, 0xDD, 0xFE, 0xFF, 0xFF, | ||
291 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
292 | 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
293 | 0xFF, 0xFF, 0xAF, 0xEF, | ||
294 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0xFE, | ||
295 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
296 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFA, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, | ||
297 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
298 | 0xF6, 0x9C, 0xBD, 0xBD, 0xBD, 0xBD, 0x7D, 0x7B, 0x7B, 0x7B, 0x7B, 0xFB, | ||
299 | 0xAE, 0xFF, 0xFF, 0xFF, | ||
300 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x7A, 0xFF, 0xFF, 0xFF, | ||
301 | 0xFF, 0xDF, 0xFF, 0xFF, | ||
302 | 0xFF, 0xFF, 0x6F, 0xEF, 0xF7, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, | ||
303 | 0xFF, 0xFF, 0xF7, 0xFE, | ||
304 | 0xFE, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xEB, | ||
305 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
306 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x9E, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, | ||
307 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
308 | 0xFF, 0xEF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
309 | 0xFF, 0xFE, 0xFF, 0xFF, | ||
310 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xEF, 0xCB, 0xFF, 0xFF, | ||
311 | 0xFF, 0xFF, 0xFF, 0xFD, | ||
312 | 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
313 | 0xFF, 0xFF, 0xFF, 0xEF, | ||
314 | 0xEF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, | ||
315 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
316 | 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
317 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
318 | 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
319 | 0xFB, 0xAF, 0x7F, 0xFF, | ||
320 | 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEF, 0xFF, | ||
321 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
322 | 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
323 | 0xFF, 0xFF, 0xBF, 0xFF, | ||
324 | 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, | ||
325 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
326 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, | ||
327 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
328 | 0xFF, 0x7F, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
329 | 0xFF, 0xF7, 0xBC, 0xBD, | ||
330 | 0xBD, 0xBD, 0xBD, 0x7D, 0x7B, 0x7B, 0x7B, 0x7B, 0xFB, 0xAF, 0xFF, 0xFF, | ||
331 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
332 | 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
333 | 0xFF, 0xFF, 0xFF, 0x7F, | ||
334 | 0xAF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, | ||
335 | 0xFE, 0xFF, 0xFF, 0xFF, | ||
336 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
337 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
338 | 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, | ||
339 | 0xFF, 0xFF, 0xEF, 0xFF, | ||
340 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, | ||
341 | 0xFF, 0xFF, 0xFF, 0xFF, | ||
342 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
343 | 0xBF, 0xFF, 0xFF, 0xFF, | ||
344 | 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
345 | 0xEF, 0xFF, 0xFF, 0xFF, | ||
346 | 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFE, 0xFF, 0x9F, 0x9F, | ||
347 | 0x9F, 0x3F, 0x3F, 0x3F, | ||
348 | 0x3F, 0x3F, 0xFF, 0xEF, 0xDF, 0xDF, 0xDF, 0xDF, 0xCF, 0xB7, 0xBF, 0xBF, | ||
349 | 0xBF, 0xBF, 0xFF, 0xBC, | ||
350 | 0xB9, 0x9D, 0xBD, 0xBD, 0x7D, 0x7B, 0x7B, 0x7B, 0x7B, 0xFB, 0xEF, 0xD7, | ||
351 | 0xF5, 0xF3, 0xF1, 0xD1, | ||
352 | 0x65, 0xE3, 0xE3, 0xE3, 0xA3, 0xFF, 0xFE, 0x7F, 0xFE, 0xDE, 0xDE, 0xFF, | ||
353 | 0xBD, 0xBD, 0xBD, 0xBD, | ||
354 | 0xDF, 0xEF, 0xFB, 0xF7, 0xF3, 0xF3, 0xF3, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, | ||
355 | 0xFB, 0xFE, 0xFF, 0xFF, | ||
356 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF | ||
357 | |||
358 | }; | ||
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c new file mode 100644 index 000000000000..b0126304ca08 --- /dev/null +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -0,0 +1,1659 @@ | |||
1 | /*====================================================================== | ||
2 | |||
3 | A PCMCIA ethernet driver for NS8390-based cards | ||
4 | |||
5 | This driver supports the D-Link DE-650 and Linksys EthernetCard | ||
6 | cards, the newer D-Link and Linksys combo cards, Accton EN2212 | ||
7 | cards, the RPTI EP400, and the PreMax PE-200 in non-shared-memory | ||
8 | mode, and the IBM Credit Card Adapter, the NE4100, the Thomas | ||
9 | Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory | ||
10 | mode. It will also handle the Socket EA card in either mode. | ||
11 | |||
12 | Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net | ||
13 | |||
14 | pcnet_cs.c 1.153 2003/11/09 18:53:09 | ||
15 | |||
16 | The network driver code is based on Donald Becker's NE2000 code: | ||
17 | |||
18 | Written 1992,1993 by Donald Becker. | ||
19 | Copyright 1993 United States Government as represented by the | ||
20 | Director, National Security Agency. This software may be used and | ||
21 | distributed according to the terms of the GNU General Public License, | ||
22 | incorporated herein by reference. | ||
23 | Donald Becker may be reached at becker@scyld.com | ||
24 | |||
25 | Based also on Keith Moore's changes to Don Becker's code, for IBM | ||
26 | CCAE support. Drivers merged back together, and shared-memory | ||
27 | Socket EA support added, by Ken Raeburn, September 1995. | ||
28 | |||
29 | ======================================================================*/ | ||
30 | |||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/ptrace.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/string.h> | ||
37 | #include <linux/timer.h> | ||
38 | #include <linux/delay.h> | ||
39 | #include <linux/ethtool.h> | ||
40 | #include <linux/netdevice.h> | ||
41 | #include <../drivers/net/8390.h> | ||
42 | |||
43 | #include <pcmcia/version.h> | ||
44 | #include <pcmcia/cs_types.h> | ||
45 | #include <pcmcia/cs.h> | ||
46 | #include <pcmcia/cistpl.h> | ||
47 | #include <pcmcia/ciscode.h> | ||
48 | #include <pcmcia/ds.h> | ||
49 | #include <pcmcia/cisreg.h> | ||
50 | |||
51 | #include <asm/io.h> | ||
52 | #include <asm/system.h> | ||
53 | #include <asm/byteorder.h> | ||
54 | #include <asm/uaccess.h> | ||
55 | |||
56 | #define PCNET_CMD 0x00 | ||
57 | #define PCNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */ | ||
58 | #define PCNET_RESET 0x1f /* Issue a read to reset, a write to clear. */ | ||
59 | #define PCNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */ | ||
60 | |||
61 | #define PCNET_START_PG 0x40 /* First page of TX buffer */ | ||
62 | #define PCNET_STOP_PG 0x80 /* Last page +1 of RX ring */ | ||
63 | |||
64 | /* Socket EA cards have a larger packet buffer */ | ||
65 | #define SOCKET_START_PG 0x01 | ||
66 | #define SOCKET_STOP_PG 0xff | ||
67 | |||
68 | #define PCNET_RDC_TIMEOUT (2*HZ/100) /* Max wait in jiffies for Tx RDC */ | ||
69 | |||
70 | static char *if_names[] = { "auto", "10baseT", "10base2"}; | ||
71 | |||
72 | #ifdef PCMCIA_DEBUG | ||
73 | static int pc_debug = PCMCIA_DEBUG; | ||
74 | module_param(pc_debug, int, 0); | ||
75 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) | ||
76 | static char *version = | ||
77 | "pcnet_cs.c 1.153 2003/11/09 18:53:09 (David Hinds)"; | ||
78 | #else | ||
79 | #define DEBUG(n, args...) | ||
80 | #endif | ||
81 | |||
82 | /*====================================================================*/ | ||
83 | |||
84 | /* Module parameters */ | ||
85 | |||
86 | MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); | ||
87 | MODULE_DESCRIPTION("NE2000 compatible PCMCIA ethernet driver"); | ||
88 | MODULE_LICENSE("GPL"); | ||
89 | |||
90 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) | ||
91 | |||
92 | INT_MODULE_PARM(if_port, 1); /* Transceiver type */ | ||
93 | INT_MODULE_PARM(use_big_buf, 1); /* use 64K packet buffer? */ | ||
94 | INT_MODULE_PARM(mem_speed, 0); /* shared mem speed, in ns */ | ||
95 | INT_MODULE_PARM(delay_output, 0); /* pause after xmit? */ | ||
96 | INT_MODULE_PARM(delay_time, 4); /* in usec */ | ||
97 | INT_MODULE_PARM(use_shmem, -1); /* use shared memory? */ | ||
98 | INT_MODULE_PARM(full_duplex, 0); /* full duplex? */ | ||
99 | |||
100 | /* Ugh! Let the user hardwire the hardware address for queer cards */ | ||
101 | static int hw_addr[6] = { 0, /* ... */ }; | ||
102 | module_param_array(hw_addr, int, NULL, 0); | ||
103 | |||
104 | /*====================================================================*/ | ||
105 | |||
106 | static void mii_phy_probe(struct net_device *dev); | ||
107 | static void pcnet_config(dev_link_t *link); | ||
108 | static void pcnet_release(dev_link_t *link); | ||
109 | static int pcnet_event(event_t event, int priority, | ||
110 | event_callback_args_t *args); | ||
111 | static int pcnet_open(struct net_device *dev); | ||
112 | static int pcnet_close(struct net_device *dev); | ||
113 | static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
114 | static struct ethtool_ops netdev_ethtool_ops; | ||
115 | static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs); | ||
116 | static void ei_watchdog(u_long arg); | ||
117 | static void pcnet_reset_8390(struct net_device *dev); | ||
118 | static int set_config(struct net_device *dev, struct ifmap *map); | ||
119 | static int setup_shmem_window(dev_link_t *link, int start_pg, | ||
120 | int stop_pg, int cm_offset); | ||
121 | static int setup_dma_config(dev_link_t *link, int start_pg, | ||
122 | int stop_pg); | ||
123 | |||
124 | static dev_link_t *pcnet_attach(void); | ||
125 | static void pcnet_detach(dev_link_t *); | ||
126 | |||
127 | static dev_info_t dev_info = "pcnet_cs"; | ||
128 | static dev_link_t *dev_list; | ||
129 | |||
130 | /*====================================================================*/ | ||
131 | |||
132 | typedef struct hw_info_t { | ||
133 | u_int offset; | ||
134 | u_char a0, a1, a2; | ||
135 | u_int flags; | ||
136 | } hw_info_t; | ||
137 | |||
138 | #define DELAY_OUTPUT 0x01 | ||
139 | #define HAS_MISC_REG 0x02 | ||
140 | #define USE_BIG_BUF 0x04 | ||
141 | #define HAS_IBM_MISC 0x08 | ||
142 | #define IS_DL10019 0x10 | ||
143 | #define IS_DL10022 0x20 | ||
144 | #define HAS_MII 0x40 | ||
145 | #define USE_SHMEM 0x80 /* autodetected */ | ||
146 | |||
147 | #define AM79C9XX_HOME_PHY 0x00006B90 /* HomePNA PHY */ | ||
148 | #define AM79C9XX_ETH_PHY 0x00006B70 /* 10baseT PHY */ | ||
149 | #define MII_PHYID_REV_MASK 0xfffffff0 | ||
150 | #define MII_PHYID_REG1 0x02 | ||
151 | #define MII_PHYID_REG2 0x03 | ||
152 | |||
153 | static hw_info_t hw_info[] = { | ||
154 | { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT }, | ||
155 | { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 }, | ||
156 | { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 }, | ||
157 | { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94, | ||
158 | DELAY_OUTPUT | HAS_IBM_MISC }, | ||
159 | { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 }, | ||
160 | { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 }, | ||
161 | { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 }, | ||
162 | { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 }, | ||
163 | { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 }, | ||
164 | { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 }, | ||
165 | { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48, | ||
166 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
167 | { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 }, | ||
168 | { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 }, | ||
169 | { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a, | ||
170 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
171 | { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac, | ||
172 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
173 | { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29, | ||
174 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
175 | { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a, | ||
176 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
177 | { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac, | ||
178 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
179 | { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87, | ||
180 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
181 | { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17, | ||
182 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
183 | { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8, | ||
184 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
185 | { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0, | ||
186 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
187 | { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0, | ||
188 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
189 | { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 }, | ||
190 | { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 }, | ||
191 | { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0, | ||
192 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
193 | { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f, | ||
194 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
195 | { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 }, | ||
196 | { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 }, | ||
197 | { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 }, | ||
198 | { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 }, | ||
199 | { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65, | ||
200 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
201 | { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45, | ||
202 | HAS_MISC_REG | HAS_IBM_MISC }, | ||
203 | { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 }, | ||
204 | { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 }, | ||
205 | { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 }, | ||
206 | { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b, | ||
207 | DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF }, | ||
208 | { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 }, | ||
209 | { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 }, | ||
210 | { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 }, | ||
211 | { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 }, | ||
212 | { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 } | ||
213 | }; | ||
214 | |||
215 | #define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t)) | ||
216 | |||
217 | static hw_info_t default_info = { 0, 0, 0, 0, 0 }; | ||
218 | static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII }; | ||
219 | static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII }; | ||
220 | |||
221 | typedef struct pcnet_dev_t { | ||
222 | dev_link_t link; | ||
223 | dev_node_t node; | ||
224 | u_int flags; | ||
225 | void __iomem *base; | ||
226 | struct timer_list watchdog; | ||
227 | int stale, fast_poll; | ||
228 | u_char phy_id; | ||
229 | u_char eth_phy, pna_phy; | ||
230 | u_short link_status; | ||
231 | u_long mii_reset; | ||
232 | } pcnet_dev_t; | ||
233 | |||
234 | static inline pcnet_dev_t *PRIV(struct net_device *dev) | ||
235 | { | ||
236 | char *p = netdev_priv(dev); | ||
237 | return (pcnet_dev_t *)(p + sizeof(struct ei_device)); | ||
238 | } | ||
239 | |||
240 | /*====================================================================== | ||
241 | |||
242 | pcnet_attach() creates an "instance" of the driver, allocating | ||
243 | local data structures for one device. The device is registered | ||
244 | with Card Services. | ||
245 | |||
246 | ======================================================================*/ | ||
247 | |||
248 | static dev_link_t *pcnet_attach(void) | ||
249 | { | ||
250 | pcnet_dev_t *info; | ||
251 | dev_link_t *link; | ||
252 | struct net_device *dev; | ||
253 | client_reg_t client_reg; | ||
254 | int ret; | ||
255 | |||
256 | DEBUG(0, "pcnet_attach()\n"); | ||
257 | |||
258 | /* Create new ethernet device */ | ||
259 | dev = __alloc_ei_netdev(sizeof(pcnet_dev_t)); | ||
260 | if (!dev) return NULL; | ||
261 | info = PRIV(dev); | ||
262 | link = &info->link; | ||
263 | link->priv = dev; | ||
264 | |||
265 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | ||
266 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
267 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
268 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
269 | |||
270 | SET_MODULE_OWNER(dev); | ||
271 | dev->open = &pcnet_open; | ||
272 | dev->stop = &pcnet_close; | ||
273 | dev->set_config = &set_config; | ||
274 | |||
275 | /* Register with Card Services */ | ||
276 | link->next = dev_list; | ||
277 | dev_list = link; | ||
278 | client_reg.dev_info = &dev_info; | ||
279 | client_reg.EventMask = | ||
280 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
281 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
282 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
283 | client_reg.event_handler = &pcnet_event; | ||
284 | client_reg.Version = 0x0210; | ||
285 | client_reg.event_callback_args.client_data = link; | ||
286 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
287 | if (ret != CS_SUCCESS) { | ||
288 | cs_error(link->handle, RegisterClient, ret); | ||
289 | pcnet_detach(link); | ||
290 | return NULL; | ||
291 | } | ||
292 | |||
293 | return link; | ||
294 | } /* pcnet_attach */ | ||
295 | |||
296 | /*====================================================================== | ||
297 | |||
298 | This deletes a driver "instance". The device is de-registered | ||
299 | with Card Services. If it has been released, all local data | ||
300 | structures are freed. Otherwise, the structures will be freed | ||
301 | when the device is released. | ||
302 | |||
303 | ======================================================================*/ | ||
304 | |||
305 | static void pcnet_detach(dev_link_t *link) | ||
306 | { | ||
307 | struct net_device *dev = link->priv; | ||
308 | dev_link_t **linkp; | ||
309 | |||
310 | DEBUG(0, "pcnet_detach(0x%p)\n", link); | ||
311 | |||
312 | /* Locate device structure */ | ||
313 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
314 | if (*linkp == link) break; | ||
315 | if (*linkp == NULL) | ||
316 | return; | ||
317 | |||
318 | if (link->dev) | ||
319 | unregister_netdev(dev); | ||
320 | |||
321 | if (link->state & DEV_CONFIG) | ||
322 | pcnet_release(link); | ||
323 | |||
324 | if (link->handle) | ||
325 | pcmcia_deregister_client(link->handle); | ||
326 | |||
327 | /* Unlink device structure, free bits */ | ||
328 | *linkp = link->next; | ||
329 | free_netdev(dev); | ||
330 | } /* pcnet_detach */ | ||
331 | |||
332 | /*====================================================================== | ||
333 | |||
334 | This probes for a card's hardware address, for card types that | ||
335 | encode this information in their CIS. | ||
336 | |||
337 | ======================================================================*/ | ||
338 | |||
339 | static hw_info_t *get_hwinfo(dev_link_t *link) | ||
340 | { | ||
341 | struct net_device *dev = link->priv; | ||
342 | win_req_t req; | ||
343 | memreq_t mem; | ||
344 | u_char __iomem *base, *virt; | ||
345 | int i, j; | ||
346 | |||
347 | /* Allocate a small memory window */ | ||
348 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | ||
349 | req.Base = 0; req.Size = 0; | ||
350 | req.AccessSpeed = 0; | ||
351 | i = pcmcia_request_window(&link->handle, &req, &link->win); | ||
352 | if (i != CS_SUCCESS) { | ||
353 | cs_error(link->handle, RequestWindow, i); | ||
354 | return NULL; | ||
355 | } | ||
356 | |||
357 | virt = ioremap(req.Base, req.Size); | ||
358 | mem.Page = 0; | ||
359 | for (i = 0; i < NR_INFO; i++) { | ||
360 | mem.CardOffset = hw_info[i].offset & ~(req.Size-1); | ||
361 | pcmcia_map_mem_page(link->win, &mem); | ||
362 | base = &virt[hw_info[i].offset & (req.Size-1)]; | ||
363 | if ((readb(base+0) == hw_info[i].a0) && | ||
364 | (readb(base+2) == hw_info[i].a1) && | ||
365 | (readb(base+4) == hw_info[i].a2)) | ||
366 | break; | ||
367 | } | ||
368 | if (i < NR_INFO) { | ||
369 | for (j = 0; j < 6; j++) | ||
370 | dev->dev_addr[j] = readb(base + (j<<1)); | ||
371 | } | ||
372 | |||
373 | iounmap(virt); | ||
374 | j = pcmcia_release_window(link->win); | ||
375 | if (j != CS_SUCCESS) | ||
376 | cs_error(link->handle, ReleaseWindow, j); | ||
377 | return (i < NR_INFO) ? hw_info+i : NULL; | ||
378 | } /* get_hwinfo */ | ||
379 | |||
380 | /*====================================================================== | ||
381 | |||
382 | This probes for a card's hardware address by reading the PROM. | ||
383 | It checks the address against a list of known types, then falls | ||
384 | back to a simple NE2000 clone signature check. | ||
385 | |||
386 | ======================================================================*/ | ||
387 | |||
388 | static hw_info_t *get_prom(dev_link_t *link) | ||
389 | { | ||
390 | struct net_device *dev = link->priv; | ||
391 | kio_addr_t ioaddr = dev->base_addr; | ||
392 | u_char prom[32]; | ||
393 | int i, j; | ||
394 | |||
395 | /* This is lifted straight from drivers/net/ne.c */ | ||
396 | struct { | ||
397 | u_char value, offset; | ||
398 | } program_seq[] = { | ||
399 | {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ | ||
400 | {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */ | ||
401 | {0x00, EN0_RCNTLO}, /* Clear the count regs. */ | ||
402 | {0x00, EN0_RCNTHI}, | ||
403 | {0x00, EN0_IMR}, /* Mask completion irq. */ | ||
404 | {0xFF, EN0_ISR}, | ||
405 | {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ | ||
406 | {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ | ||
407 | {32, EN0_RCNTLO}, | ||
408 | {0x00, EN0_RCNTHI}, | ||
409 | {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ | ||
410 | {0x00, EN0_RSARHI}, | ||
411 | {E8390_RREAD+E8390_START, E8390_CMD}, | ||
412 | }; | ||
413 | |||
414 | pcnet_reset_8390(dev); | ||
415 | mdelay(10); | ||
416 | |||
417 | for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) | ||
418 | outb_p(program_seq[i].value, ioaddr + program_seq[i].offset); | ||
419 | |||
420 | for (i = 0; i < 32; i++) | ||
421 | prom[i] = inb(ioaddr + PCNET_DATAPORT); | ||
422 | for (i = 0; i < NR_INFO; i++) { | ||
423 | if ((prom[0] == hw_info[i].a0) && | ||
424 | (prom[2] == hw_info[i].a1) && | ||
425 | (prom[4] == hw_info[i].a2)) | ||
426 | break; | ||
427 | } | ||
428 | if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) { | ||
429 | for (j = 0; j < 6; j++) | ||
430 | dev->dev_addr[j] = prom[j<<1]; | ||
431 | return (i < NR_INFO) ? hw_info+i : &default_info; | ||
432 | } | ||
433 | return NULL; | ||
434 | } /* get_prom */ | ||
435 | |||
436 | /*====================================================================== | ||
437 | |||
438 | For DL10019 based cards, like the Linksys EtherFast | ||
439 | |||
440 | ======================================================================*/ | ||
441 | |||
442 | static hw_info_t *get_dl10019(dev_link_t *link) | ||
443 | { | ||
444 | struct net_device *dev = link->priv; | ||
445 | int i; | ||
446 | u_char sum; | ||
447 | |||
448 | for (sum = 0, i = 0x14; i < 0x1c; i++) | ||
449 | sum += inb_p(dev->base_addr + i); | ||
450 | if (sum != 0xff) | ||
451 | return NULL; | ||
452 | for (i = 0; i < 6; i++) | ||
453 | dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i); | ||
454 | i = inb(dev->base_addr + 0x1f); | ||
455 | return ((i == 0x91)||(i == 0x99)) ? &dl10022_info : &dl10019_info; | ||
456 | } | ||
457 | |||
458 | /*====================================================================== | ||
459 | |||
460 | For Asix AX88190 based cards | ||
461 | |||
462 | ======================================================================*/ | ||
463 | |||
464 | static hw_info_t *get_ax88190(dev_link_t *link) | ||
465 | { | ||
466 | struct net_device *dev = link->priv; | ||
467 | kio_addr_t ioaddr = dev->base_addr; | ||
468 | int i, j; | ||
469 | |||
470 | /* Not much of a test, but the alternatives are messy */ | ||
471 | if (link->conf.ConfigBase != 0x03c0) | ||
472 | return NULL; | ||
473 | |||
474 | outb_p(0x01, ioaddr + EN0_DCFG); /* Set word-wide access. */ | ||
475 | outb_p(0x00, ioaddr + EN0_RSARLO); /* DMA starting at 0x0400. */ | ||
476 | outb_p(0x04, ioaddr + EN0_RSARHI); | ||
477 | outb_p(E8390_RREAD+E8390_START, ioaddr + E8390_CMD); | ||
478 | |||
479 | for (i = 0; i < 6; i += 2) { | ||
480 | j = inw(ioaddr + PCNET_DATAPORT); | ||
481 | dev->dev_addr[i] = j & 0xff; | ||
482 | dev->dev_addr[i+1] = j >> 8; | ||
483 | } | ||
484 | printk(KERN_NOTICE "pcnet_cs: this is an AX88190 card!\n"); | ||
485 | printk(KERN_NOTICE "pcnet_cs: use axnet_cs instead.\n"); | ||
486 | return NULL; | ||
487 | } | ||
488 | |||
489 | /*====================================================================== | ||
490 | |||
491 | This should be totally unnecessary... but when we can't figure | ||
492 | out the hardware address any other way, we'll let the user hard | ||
493 | wire it when the module is initialized. | ||
494 | |||
495 | ======================================================================*/ | ||
496 | |||
497 | static hw_info_t *get_hwired(dev_link_t *link) | ||
498 | { | ||
499 | struct net_device *dev = link->priv; | ||
500 | int i; | ||
501 | |||
502 | for (i = 0; i < 6; i++) | ||
503 | if (hw_addr[i] != 0) break; | ||
504 | if (i == 6) | ||
505 | return NULL; | ||
506 | |||
507 | for (i = 0; i < 6; i++) | ||
508 | dev->dev_addr[i] = hw_addr[i]; | ||
509 | |||
510 | return &default_info; | ||
511 | } /* get_hwired */ | ||
512 | |||
513 | /*====================================================================== | ||
514 | |||
515 | pcnet_config() is scheduled to run after a CARD_INSERTION event | ||
516 | is received, to configure the PCMCIA socket, and to make the | ||
517 | ethernet device available to the system. | ||
518 | |||
519 | ======================================================================*/ | ||
520 | |||
521 | #define CS_CHECK(fn, ret) \ | ||
522 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
523 | |||
524 | static int try_io_port(dev_link_t *link) | ||
525 | { | ||
526 | int j, ret; | ||
527 | if (link->io.NumPorts1 == 32) { | ||
528 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
529 | if (link->io.NumPorts2 > 0) { | ||
530 | /* for master/slave multifunction cards */ | ||
531 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; | ||
532 | link->irq.Attributes = | ||
533 | IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | ||
534 | } | ||
535 | } else { | ||
536 | /* This should be two 16-port windows */ | ||
537 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
538 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_16; | ||
539 | } | ||
540 | if (link->io.BasePort1 == 0) { | ||
541 | link->io.IOAddrLines = 16; | ||
542 | for (j = 0; j < 0x400; j += 0x20) { | ||
543 | link->io.BasePort1 = j ^ 0x300; | ||
544 | link->io.BasePort2 = (j ^ 0x300) + 0x10; | ||
545 | ret = pcmcia_request_io(link->handle, &link->io); | ||
546 | if (ret == CS_SUCCESS) return ret; | ||
547 | } | ||
548 | return ret; | ||
549 | } else { | ||
550 | return pcmcia_request_io(link->handle, &link->io); | ||
551 | } | ||
552 | } | ||
553 | |||
554 | static void pcnet_config(dev_link_t *link) | ||
555 | { | ||
556 | client_handle_t handle = link->handle; | ||
557 | struct net_device *dev = link->priv; | ||
558 | pcnet_dev_t *info = PRIV(dev); | ||
559 | tuple_t tuple; | ||
560 | cisparse_t parse; | ||
561 | int i, last_ret, last_fn, start_pg, stop_pg, cm_offset; | ||
562 | int manfid = 0, prodid = 0, has_shmem = 0; | ||
563 | u_short buf[64]; | ||
564 | config_info_t conf; | ||
565 | hw_info_t *hw_info; | ||
566 | |||
567 | DEBUG(0, "pcnet_config(0x%p)\n", link); | ||
568 | |||
569 | tuple.Attributes = 0; | ||
570 | tuple.TupleData = (cisdata_t *)buf; | ||
571 | tuple.TupleDataMax = sizeof(buf); | ||
572 | tuple.TupleOffset = 0; | ||
573 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
574 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
575 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
576 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | ||
577 | link->conf.ConfigBase = parse.config.base; | ||
578 | link->conf.Present = parse.config.rmask[0]; | ||
579 | |||
580 | /* Configure card */ | ||
581 | link->state |= DEV_CONFIG; | ||
582 | |||
583 | /* Look up current Vcc */ | ||
584 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); | ||
585 | link->conf.Vcc = conf.Vcc; | ||
586 | |||
587 | tuple.DesiredTuple = CISTPL_MANFID; | ||
588 | tuple.Attributes = TUPLE_RETURN_COMMON; | ||
589 | if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && | ||
590 | (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) { | ||
591 | manfid = le16_to_cpu(buf[0]); | ||
592 | prodid = le16_to_cpu(buf[1]); | ||
593 | } | ||
594 | |||
595 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
596 | tuple.Attributes = 0; | ||
597 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
598 | while (last_ret == CS_SUCCESS) { | ||
599 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | ||
600 | cistpl_io_t *io = &(parse.cftable_entry.io); | ||
601 | |||
602 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | ||
603 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0 || | ||
604 | cfg->index == 0 || cfg->io.nwin == 0) | ||
605 | goto next_entry; | ||
606 | |||
607 | link->conf.ConfigIndex = cfg->index; | ||
608 | /* For multifunction cards, by convention, we configure the | ||
609 | network function with window 0, and serial with window 1 */ | ||
610 | if (io->nwin > 1) { | ||
611 | i = (io->win[1].len > io->win[0].len); | ||
612 | link->io.BasePort2 = io->win[1-i].base; | ||
613 | link->io.NumPorts2 = io->win[1-i].len; | ||
614 | } else { | ||
615 | i = link->io.NumPorts2 = 0; | ||
616 | } | ||
617 | has_shmem = ((cfg->mem.nwin == 1) && | ||
618 | (cfg->mem.win[0].len >= 0x4000)); | ||
619 | link->io.BasePort1 = io->win[i].base; | ||
620 | link->io.NumPorts1 = io->win[i].len; | ||
621 | link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
622 | if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) { | ||
623 | last_ret = try_io_port(link); | ||
624 | if (last_ret == CS_SUCCESS) break; | ||
625 | } | ||
626 | next_entry: | ||
627 | last_ret = pcmcia_get_next_tuple(handle, &tuple); | ||
628 | } | ||
629 | if (last_ret != CS_SUCCESS) { | ||
630 | cs_error(handle, RequestIO, last_ret); | ||
631 | goto failed; | ||
632 | } | ||
633 | |||
634 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | ||
635 | |||
636 | if (link->io.NumPorts2 == 8) { | ||
637 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
638 | link->conf.Status = CCSR_AUDIO_ENA; | ||
639 | } | ||
640 | if ((manfid == MANFID_IBM) && | ||
641 | (prodid == PRODID_IBM_HOME_AND_AWAY)) | ||
642 | link->conf.ConfigIndex |= 0x10; | ||
643 | |||
644 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | ||
645 | dev->irq = link->irq.AssignedIRQ; | ||
646 | dev->base_addr = link->io.BasePort1; | ||
647 | if (info->flags & HAS_MISC_REG) { | ||
648 | if ((if_port == 1) || (if_port == 2)) | ||
649 | dev->if_port = if_port; | ||
650 | else | ||
651 | printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n"); | ||
652 | } else { | ||
653 | dev->if_port = 0; | ||
654 | } | ||
655 | |||
656 | hw_info = get_hwinfo(link); | ||
657 | if (hw_info == NULL) | ||
658 | hw_info = get_prom(link); | ||
659 | if (hw_info == NULL) | ||
660 | hw_info = get_dl10019(link); | ||
661 | if (hw_info == NULL) | ||
662 | hw_info = get_ax88190(link); | ||
663 | if (hw_info == NULL) | ||
664 | hw_info = get_hwired(link); | ||
665 | |||
666 | if (hw_info == NULL) { | ||
667 | printk(KERN_NOTICE "pcnet_cs: unable to read hardware net" | ||
668 | " address for io base %#3lx\n", dev->base_addr); | ||
669 | goto failed; | ||
670 | } | ||
671 | |||
672 | info->flags = hw_info->flags; | ||
673 | /* Check for user overrides */ | ||
674 | info->flags |= (delay_output) ? DELAY_OUTPUT : 0; | ||
675 | if ((manfid == MANFID_SOCKET) && | ||
676 | ((prodid == PRODID_SOCKET_LPE) || | ||
677 | (prodid == PRODID_SOCKET_LPE_CF) || | ||
678 | (prodid == PRODID_SOCKET_EIO))) | ||
679 | info->flags &= ~USE_BIG_BUF; | ||
680 | if (!use_big_buf) | ||
681 | info->flags &= ~USE_BIG_BUF; | ||
682 | |||
683 | if (info->flags & USE_BIG_BUF) { | ||
684 | start_pg = SOCKET_START_PG; | ||
685 | stop_pg = SOCKET_STOP_PG; | ||
686 | cm_offset = 0x10000; | ||
687 | } else { | ||
688 | start_pg = PCNET_START_PG; | ||
689 | stop_pg = PCNET_STOP_PG; | ||
690 | cm_offset = 0; | ||
691 | } | ||
692 | |||
693 | /* has_shmem is ignored if use_shmem != -1 */ | ||
694 | if ((use_shmem == 0) || (!has_shmem && (use_shmem == -1)) || | ||
695 | (setup_shmem_window(link, start_pg, stop_pg, cm_offset) != 0)) | ||
696 | setup_dma_config(link, start_pg, stop_pg); | ||
697 | |||
698 | ei_status.name = "NE2000"; | ||
699 | ei_status.word16 = 1; | ||
700 | ei_status.reset_8390 = &pcnet_reset_8390; | ||
701 | |||
702 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | ||
703 | |||
704 | if (info->flags & (IS_DL10019|IS_DL10022)) { | ||
705 | u_char id = inb(dev->base_addr + 0x1a); | ||
706 | dev->do_ioctl = &ei_ioctl; | ||
707 | mii_phy_probe(dev); | ||
708 | if ((id == 0x30) && !info->pna_phy && (info->eth_phy == 4)) | ||
709 | info->eth_phy = 0; | ||
710 | } | ||
711 | |||
712 | link->dev = &info->node; | ||
713 | link->state &= ~DEV_CONFIG_PENDING; | ||
714 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
715 | |||
716 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
717 | dev->poll_controller = ei_poll; | ||
718 | #endif | ||
719 | |||
720 | if (register_netdev(dev) != 0) { | ||
721 | printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n"); | ||
722 | link->dev = NULL; | ||
723 | goto failed; | ||
724 | } | ||
725 | |||
726 | strcpy(info->node.dev_name, dev->name); | ||
727 | |||
728 | if (info->flags & (IS_DL10019|IS_DL10022)) { | ||
729 | u_char id = inb(dev->base_addr + 0x1a); | ||
730 | printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ", | ||
731 | dev->name, ((info->flags & IS_DL10022) ? 22 : 19), id); | ||
732 | if (info->pna_phy) | ||
733 | printk("PNA, "); | ||
734 | } else { | ||
735 | printk(KERN_INFO "%s: NE2000 Compatible: ", dev->name); | ||
736 | } | ||
737 | printk("io %#3lx, irq %d,", dev->base_addr, dev->irq); | ||
738 | if (info->flags & USE_SHMEM) | ||
739 | printk (" mem %#5lx,", dev->mem_start); | ||
740 | if (info->flags & HAS_MISC_REG) | ||
741 | printk(" %s xcvr,", if_names[dev->if_port]); | ||
742 | printk(" hw_addr "); | ||
743 | for (i = 0; i < 6; i++) | ||
744 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); | ||
745 | return; | ||
746 | |||
747 | cs_failed: | ||
748 | cs_error(link->handle, last_fn, last_ret); | ||
749 | failed: | ||
750 | pcnet_release(link); | ||
751 | link->state &= ~DEV_CONFIG_PENDING; | ||
752 | return; | ||
753 | } /* pcnet_config */ | ||
754 | |||
755 | /*====================================================================== | ||
756 | |||
757 | After a card is removed, pcnet_release() will unregister the net | ||
758 | device, and release the PCMCIA configuration. If the device is | ||
759 | still open, this will be postponed until it is closed. | ||
760 | |||
761 | ======================================================================*/ | ||
762 | |||
763 | static void pcnet_release(dev_link_t *link) | ||
764 | { | ||
765 | pcnet_dev_t *info = PRIV(link->priv); | ||
766 | |||
767 | DEBUG(0, "pcnet_release(0x%p)\n", link); | ||
768 | |||
769 | if (info->flags & USE_SHMEM) { | ||
770 | iounmap(info->base); | ||
771 | pcmcia_release_window(link->win); | ||
772 | } | ||
773 | pcmcia_release_configuration(link->handle); | ||
774 | pcmcia_release_io(link->handle, &link->io); | ||
775 | pcmcia_release_irq(link->handle, &link->irq); | ||
776 | |||
777 | link->state &= ~DEV_CONFIG; | ||
778 | } | ||
779 | |||
780 | /*====================================================================== | ||
781 | |||
782 | The card status event handler. Mostly, this schedules other | ||
783 | stuff to run after an event is received. A CARD_REMOVAL event | ||
784 | also sets some flags to discourage the net drivers from trying | ||
785 | to talk to the card any more. | ||
786 | |||
787 | ======================================================================*/ | ||
788 | |||
789 | static int pcnet_event(event_t event, int priority, | ||
790 | event_callback_args_t *args) | ||
791 | { | ||
792 | dev_link_t *link = args->client_data; | ||
793 | struct net_device *dev = link->priv; | ||
794 | |||
795 | DEBUG(2, "pcnet_event(0x%06x)\n", event); | ||
796 | |||
797 | switch (event) { | ||
798 | case CS_EVENT_CARD_REMOVAL: | ||
799 | link->state &= ~DEV_PRESENT; | ||
800 | if (link->state & DEV_CONFIG) | ||
801 | netif_device_detach(dev); | ||
802 | break; | ||
803 | case CS_EVENT_CARD_INSERTION: | ||
804 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
805 | pcnet_config(link); | ||
806 | break; | ||
807 | case CS_EVENT_PM_SUSPEND: | ||
808 | link->state |= DEV_SUSPEND; | ||
809 | /* Fall through... */ | ||
810 | case CS_EVENT_RESET_PHYSICAL: | ||
811 | if (link->state & DEV_CONFIG) { | ||
812 | if (link->open) | ||
813 | netif_device_detach(dev); | ||
814 | pcmcia_release_configuration(link->handle); | ||
815 | } | ||
816 | break; | ||
817 | case CS_EVENT_PM_RESUME: | ||
818 | link->state &= ~DEV_SUSPEND; | ||
819 | /* Fall through... */ | ||
820 | case CS_EVENT_CARD_RESET: | ||
821 | if (link->state & DEV_CONFIG) { | ||
822 | pcmcia_request_configuration(link->handle, &link->conf); | ||
823 | if (link->open) { | ||
824 | pcnet_reset_8390(dev); | ||
825 | NS8390_init(dev, 1); | ||
826 | netif_device_attach(dev); | ||
827 | } | ||
828 | } | ||
829 | break; | ||
830 | } | ||
831 | return 0; | ||
832 | } /* pcnet_event */ | ||
833 | |||
834 | /*====================================================================== | ||
835 | |||
836 | MII interface support for DL10019 and DL10022 based cards | ||
837 | |||
838 | On the DL10019, the MII IO direction bit is 0x10; on the DL10022 | ||
839 | it is 0x20. Setting both bits seems to work on both card types. | ||
840 | |||
841 | ======================================================================*/ | ||
842 | |||
843 | #define DLINK_GPIO 0x1c | ||
844 | #define DLINK_DIAG 0x1d | ||
845 | #define DLINK_EEPROM 0x1e | ||
846 | |||
847 | #define MDIO_SHIFT_CLK 0x80 | ||
848 | #define MDIO_DATA_OUT 0x40 | ||
849 | #define MDIO_DIR_WRITE 0x30 | ||
850 | #define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE) | ||
851 | #define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT) | ||
852 | #define MDIO_DATA_READ 0x10 | ||
853 | #define MDIO_MASK 0x0f | ||
854 | |||
855 | static void mdio_sync(kio_addr_t addr) | ||
856 | { | ||
857 | int bits, mask = inb(addr) & MDIO_MASK; | ||
858 | for (bits = 0; bits < 32; bits++) { | ||
859 | outb(mask | MDIO_DATA_WRITE1, addr); | ||
860 | outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr); | ||
861 | } | ||
862 | } | ||
863 | |||
864 | static int mdio_read(kio_addr_t addr, int phy_id, int loc) | ||
865 | { | ||
866 | u_int cmd = (0x06<<10)|(phy_id<<5)|loc; | ||
867 | int i, retval = 0, mask = inb(addr) & MDIO_MASK; | ||
868 | |||
869 | mdio_sync(addr); | ||
870 | for (i = 13; i >= 0; i--) { | ||
871 | int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; | ||
872 | outb(mask | dat, addr); | ||
873 | outb(mask | dat | MDIO_SHIFT_CLK, addr); | ||
874 | } | ||
875 | for (i = 19; i > 0; i--) { | ||
876 | outb(mask, addr); | ||
877 | retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0); | ||
878 | outb(mask | MDIO_SHIFT_CLK, addr); | ||
879 | } | ||
880 | return (retval>>1) & 0xffff; | ||
881 | } | ||
882 | |||
883 | static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value) | ||
884 | { | ||
885 | u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value; | ||
886 | int i, mask = inb(addr) & MDIO_MASK; | ||
887 | |||
888 | mdio_sync(addr); | ||
889 | for (i = 31; i >= 0; i--) { | ||
890 | int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; | ||
891 | outb(mask | dat, addr); | ||
892 | outb(mask | dat | MDIO_SHIFT_CLK, addr); | ||
893 | } | ||
894 | for (i = 1; i >= 0; i--) { | ||
895 | outb(mask, addr); | ||
896 | outb(mask | MDIO_SHIFT_CLK, addr); | ||
897 | } | ||
898 | } | ||
899 | |||
900 | static void mdio_reset(kio_addr_t addr, int phy_id) | ||
901 | { | ||
902 | outb_p(0x08, addr); | ||
903 | outb_p(0x0c, addr); | ||
904 | outb_p(0x08, addr); | ||
905 | outb_p(0x0c, addr); | ||
906 | outb_p(0x00, addr); | ||
907 | } | ||
908 | |||
909 | /*====================================================================== | ||
910 | |||
911 | EEPROM access routines for DL10019 and DL10022 based cards | ||
912 | |||
913 | ======================================================================*/ | ||
914 | |||
915 | #define EE_EEP 0x40 | ||
916 | #define EE_ASIC 0x10 | ||
917 | #define EE_CS 0x08 | ||
918 | #define EE_CK 0x04 | ||
919 | #define EE_DO 0x02 | ||
920 | #define EE_DI 0x01 | ||
921 | #define EE_ADOT 0x01 /* DataOut for ASIC */ | ||
922 | #define EE_READ_CMD 0x06 | ||
923 | |||
924 | #define DL19FDUPLX 0x0400 /* DL10019 Full duplex mode */ | ||
925 | |||
926 | static int read_eeprom(kio_addr_t ioaddr, int location) | ||
927 | { | ||
928 | int i, retval = 0; | ||
929 | kio_addr_t ee_addr = ioaddr + DLINK_EEPROM; | ||
930 | int read_cmd = location | (EE_READ_CMD << 8); | ||
931 | |||
932 | outb(0, ee_addr); | ||
933 | outb(EE_EEP|EE_CS, ee_addr); | ||
934 | |||
935 | /* Shift the read command bits out. */ | ||
936 | for (i = 10; i >= 0; i--) { | ||
937 | short dataval = (read_cmd & (1 << i)) ? EE_DO : 0; | ||
938 | outb_p(EE_EEP|EE_CS|dataval, ee_addr); | ||
939 | outb_p(EE_EEP|EE_CS|dataval|EE_CK, ee_addr); | ||
940 | } | ||
941 | outb(EE_EEP|EE_CS, ee_addr); | ||
942 | |||
943 | for (i = 16; i > 0; i--) { | ||
944 | outb_p(EE_EEP|EE_CS | EE_CK, ee_addr); | ||
945 | retval = (retval << 1) | ((inb(ee_addr) & EE_DI) ? 1 : 0); | ||
946 | outb_p(EE_EEP|EE_CS, ee_addr); | ||
947 | } | ||
948 | |||
949 | /* Terminate the EEPROM access. */ | ||
950 | outb(0, ee_addr); | ||
951 | return retval; | ||
952 | } | ||
953 | |||
954 | /* | ||
955 | The internal ASIC registers can be changed by EEPROM READ access | ||
956 | with EE_ASIC bit set. | ||
957 | In ASIC mode, EE_ADOT is used to output the data to the ASIC. | ||
958 | */ | ||
959 | |||
960 | static void write_asic(kio_addr_t ioaddr, int location, short asic_data) | ||
961 | { | ||
962 | int i; | ||
963 | kio_addr_t ee_addr = ioaddr + DLINK_EEPROM; | ||
964 | short dataval; | ||
965 | int read_cmd = location | (EE_READ_CMD << 8); | ||
966 | |||
967 | asic_data |= read_eeprom(ioaddr, location); | ||
968 | |||
969 | outb(0, ee_addr); | ||
970 | outb(EE_ASIC|EE_CS|EE_DI, ee_addr); | ||
971 | |||
972 | read_cmd = read_cmd >> 1; | ||
973 | |||
974 | /* Shift the read command bits out. */ | ||
975 | for (i = 9; i >= 0; i--) { | ||
976 | dataval = (read_cmd & (1 << i)) ? EE_DO : 0; | ||
977 | outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr); | ||
978 | outb_p(EE_ASIC|EE_CS|EE_DI|dataval|EE_CK, ee_addr); | ||
979 | outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr); | ||
980 | } | ||
981 | // sync | ||
982 | outb(EE_ASIC|EE_CS, ee_addr); | ||
983 | outb(EE_ASIC|EE_CS|EE_CK, ee_addr); | ||
984 | outb(EE_ASIC|EE_CS, ee_addr); | ||
985 | |||
986 | for (i = 15; i >= 0; i--) { | ||
987 | dataval = (asic_data & (1 << i)) ? EE_ADOT : 0; | ||
988 | outb_p(EE_ASIC|EE_CS|dataval, ee_addr); | ||
989 | outb_p(EE_ASIC|EE_CS|dataval|EE_CK, ee_addr); | ||
990 | outb_p(EE_ASIC|EE_CS|dataval, ee_addr); | ||
991 | } | ||
992 | |||
993 | /* Terminate the ASIC access. */ | ||
994 | outb(EE_ASIC|EE_DI, ee_addr); | ||
995 | outb(EE_ASIC|EE_DI| EE_CK, ee_addr); | ||
996 | outb(EE_ASIC|EE_DI, ee_addr); | ||
997 | |||
998 | outb(0, ee_addr); | ||
999 | } | ||
1000 | |||
1001 | /*====================================================================*/ | ||
1002 | |||
1003 | static void set_misc_reg(struct net_device *dev) | ||
1004 | { | ||
1005 | kio_addr_t nic_base = dev->base_addr; | ||
1006 | pcnet_dev_t *info = PRIV(dev); | ||
1007 | u_char tmp; | ||
1008 | |||
1009 | if (info->flags & HAS_MISC_REG) { | ||
1010 | tmp = inb_p(nic_base + PCNET_MISC) & ~3; | ||
1011 | if (dev->if_port == 2) | ||
1012 | tmp |= 1; | ||
1013 | if (info->flags & USE_BIG_BUF) | ||
1014 | tmp |= 2; | ||
1015 | if (info->flags & HAS_IBM_MISC) | ||
1016 | tmp |= 8; | ||
1017 | outb_p(tmp, nic_base + PCNET_MISC); | ||
1018 | } | ||
1019 | if (info->flags & IS_DL10022) { | ||
1020 | if (info->flags & HAS_MII) { | ||
1021 | mdio_reset(nic_base + DLINK_GPIO, info->eth_phy); | ||
1022 | /* Restart MII autonegotiation */ | ||
1023 | mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000); | ||
1024 | mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200); | ||
1025 | info->mii_reset = jiffies; | ||
1026 | } else { | ||
1027 | outb(full_duplex ? 4 : 0, nic_base + DLINK_DIAG); | ||
1028 | } | ||
1029 | } | ||
1030 | } | ||
1031 | |||
1032 | /*====================================================================*/ | ||
1033 | |||
1034 | static void mii_phy_probe(struct net_device *dev) | ||
1035 | { | ||
1036 | pcnet_dev_t *info = PRIV(dev); | ||
1037 | kio_addr_t mii_addr = dev->base_addr + DLINK_GPIO; | ||
1038 | int i; | ||
1039 | u_int tmp, phyid; | ||
1040 | |||
1041 | for (i = 31; i >= 0; i--) { | ||
1042 | tmp = mdio_read(mii_addr, i, 1); | ||
1043 | if ((tmp == 0) || (tmp == 0xffff)) | ||
1044 | continue; | ||
1045 | tmp = mdio_read(mii_addr, i, MII_PHYID_REG1); | ||
1046 | phyid = tmp << 16; | ||
1047 | phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2); | ||
1048 | phyid &= MII_PHYID_REV_MASK; | ||
1049 | DEBUG(0, "%s: MII at %d is 0x%08x\n", dev->name, i, phyid); | ||
1050 | if (phyid == AM79C9XX_HOME_PHY) { | ||
1051 | info->pna_phy = i; | ||
1052 | } else if (phyid != AM79C9XX_ETH_PHY) { | ||
1053 | info->eth_phy = i; | ||
1054 | } | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | static int pcnet_open(struct net_device *dev) | ||
1059 | { | ||
1060 | pcnet_dev_t *info = PRIV(dev); | ||
1061 | dev_link_t *link = &info->link; | ||
1062 | |||
1063 | DEBUG(2, "pcnet_open('%s')\n", dev->name); | ||
1064 | |||
1065 | if (!DEV_OK(link)) | ||
1066 | return -ENODEV; | ||
1067 | |||
1068 | link->open++; | ||
1069 | |||
1070 | set_misc_reg(dev); | ||
1071 | request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev); | ||
1072 | |||
1073 | info->phy_id = info->eth_phy; | ||
1074 | info->link_status = 0x00; | ||
1075 | init_timer(&info->watchdog); | ||
1076 | info->watchdog.function = &ei_watchdog; | ||
1077 | info->watchdog.data = (u_long)dev; | ||
1078 | info->watchdog.expires = jiffies + HZ; | ||
1079 | add_timer(&info->watchdog); | ||
1080 | |||
1081 | return ei_open(dev); | ||
1082 | } /* pcnet_open */ | ||
1083 | |||
1084 | /*====================================================================*/ | ||
1085 | |||
1086 | static int pcnet_close(struct net_device *dev) | ||
1087 | { | ||
1088 | pcnet_dev_t *info = PRIV(dev); | ||
1089 | dev_link_t *link = &info->link; | ||
1090 | |||
1091 | DEBUG(2, "pcnet_close('%s')\n", dev->name); | ||
1092 | |||
1093 | ei_close(dev); | ||
1094 | free_irq(dev->irq, dev); | ||
1095 | |||
1096 | link->open--; | ||
1097 | netif_stop_queue(dev); | ||
1098 | del_timer_sync(&info->watchdog); | ||
1099 | |||
1100 | return 0; | ||
1101 | } /* pcnet_close */ | ||
1102 | |||
1103 | /*====================================================================== | ||
1104 | |||
1105 | Hard reset the card. This used to pause for the same period that | ||
1106 | a 8390 reset command required, but that shouldn't be necessary. | ||
1107 | |||
1108 | ======================================================================*/ | ||
1109 | |||
1110 | static void pcnet_reset_8390(struct net_device *dev) | ||
1111 | { | ||
1112 | kio_addr_t nic_base = dev->base_addr; | ||
1113 | int i; | ||
1114 | |||
1115 | ei_status.txing = ei_status.dmaing = 0; | ||
1116 | |||
1117 | outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD); | ||
1118 | |||
1119 | outb(inb(nic_base + PCNET_RESET), nic_base + PCNET_RESET); | ||
1120 | |||
1121 | for (i = 0; i < 100; i++) { | ||
1122 | if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0) | ||
1123 | break; | ||
1124 | udelay(100); | ||
1125 | } | ||
1126 | outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */ | ||
1127 | |||
1128 | if (i == 100) | ||
1129 | printk(KERN_ERR "%s: pcnet_reset_8390() did not complete.\n", | ||
1130 | dev->name); | ||
1131 | set_misc_reg(dev); | ||
1132 | |||
1133 | } /* pcnet_reset_8390 */ | ||
1134 | |||
1135 | /*====================================================================*/ | ||
1136 | |||
1137 | static int set_config(struct net_device *dev, struct ifmap *map) | ||
1138 | { | ||
1139 | pcnet_dev_t *info = PRIV(dev); | ||
1140 | if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { | ||
1141 | if (!(info->flags & HAS_MISC_REG)) | ||
1142 | return -EOPNOTSUPP; | ||
1143 | else if ((map->port < 1) || (map->port > 2)) | ||
1144 | return -EINVAL; | ||
1145 | dev->if_port = map->port; | ||
1146 | printk(KERN_INFO "%s: switched to %s port\n", | ||
1147 | dev->name, if_names[dev->if_port]); | ||
1148 | NS8390_init(dev, 1); | ||
1149 | } | ||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | /*====================================================================*/ | ||
1154 | |||
1155 | static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs) | ||
1156 | { | ||
1157 | struct net_device *dev = dev_id; | ||
1158 | pcnet_dev_t *info = PRIV(dev); | ||
1159 | irqreturn_t ret = ei_interrupt(irq, dev_id, regs); | ||
1160 | |||
1161 | if (ret == IRQ_HANDLED) | ||
1162 | info->stale = 0; | ||
1163 | return ret; | ||
1164 | } | ||
1165 | |||
1166 | static void ei_watchdog(u_long arg) | ||
1167 | { | ||
1168 | struct net_device *dev = (struct net_device *)arg; | ||
1169 | pcnet_dev_t *info = PRIV(dev); | ||
1170 | kio_addr_t nic_base = dev->base_addr; | ||
1171 | kio_addr_t mii_addr = nic_base + DLINK_GPIO; | ||
1172 | u_short link; | ||
1173 | |||
1174 | if (!netif_device_present(dev)) goto reschedule; | ||
1175 | |||
1176 | /* Check for pending interrupt with expired latency timer: with | ||
1177 | this, we can limp along even if the interrupt is blocked */ | ||
1178 | outb_p(E8390_NODMA+E8390_PAGE0, nic_base + E8390_CMD); | ||
1179 | if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { | ||
1180 | if (!info->fast_poll) | ||
1181 | printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); | ||
1182 | ei_irq_wrapper(dev->irq, dev, NULL); | ||
1183 | info->fast_poll = HZ; | ||
1184 | } | ||
1185 | if (info->fast_poll) { | ||
1186 | info->fast_poll--; | ||
1187 | info->watchdog.expires = jiffies + 1; | ||
1188 | add_timer(&info->watchdog); | ||
1189 | return; | ||
1190 | } | ||
1191 | |||
1192 | if (!(info->flags & HAS_MII)) | ||
1193 | goto reschedule; | ||
1194 | |||
1195 | mdio_read(mii_addr, info->phy_id, 1); | ||
1196 | link = mdio_read(mii_addr, info->phy_id, 1); | ||
1197 | if (!link || (link == 0xffff)) { | ||
1198 | if (info->eth_phy) { | ||
1199 | info->phy_id = info->eth_phy = 0; | ||
1200 | } else { | ||
1201 | printk(KERN_INFO "%s: MII is missing!\n", dev->name); | ||
1202 | info->flags &= ~HAS_MII; | ||
1203 | } | ||
1204 | goto reschedule; | ||
1205 | } | ||
1206 | |||
1207 | link &= 0x0004; | ||
1208 | if (link != info->link_status) { | ||
1209 | u_short p = mdio_read(mii_addr, info->phy_id, 5); | ||
1210 | printk(KERN_INFO "%s: %s link beat\n", dev->name, | ||
1211 | (link) ? "found" : "lost"); | ||
1212 | if (link && (info->flags & IS_DL10022)) { | ||
1213 | /* Disable collision detection on full duplex links */ | ||
1214 | outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG); | ||
1215 | } else if (link && (info->flags & IS_DL10019)) { | ||
1216 | /* Disable collision detection on full duplex links */ | ||
1217 | write_asic(dev->base_addr, 4, (p & 0x140) ? DL19FDUPLX : 0); | ||
1218 | } | ||
1219 | if (link) { | ||
1220 | if (info->phy_id == info->eth_phy) { | ||
1221 | if (p) | ||
1222 | printk(KERN_INFO "%s: autonegotiation complete: " | ||
1223 | "%sbaseT-%cD selected\n", dev->name, | ||
1224 | ((p & 0x0180) ? "100" : "10"), | ||
1225 | ((p & 0x0140) ? 'F' : 'H')); | ||
1226 | else | ||
1227 | printk(KERN_INFO "%s: link partner did not " | ||
1228 | "autonegotiate\n", dev->name); | ||
1229 | } | ||
1230 | NS8390_init(dev, 1); | ||
1231 | } | ||
1232 | info->link_status = link; | ||
1233 | } | ||
1234 | if (info->pna_phy && time_after(jiffies, info->mii_reset + 6*HZ)) { | ||
1235 | link = mdio_read(mii_addr, info->eth_phy, 1) & 0x0004; | ||
1236 | if (((info->phy_id == info->pna_phy) && link) || | ||
1237 | ((info->phy_id != info->pna_phy) && !link)) { | ||
1238 | /* isolate this MII and try flipping to the other one */ | ||
1239 | mdio_write(mii_addr, info->phy_id, 0, 0x0400); | ||
1240 | info->phy_id ^= info->pna_phy ^ info->eth_phy; | ||
1241 | printk(KERN_INFO "%s: switched to %s transceiver\n", dev->name, | ||
1242 | (info->phy_id == info->eth_phy) ? "ethernet" : "PNA"); | ||
1243 | mdio_write(mii_addr, info->phy_id, 0, | ||
1244 | (info->phy_id == info->eth_phy) ? 0x1000 : 0); | ||
1245 | info->link_status = 0; | ||
1246 | info->mii_reset = jiffies; | ||
1247 | } | ||
1248 | } | ||
1249 | |||
1250 | reschedule: | ||
1251 | info->watchdog.expires = jiffies + HZ; | ||
1252 | add_timer(&info->watchdog); | ||
1253 | } | ||
1254 | |||
1255 | /*====================================================================*/ | ||
1256 | |||
1257 | static void netdev_get_drvinfo(struct net_device *dev, | ||
1258 | struct ethtool_drvinfo *info) | ||
1259 | { | ||
1260 | strcpy(info->driver, "pcnet_cs"); | ||
1261 | } | ||
1262 | |||
1263 | static struct ethtool_ops netdev_ethtool_ops = { | ||
1264 | .get_drvinfo = netdev_get_drvinfo, | ||
1265 | }; | ||
1266 | |||
1267 | /*====================================================================*/ | ||
1268 | |||
1269 | |||
1270 | static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||
1271 | { | ||
1272 | pcnet_dev_t *info = PRIV(dev); | ||
1273 | u16 *data = (u16 *)&rq->ifr_ifru; | ||
1274 | kio_addr_t mii_addr = dev->base_addr + DLINK_GPIO; | ||
1275 | switch (cmd) { | ||
1276 | case SIOCGMIIPHY: | ||
1277 | data[0] = info->phy_id; | ||
1278 | case SIOCGMIIREG: /* Read MII PHY register. */ | ||
1279 | data[3] = mdio_read(mii_addr, data[0], data[1] & 0x1f); | ||
1280 | return 0; | ||
1281 | case SIOCSMIIREG: /* Write MII PHY register. */ | ||
1282 | if (!capable(CAP_NET_ADMIN)) | ||
1283 | return -EPERM; | ||
1284 | mdio_write(mii_addr, data[0], data[1] & 0x1f, data[2]); | ||
1285 | return 0; | ||
1286 | } | ||
1287 | return -EOPNOTSUPP; | ||
1288 | } | ||
1289 | |||
1290 | /*====================================================================*/ | ||
1291 | |||
1292 | static void dma_get_8390_hdr(struct net_device *dev, | ||
1293 | struct e8390_pkt_hdr *hdr, | ||
1294 | int ring_page) | ||
1295 | { | ||
1296 | kio_addr_t nic_base = dev->base_addr; | ||
1297 | |||
1298 | if (ei_status.dmaing) { | ||
1299 | printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input." | ||
1300 | "[DMAstat:%1x][irqlock:%1x]\n", | ||
1301 | dev->name, ei_status.dmaing, ei_status.irqlock); | ||
1302 | return; | ||
1303 | } | ||
1304 | |||
1305 | ei_status.dmaing |= 0x01; | ||
1306 | outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD); | ||
1307 | outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); | ||
1308 | outb_p(0, nic_base + EN0_RCNTHI); | ||
1309 | outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */ | ||
1310 | outb_p(ring_page, nic_base + EN0_RSARHI); | ||
1311 | outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD); | ||
1312 | |||
1313 | insw(nic_base + PCNET_DATAPORT, hdr, | ||
1314 | sizeof(struct e8390_pkt_hdr)>>1); | ||
1315 | /* Fix for big endian systems */ | ||
1316 | hdr->count = le16_to_cpu(hdr->count); | ||
1317 | |||
1318 | outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ | ||
1319 | ei_status.dmaing &= ~0x01; | ||
1320 | } | ||
1321 | |||
1322 | /*====================================================================*/ | ||
1323 | |||
1324 | static void dma_block_input(struct net_device *dev, int count, | ||
1325 | struct sk_buff *skb, int ring_offset) | ||
1326 | { | ||
1327 | kio_addr_t nic_base = dev->base_addr; | ||
1328 | int xfer_count = count; | ||
1329 | char *buf = skb->data; | ||
1330 | |||
1331 | #ifdef PCMCIA_DEBUG | ||
1332 | if ((ei_debug > 4) && (count != 4)) | ||
1333 | printk(KERN_DEBUG "%s: [bi=%d]\n", dev->name, count+4); | ||
1334 | #endif | ||
1335 | if (ei_status.dmaing) { | ||
1336 | printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input." | ||
1337 | "[DMAstat:%1x][irqlock:%1x]\n", | ||
1338 | dev->name, ei_status.dmaing, ei_status.irqlock); | ||
1339 | return; | ||
1340 | } | ||
1341 | ei_status.dmaing |= 0x01; | ||
1342 | outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD); | ||
1343 | outb_p(count & 0xff, nic_base + EN0_RCNTLO); | ||
1344 | outb_p(count >> 8, nic_base + EN0_RCNTHI); | ||
1345 | outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); | ||
1346 | outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); | ||
1347 | outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD); | ||
1348 | |||
1349 | insw(nic_base + PCNET_DATAPORT,buf,count>>1); | ||
1350 | if (count & 0x01) | ||
1351 | buf[count-1] = inb(nic_base + PCNET_DATAPORT), xfer_count++; | ||
1352 | |||
1353 | /* This was for the ALPHA version only, but enough people have | ||
1354 | encountering problems that it is still here. */ | ||
1355 | #ifdef PCMCIA_DEBUG | ||
1356 | if (ei_debug > 4) { /* DMA termination address check... */ | ||
1357 | int addr, tries = 20; | ||
1358 | do { | ||
1359 | /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here | ||
1360 | -- it's broken for Rx on some cards! */ | ||
1361 | int high = inb_p(nic_base + EN0_RSARHI); | ||
1362 | int low = inb_p(nic_base + EN0_RSARLO); | ||
1363 | addr = (high << 8) + low; | ||
1364 | if (((ring_offset + xfer_count) & 0xff) == (addr & 0xff)) | ||
1365 | break; | ||
1366 | } while (--tries > 0); | ||
1367 | if (tries <= 0) | ||
1368 | printk(KERN_NOTICE "%s: RX transfer address mismatch," | ||
1369 | "%#4.4x (expected) vs. %#4.4x (actual).\n", | ||
1370 | dev->name, ring_offset + xfer_count, addr); | ||
1371 | } | ||
1372 | #endif | ||
1373 | outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ | ||
1374 | ei_status.dmaing &= ~0x01; | ||
1375 | } /* dma_block_input */ | ||
1376 | |||
1377 | /*====================================================================*/ | ||
1378 | |||
1379 | static void dma_block_output(struct net_device *dev, int count, | ||
1380 | const u_char *buf, const int start_page) | ||
1381 | { | ||
1382 | kio_addr_t nic_base = dev->base_addr; | ||
1383 | pcnet_dev_t *info = PRIV(dev); | ||
1384 | #ifdef PCMCIA_DEBUG | ||
1385 | int retries = 0; | ||
1386 | #endif | ||
1387 | u_long dma_start; | ||
1388 | |||
1389 | #ifdef PCMCIA_DEBUG | ||
1390 | if (ei_debug > 4) | ||
1391 | printk(KERN_DEBUG "%s: [bo=%d]\n", dev->name, count); | ||
1392 | #endif | ||
1393 | |||
1394 | /* Round the count up for word writes. Do we need to do this? | ||
1395 | What effect will an odd byte count have on the 8390? | ||
1396 | I should check someday. */ | ||
1397 | if (count & 0x01) | ||
1398 | count++; | ||
1399 | if (ei_status.dmaing) { | ||
1400 | printk(KERN_NOTICE "%s: DMAing conflict in dma_block_output." | ||
1401 | "[DMAstat:%1x][irqlock:%1x]\n", | ||
1402 | dev->name, ei_status.dmaing, ei_status.irqlock); | ||
1403 | return; | ||
1404 | } | ||
1405 | ei_status.dmaing |= 0x01; | ||
1406 | /* We should already be in page 0, but to be safe... */ | ||
1407 | outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base+PCNET_CMD); | ||
1408 | |||
1409 | #ifdef PCMCIA_DEBUG | ||
1410 | retry: | ||
1411 | #endif | ||
1412 | |||
1413 | outb_p(ENISR_RDC, nic_base + EN0_ISR); | ||
1414 | |||
1415 | /* Now the normal output. */ | ||
1416 | outb_p(count & 0xff, nic_base + EN0_RCNTLO); | ||
1417 | outb_p(count >> 8, nic_base + EN0_RCNTHI); | ||
1418 | outb_p(0x00, nic_base + EN0_RSARLO); | ||
1419 | outb_p(start_page, nic_base + EN0_RSARHI); | ||
1420 | |||
1421 | outb_p(E8390_RWRITE+E8390_START, nic_base + PCNET_CMD); | ||
1422 | outsw(nic_base + PCNET_DATAPORT, buf, count>>1); | ||
1423 | |||
1424 | dma_start = jiffies; | ||
1425 | |||
1426 | #ifdef PCMCIA_DEBUG | ||
1427 | /* This was for the ALPHA version only, but enough people have | ||
1428 | encountering problems that it is still here. */ | ||
1429 | if (ei_debug > 4) { /* DMA termination address check... */ | ||
1430 | int addr, tries = 20; | ||
1431 | do { | ||
1432 | int high = inb_p(nic_base + EN0_RSARHI); | ||
1433 | int low = inb_p(nic_base + EN0_RSARLO); | ||
1434 | addr = (high << 8) + low; | ||
1435 | if ((start_page << 8) + count == addr) | ||
1436 | break; | ||
1437 | } while (--tries > 0); | ||
1438 | if (tries <= 0) { | ||
1439 | printk(KERN_NOTICE "%s: Tx packet transfer address mismatch," | ||
1440 | "%#4.4x (expected) vs. %#4.4x (actual).\n", | ||
1441 | dev->name, (start_page << 8) + count, addr); | ||
1442 | if (retries++ == 0) | ||
1443 | goto retry; | ||
1444 | } | ||
1445 | } | ||
1446 | #endif | ||
1447 | |||
1448 | while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) | ||
1449 | if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) { | ||
1450 | printk(KERN_NOTICE "%s: timeout waiting for Tx RDC.\n", | ||
1451 | dev->name); | ||
1452 | pcnet_reset_8390(dev); | ||
1453 | NS8390_init(dev, 1); | ||
1454 | break; | ||
1455 | } | ||
1456 | |||
1457 | outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ | ||
1458 | if (info->flags & DELAY_OUTPUT) | ||
1459 | udelay((long)delay_time); | ||
1460 | ei_status.dmaing &= ~0x01; | ||
1461 | } | ||
1462 | |||
1463 | /*====================================================================*/ | ||
1464 | |||
1465 | static int setup_dma_config(dev_link_t *link, int start_pg, | ||
1466 | int stop_pg) | ||
1467 | { | ||
1468 | struct net_device *dev = link->priv; | ||
1469 | |||
1470 | ei_status.tx_start_page = start_pg; | ||
1471 | ei_status.rx_start_page = start_pg + TX_PAGES; | ||
1472 | ei_status.stop_page = stop_pg; | ||
1473 | |||
1474 | /* set up block i/o functions */ | ||
1475 | ei_status.get_8390_hdr = &dma_get_8390_hdr; | ||
1476 | ei_status.block_input = &dma_block_input; | ||
1477 | ei_status.block_output = &dma_block_output; | ||
1478 | |||
1479 | return 0; | ||
1480 | } | ||
1481 | |||
1482 | /*====================================================================*/ | ||
1483 | |||
1484 | static void copyin(void *dest, void __iomem *src, int c) | ||
1485 | { | ||
1486 | u_short *d = dest; | ||
1487 | u_short __iomem *s = src; | ||
1488 | int odd; | ||
1489 | |||
1490 | if (c <= 0) | ||
1491 | return; | ||
1492 | odd = (c & 1); c >>= 1; | ||
1493 | |||
1494 | if (c) { | ||
1495 | do { *d++ = __raw_readw(s++); } while (--c); | ||
1496 | } | ||
1497 | /* get last byte by fetching a word and masking */ | ||
1498 | if (odd) | ||
1499 | *((u_char *)d) = readw(s) & 0xff; | ||
1500 | } | ||
1501 | |||
1502 | static void copyout(void __iomem *dest, const void *src, int c) | ||
1503 | { | ||
1504 | u_short __iomem *d = dest; | ||
1505 | const u_short *s = src; | ||
1506 | int odd; | ||
1507 | |||
1508 | if (c <= 0) | ||
1509 | return; | ||
1510 | odd = (c & 1); c >>= 1; | ||
1511 | |||
1512 | if (c) { | ||
1513 | do { __raw_writew(*s++, d++); } while (--c); | ||
1514 | } | ||
1515 | /* copy last byte doing a read-modify-write */ | ||
1516 | if (odd) | ||
1517 | writew((readw(d) & 0xff00) | *(u_char *)s, d); | ||
1518 | } | ||
1519 | |||
1520 | /*====================================================================*/ | ||
1521 | |||
1522 | static void shmem_get_8390_hdr(struct net_device *dev, | ||
1523 | struct e8390_pkt_hdr *hdr, | ||
1524 | int ring_page) | ||
1525 | { | ||
1526 | void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8) | ||
1527 | + (ring_page << 8) | ||
1528 | - (ei_status.rx_start_page << 8); | ||
1529 | |||
1530 | copyin(hdr, xfer_start, sizeof(struct e8390_pkt_hdr)); | ||
1531 | /* Fix for big endian systems */ | ||
1532 | hdr->count = le16_to_cpu(hdr->count); | ||
1533 | } | ||
1534 | |||
1535 | /*====================================================================*/ | ||
1536 | |||
1537 | static void shmem_block_input(struct net_device *dev, int count, | ||
1538 | struct sk_buff *skb, int ring_offset) | ||
1539 | { | ||
1540 | void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8) | ||
1541 | + ring_offset | ||
1542 | - (ei_status.rx_start_page << 8); | ||
1543 | char *buf = skb->data; | ||
1544 | |||
1545 | if (xfer_start + count > (void __iomem *)ei_status.rmem_end) { | ||
1546 | /* We must wrap the input move. */ | ||
1547 | int semi_count = (void __iomem *)ei_status.rmem_end - xfer_start; | ||
1548 | copyin(buf, xfer_start, semi_count); | ||
1549 | buf += semi_count; | ||
1550 | xfer_start = ei_status.mem + (TX_PAGES<<8); | ||
1551 | count -= semi_count; | ||
1552 | } | ||
1553 | copyin(buf, xfer_start, count); | ||
1554 | } | ||
1555 | |||
1556 | /*====================================================================*/ | ||
1557 | |||
1558 | static void shmem_block_output(struct net_device *dev, int count, | ||
1559 | const u_char *buf, const int start_page) | ||
1560 | { | ||
1561 | void __iomem *shmem = ei_status.mem + (start_page << 8); | ||
1562 | shmem -= ei_status.tx_start_page << 8; | ||
1563 | copyout(shmem, buf, count); | ||
1564 | } | ||
1565 | |||
1566 | /*====================================================================*/ | ||
1567 | |||
1568 | static int setup_shmem_window(dev_link_t *link, int start_pg, | ||
1569 | int stop_pg, int cm_offset) | ||
1570 | { | ||
1571 | struct net_device *dev = link->priv; | ||
1572 | pcnet_dev_t *info = PRIV(dev); | ||
1573 | win_req_t req; | ||
1574 | memreq_t mem; | ||
1575 | int i, window_size, offset, last_ret, last_fn; | ||
1576 | |||
1577 | window_size = (stop_pg - start_pg) << 8; | ||
1578 | if (window_size > 32 * 1024) | ||
1579 | window_size = 32 * 1024; | ||
1580 | |||
1581 | /* Make sure it's a power of two. */ | ||
1582 | while ((window_size & (window_size - 1)) != 0) | ||
1583 | window_size += window_size & ~(window_size - 1); | ||
1584 | |||
1585 | /* Allocate a memory window */ | ||
1586 | req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; | ||
1587 | req.Attributes |= WIN_USE_WAIT; | ||
1588 | req.Base = 0; req.Size = window_size; | ||
1589 | req.AccessSpeed = mem_speed; | ||
1590 | CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); | ||
1591 | |||
1592 | mem.CardOffset = (start_pg << 8) + cm_offset; | ||
1593 | offset = mem.CardOffset % window_size; | ||
1594 | mem.CardOffset -= offset; | ||
1595 | mem.Page = 0; | ||
1596 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); | ||
1597 | |||
1598 | /* Try scribbling on the buffer */ | ||
1599 | info->base = ioremap(req.Base, window_size); | ||
1600 | for (i = 0; i < (TX_PAGES<<8); i += 2) | ||
1601 | __raw_writew((i>>1), info->base+offset+i); | ||
1602 | udelay(100); | ||
1603 | for (i = 0; i < (TX_PAGES<<8); i += 2) | ||
1604 | if (__raw_readw(info->base+offset+i) != (i>>1)) break; | ||
1605 | pcnet_reset_8390(dev); | ||
1606 | if (i != (TX_PAGES<<8)) { | ||
1607 | iounmap(info->base); | ||
1608 | pcmcia_release_window(link->win); | ||
1609 | info->base = NULL; link->win = NULL; | ||
1610 | goto failed; | ||
1611 | } | ||
1612 | |||
1613 | ei_status.mem = info->base + offset; | ||
1614 | dev->mem_start = (u_long)ei_status.mem; | ||
1615 | dev->mem_end = ei_status.rmem_end = (u_long)info->base + req.Size; | ||
1616 | |||
1617 | ei_status.tx_start_page = start_pg; | ||
1618 | ei_status.rx_start_page = start_pg + TX_PAGES; | ||
1619 | ei_status.stop_page = start_pg + ((req.Size - offset) >> 8); | ||
1620 | |||
1621 | /* set up block i/o functions */ | ||
1622 | ei_status.get_8390_hdr = &shmem_get_8390_hdr; | ||
1623 | ei_status.block_input = &shmem_block_input; | ||
1624 | ei_status.block_output = &shmem_block_output; | ||
1625 | |||
1626 | info->flags |= USE_SHMEM; | ||
1627 | return 0; | ||
1628 | |||
1629 | cs_failed: | ||
1630 | cs_error(link->handle, last_fn, last_ret); | ||
1631 | failed: | ||
1632 | return 1; | ||
1633 | } | ||
1634 | |||
1635 | /*====================================================================*/ | ||
1636 | |||
1637 | static struct pcmcia_driver pcnet_driver = { | ||
1638 | .drv = { | ||
1639 | .name = "pcnet_cs", | ||
1640 | }, | ||
1641 | .attach = pcnet_attach, | ||
1642 | .detach = pcnet_detach, | ||
1643 | .owner = THIS_MODULE, | ||
1644 | }; | ||
1645 | |||
1646 | static int __init init_pcnet_cs(void) | ||
1647 | { | ||
1648 | return pcmcia_register_driver(&pcnet_driver); | ||
1649 | } | ||
1650 | |||
1651 | static void __exit exit_pcnet_cs(void) | ||
1652 | { | ||
1653 | DEBUG(0, "pcnet_cs: unloading\n"); | ||
1654 | pcmcia_unregister_driver(&pcnet_driver); | ||
1655 | BUG_ON(dev_list != NULL); | ||
1656 | } | ||
1657 | |||
1658 | module_init(init_pcnet_cs); | ||
1659 | module_exit(exit_pcnet_cs); | ||
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c new file mode 100644 index 000000000000..85a152173148 --- /dev/null +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -0,0 +1,2260 @@ | |||
1 | /*====================================================================== | ||
2 | |||
3 | A PCMCIA ethernet driver for SMC91c92-based cards. | ||
4 | |||
5 | This driver supports Megahertz PCMCIA ethernet cards; and | ||
6 | Megahertz, Motorola, Ositech, and Psion Dacom ethernet/modem | ||
7 | multifunction cards. | ||
8 | |||
9 | Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net | ||
10 | |||
11 | smc91c92_cs.c 1.122 2002/10/25 06:26:39 | ||
12 | |||
13 | This driver contains code written by Donald Becker | ||
14 | (becker@scyld.com), Rowan Hughes (x-csrdh@jcu.edu.au), | ||
15 | David Hinds (dahinds@users.sourceforge.net), and Erik Stahlman | ||
16 | (erik@vt.edu). Donald wrote the SMC 91c92 code using parts of | ||
17 | Erik's SMC 91c94 driver. Rowan wrote a similar driver, and I've | ||
18 | incorporated some parts of his driver here. I (Dave) wrote most | ||
19 | of the PCMCIA glue code, and the Ositech support code. Kelly | ||
20 | Stephens (kstephen@holli.com) added support for the Motorola | ||
21 | Mariner, with help from Allen Brost. | ||
22 | |||
23 | This software may be used and distributed according to the terms of | ||
24 | the GNU General Public License, incorporated herein by reference. | ||
25 | |||
26 | ======================================================================*/ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/string.h> | ||
33 | #include <linux/timer.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/crc32.h> | ||
37 | #include <linux/netdevice.h> | ||
38 | #include <linux/etherdevice.h> | ||
39 | #include <linux/skbuff.h> | ||
40 | #include <linux/if_arp.h> | ||
41 | #include <linux/ioport.h> | ||
42 | #include <linux/ethtool.h> | ||
43 | #include <linux/mii.h> | ||
44 | |||
45 | #include <pcmcia/version.h> | ||
46 | #include <pcmcia/cs_types.h> | ||
47 | #include <pcmcia/cs.h> | ||
48 | #include <pcmcia/cistpl.h> | ||
49 | #include <pcmcia/cisreg.h> | ||
50 | #include <pcmcia/ciscode.h> | ||
51 | #include <pcmcia/ds.h> | ||
52 | |||
53 | #include <asm/io.h> | ||
54 | #include <asm/system.h> | ||
55 | #include <asm/uaccess.h> | ||
56 | |||
57 | /* Ositech Seven of Diamonds firmware */ | ||
58 | #include "ositech.h" | ||
59 | |||
60 | /*====================================================================*/ | ||
61 | |||
62 | static char *if_names[] = { "auto", "10baseT", "10base2"}; | ||
63 | |||
64 | /* Module parameters */ | ||
65 | |||
66 | MODULE_DESCRIPTION("SMC 91c92 series PCMCIA ethernet driver"); | ||
67 | MODULE_LICENSE("GPL"); | ||
68 | |||
69 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) | ||
70 | |||
71 | /* | ||
72 | Transceiver/media type. | ||
73 | 0 = auto | ||
74 | 1 = 10baseT (and autoselect if #define AUTOSELECT), | ||
75 | 2 = AUI/10base2, | ||
76 | */ | ||
77 | INT_MODULE_PARM(if_port, 0); | ||
78 | |||
79 | #ifdef PCMCIA_DEBUG | ||
80 | INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); | ||
81 | static const char *version = | ||
82 | "smc91c92_cs.c 0.09 1996/8/4 Donald Becker, becker@scyld.com.\n"; | ||
83 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) | ||
84 | #else | ||
85 | #define DEBUG(n, args...) | ||
86 | #endif | ||
87 | |||
88 | #define DRV_NAME "smc91c92_cs" | ||
89 | #define DRV_VERSION "1.122" | ||
90 | |||
91 | /*====================================================================*/ | ||
92 | |||
93 | /* Operational parameter that usually are not changed. */ | ||
94 | |||
95 | /* Time in jiffies before concluding Tx hung */ | ||
96 | #define TX_TIMEOUT ((400*HZ)/1000) | ||
97 | |||
98 | /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ | ||
99 | #define INTR_WORK 4 | ||
100 | |||
101 | /* Times to check the check the chip before concluding that it doesn't | ||
102 | currently have room for another Tx packet. */ | ||
103 | #define MEMORY_WAIT_TIME 8 | ||
104 | |||
105 | static dev_info_t dev_info = "smc91c92_cs"; | ||
106 | |||
107 | static dev_link_t *dev_list; | ||
108 | |||
109 | struct smc_private { | ||
110 | dev_link_t link; | ||
111 | spinlock_t lock; | ||
112 | u_short manfid; | ||
113 | u_short cardid; | ||
114 | struct net_device_stats stats; | ||
115 | dev_node_t node; | ||
116 | struct sk_buff *saved_skb; | ||
117 | int packets_waiting; | ||
118 | void __iomem *base; | ||
119 | u_short cfg; | ||
120 | struct timer_list media; | ||
121 | int watchdog, tx_err; | ||
122 | u_short media_status; | ||
123 | u_short fast_poll; | ||
124 | u_short link_status; | ||
125 | struct mii_if_info mii_if; | ||
126 | int duplex; | ||
127 | int rx_ovrn; | ||
128 | }; | ||
129 | |||
130 | /* Special definitions for Megahertz multifunction cards */ | ||
131 | #define MEGAHERTZ_ISR 0x0380 | ||
132 | |||
133 | /* Special function registers for Motorola Mariner */ | ||
134 | #define MOT_LAN 0x0000 | ||
135 | #define MOT_UART 0x0020 | ||
136 | #define MOT_EEPROM 0x20 | ||
137 | |||
138 | #define MOT_NORMAL \ | ||
139 | (COR_LEVEL_REQ | COR_FUNC_ENA | COR_ADDR_DECODE | COR_IREQ_ENA) | ||
140 | |||
141 | /* Special function registers for Ositech cards */ | ||
142 | #define OSITECH_AUI_CTL 0x0c | ||
143 | #define OSITECH_PWRDOWN 0x0d | ||
144 | #define OSITECH_RESET 0x0e | ||
145 | #define OSITECH_ISR 0x0f | ||
146 | #define OSITECH_AUI_PWR 0x0c | ||
147 | #define OSITECH_RESET_ISR 0x0e | ||
148 | |||
149 | #define OSI_AUI_PWR 0x40 | ||
150 | #define OSI_LAN_PWRDOWN 0x02 | ||
151 | #define OSI_MODEM_PWRDOWN 0x01 | ||
152 | #define OSI_LAN_RESET 0x02 | ||
153 | #define OSI_MODEM_RESET 0x01 | ||
154 | |||
155 | /* Symbolic constants for the SMC91c9* series chips, from Erik Stahlman. */ | ||
156 | #define BANK_SELECT 14 /* Window select register. */ | ||
157 | #define SMC_SELECT_BANK(x) { outw(x, ioaddr + BANK_SELECT); } | ||
158 | |||
159 | /* Bank 0 registers. */ | ||
160 | #define TCR 0 /* transmit control register */ | ||
161 | #define TCR_CLEAR 0 /* do NOTHING */ | ||
162 | #define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */ | ||
163 | #define TCR_PAD_EN 0x0080 /* pads short packets to 64 bytes */ | ||
164 | #define TCR_MONCSN 0x0400 /* Monitor Carrier. */ | ||
165 | #define TCR_FDUPLX 0x0800 /* Full duplex mode. */ | ||
166 | #define TCR_NORMAL TCR_ENABLE | TCR_PAD_EN | ||
167 | |||
168 | #define EPH 2 /* Ethernet Protocol Handler report. */ | ||
169 | #define EPH_TX_SUC 0x0001 | ||
170 | #define EPH_SNGLCOL 0x0002 | ||
171 | #define EPH_MULCOL 0x0004 | ||
172 | #define EPH_LTX_MULT 0x0008 | ||
173 | #define EPH_16COL 0x0010 | ||
174 | #define EPH_SQET 0x0020 | ||
175 | #define EPH_LTX_BRD 0x0040 | ||
176 | #define EPH_TX_DEFR 0x0080 | ||
177 | #define EPH_LAT_COL 0x0200 | ||
178 | #define EPH_LOST_CAR 0x0400 | ||
179 | #define EPH_EXC_DEF 0x0800 | ||
180 | #define EPH_CTR_ROL 0x1000 | ||
181 | #define EPH_RX_OVRN 0x2000 | ||
182 | #define EPH_LINK_OK 0x4000 | ||
183 | #define EPH_TX_UNRN 0x8000 | ||
184 | #define MEMINFO 8 /* Memory Information Register */ | ||
185 | #define MEMCFG 10 /* Memory Configuration Register */ | ||
186 | |||
187 | /* Bank 1 registers. */ | ||
188 | #define CONFIG 0 | ||
189 | #define CFG_MII_SELECT 0x8000 /* 91C100 only */ | ||
190 | #define CFG_NO_WAIT 0x1000 | ||
191 | #define CFG_FULL_STEP 0x0400 | ||
192 | #define CFG_SET_SQLCH 0x0200 | ||
193 | #define CFG_AUI_SELECT 0x0100 | ||
194 | #define CFG_16BIT 0x0080 | ||
195 | #define CFG_DIS_LINK 0x0040 | ||
196 | #define CFG_STATIC 0x0030 | ||
197 | #define CFG_IRQ_SEL_1 0x0004 | ||
198 | #define CFG_IRQ_SEL_0 0x0002 | ||
199 | #define BASE_ADDR 2 | ||
200 | #define ADDR0 4 | ||
201 | #define GENERAL 10 | ||
202 | #define CONTROL 12 | ||
203 | #define CTL_STORE 0x0001 | ||
204 | #define CTL_RELOAD 0x0002 | ||
205 | #define CTL_EE_SELECT 0x0004 | ||
206 | #define CTL_TE_ENABLE 0x0020 | ||
207 | #define CTL_CR_ENABLE 0x0040 | ||
208 | #define CTL_LE_ENABLE 0x0080 | ||
209 | #define CTL_AUTO_RELEASE 0x0800 | ||
210 | #define CTL_POWERDOWN 0x2000 | ||
211 | |||
212 | /* Bank 2 registers. */ | ||
213 | #define MMU_CMD 0 | ||
214 | #define MC_ALLOC 0x20 /* or with number of 256 byte packets */ | ||
215 | #define MC_RESET 0x40 | ||
216 | #define MC_RELEASE 0x80 /* remove and release the current rx packet */ | ||
217 | #define MC_FREEPKT 0xA0 /* Release packet in PNR register */ | ||
218 | #define MC_ENQUEUE 0xC0 /* Enqueue the packet for transmit */ | ||
219 | #define PNR_ARR 2 | ||
220 | #define FIFO_PORTS 4 | ||
221 | #define FP_RXEMPTY 0x8000 | ||
222 | #define POINTER 6 | ||
223 | #define PTR_AUTO_INC 0x0040 | ||
224 | #define PTR_READ 0x2000 | ||
225 | #define PTR_AUTOINC 0x4000 | ||
226 | #define PTR_RCV 0x8000 | ||
227 | #define DATA_1 8 | ||
228 | #define INTERRUPT 12 | ||
229 | #define IM_RCV_INT 0x1 | ||
230 | #define IM_TX_INT 0x2 | ||
231 | #define IM_TX_EMPTY_INT 0x4 | ||
232 | #define IM_ALLOC_INT 0x8 | ||
233 | #define IM_RX_OVRN_INT 0x10 | ||
234 | #define IM_EPH_INT 0x20 | ||
235 | |||
236 | #define RCR 4 | ||
237 | enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002, | ||
238 | RxEnable = 0x0100, RxStripCRC = 0x0200}; | ||
239 | #define RCR_SOFTRESET 0x8000 /* resets the chip */ | ||
240 | #define RCR_STRIP_CRC 0x200 /* strips CRC */ | ||
241 | #define RCR_ENABLE 0x100 /* IFF this is set, we can receive packets */ | ||
242 | #define RCR_ALMUL 0x4 /* receive all multicast packets */ | ||
243 | #define RCR_PROMISC 0x2 /* enable promiscuous mode */ | ||
244 | |||
245 | /* the normal settings for the RCR register : */ | ||
246 | #define RCR_NORMAL (RCR_STRIP_CRC | RCR_ENABLE) | ||
247 | #define RCR_CLEAR 0x0 /* set it to a base state */ | ||
248 | #define COUNTER 6 | ||
249 | |||
250 | /* BANK 3 -- not the same values as in smc9194! */ | ||
251 | #define MULTICAST0 0 | ||
252 | #define MULTICAST2 2 | ||
253 | #define MULTICAST4 4 | ||
254 | #define MULTICAST6 6 | ||
255 | #define MGMT 8 | ||
256 | #define REVISION 0x0a | ||
257 | |||
258 | /* Transmit status bits. */ | ||
259 | #define TS_SUCCESS 0x0001 | ||
260 | #define TS_16COL 0x0010 | ||
261 | #define TS_LATCOL 0x0200 | ||
262 | #define TS_LOSTCAR 0x0400 | ||
263 | |||
264 | /* Receive status bits. */ | ||
265 | #define RS_ALGNERR 0x8000 | ||
266 | #define RS_BADCRC 0x2000 | ||
267 | #define RS_ODDFRAME 0x1000 | ||
268 | #define RS_TOOLONG 0x0800 | ||
269 | #define RS_TOOSHORT 0x0400 | ||
270 | #define RS_MULTICAST 0x0001 | ||
271 | #define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) | ||
272 | |||
273 | #define set_bits(v, p) outw(inw(p)|(v), (p)) | ||
274 | #define mask_bits(v, p) outw(inw(p)&(v), (p)) | ||
275 | |||
276 | /*====================================================================*/ | ||
277 | |||
278 | static dev_link_t *smc91c92_attach(void); | ||
279 | static void smc91c92_detach(dev_link_t *); | ||
280 | static void smc91c92_config(dev_link_t *link); | ||
281 | static void smc91c92_release(dev_link_t *link); | ||
282 | static int smc91c92_event(event_t event, int priority, | ||
283 | event_callback_args_t *args); | ||
284 | |||
285 | static int smc_open(struct net_device *dev); | ||
286 | static int smc_close(struct net_device *dev); | ||
287 | static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
288 | static void smc_tx_timeout(struct net_device *dev); | ||
289 | static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
290 | static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs); | ||
291 | static void smc_rx(struct net_device *dev); | ||
292 | static struct net_device_stats *smc_get_stats(struct net_device *dev); | ||
293 | static void set_rx_mode(struct net_device *dev); | ||
294 | static int s9k_config(struct net_device *dev, struct ifmap *map); | ||
295 | static void smc_set_xcvr(struct net_device *dev, int if_port); | ||
296 | static void smc_reset(struct net_device *dev); | ||
297 | static void media_check(u_long arg); | ||
298 | static void mdio_sync(kio_addr_t addr); | ||
299 | static int mdio_read(struct net_device *dev, int phy_id, int loc); | ||
300 | static void mdio_write(struct net_device *dev, int phy_id, int loc, int value); | ||
301 | static int smc_link_ok(struct net_device *dev); | ||
302 | static struct ethtool_ops ethtool_ops; | ||
303 | |||
304 | /*====================================================================== | ||
305 | |||
306 | smc91c92_attach() creates an "instance" of the driver, allocating | ||
307 | local data structures for one device. The device is registered | ||
308 | with Card Services. | ||
309 | |||
310 | ======================================================================*/ | ||
311 | |||
312 | static dev_link_t *smc91c92_attach(void) | ||
313 | { | ||
314 | client_reg_t client_reg; | ||
315 | struct smc_private *smc; | ||
316 | dev_link_t *link; | ||
317 | struct net_device *dev; | ||
318 | int ret; | ||
319 | |||
320 | DEBUG(0, "smc91c92_attach()\n"); | ||
321 | |||
322 | /* Create new ethernet device */ | ||
323 | dev = alloc_etherdev(sizeof(struct smc_private)); | ||
324 | if (!dev) | ||
325 | return NULL; | ||
326 | smc = netdev_priv(dev); | ||
327 | link = &smc->link; | ||
328 | link->priv = dev; | ||
329 | |||
330 | spin_lock_init(&smc->lock); | ||
331 | link->io.NumPorts1 = 16; | ||
332 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
333 | link->io.IOAddrLines = 4; | ||
334 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
335 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
336 | link->irq.Handler = &smc_interrupt; | ||
337 | link->irq.Instance = dev; | ||
338 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
339 | link->conf.Vcc = 50; | ||
340 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
341 | |||
342 | /* The SMC91c92-specific entries in the device structure. */ | ||
343 | SET_MODULE_OWNER(dev); | ||
344 | dev->hard_start_xmit = &smc_start_xmit; | ||
345 | dev->get_stats = &smc_get_stats; | ||
346 | dev->set_config = &s9k_config; | ||
347 | dev->set_multicast_list = &set_rx_mode; | ||
348 | dev->open = &smc_open; | ||
349 | dev->stop = &smc_close; | ||
350 | dev->do_ioctl = &smc_ioctl; | ||
351 | SET_ETHTOOL_OPS(dev, ðtool_ops); | ||
352 | #ifdef HAVE_TX_TIMEOUT | ||
353 | dev->tx_timeout = smc_tx_timeout; | ||
354 | dev->watchdog_timeo = TX_TIMEOUT; | ||
355 | #endif | ||
356 | |||
357 | smc->mii_if.dev = dev; | ||
358 | smc->mii_if.mdio_read = mdio_read; | ||
359 | smc->mii_if.mdio_write = mdio_write; | ||
360 | smc->mii_if.phy_id_mask = 0x1f; | ||
361 | smc->mii_if.reg_num_mask = 0x1f; | ||
362 | |||
363 | /* Register with Card Services */ | ||
364 | link->next = dev_list; | ||
365 | dev_list = link; | ||
366 | client_reg.dev_info = &dev_info; | ||
367 | client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
368 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
369 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
370 | client_reg.event_handler = &smc91c92_event; | ||
371 | client_reg.Version = 0x0210; | ||
372 | client_reg.event_callback_args.client_data = link; | ||
373 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
374 | if (ret != 0) { | ||
375 | cs_error(link->handle, RegisterClient, ret); | ||
376 | smc91c92_detach(link); | ||
377 | return NULL; | ||
378 | } | ||
379 | |||
380 | return link; | ||
381 | } /* smc91c92_attach */ | ||
382 | |||
383 | /*====================================================================== | ||
384 | |||
385 | This deletes a driver "instance". The device is de-registered | ||
386 | with Card Services. If it has been released, all local data | ||
387 | structures are freed. Otherwise, the structures will be freed | ||
388 | when the device is released. | ||
389 | |||
390 | ======================================================================*/ | ||
391 | |||
392 | static void smc91c92_detach(dev_link_t *link) | ||
393 | { | ||
394 | struct net_device *dev = link->priv; | ||
395 | dev_link_t **linkp; | ||
396 | |||
397 | DEBUG(0, "smc91c92_detach(0x%p)\n", link); | ||
398 | |||
399 | /* Locate device structure */ | ||
400 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
401 | if (*linkp == link) break; | ||
402 | if (*linkp == NULL) | ||
403 | return; | ||
404 | |||
405 | if (link->dev) | ||
406 | unregister_netdev(dev); | ||
407 | |||
408 | if (link->state & DEV_CONFIG) | ||
409 | smc91c92_release(link); | ||
410 | |||
411 | if (link->handle) | ||
412 | pcmcia_deregister_client(link->handle); | ||
413 | |||
414 | /* Unlink device structure, free bits */ | ||
415 | *linkp = link->next; | ||
416 | free_netdev(dev); | ||
417 | } /* smc91c92_detach */ | ||
418 | |||
419 | /*====================================================================*/ | ||
420 | |||
421 | static int cvt_ascii_address(struct net_device *dev, char *s) | ||
422 | { | ||
423 | int i, j, da, c; | ||
424 | |||
425 | if (strlen(s) != 12) | ||
426 | return -1; | ||
427 | for (i = 0; i < 6; i++) { | ||
428 | da = 0; | ||
429 | for (j = 0; j < 2; j++) { | ||
430 | c = *s++; | ||
431 | da <<= 4; | ||
432 | da += ((c >= '0') && (c <= '9')) ? | ||
433 | (c - '0') : ((c & 0x0f) + 9); | ||
434 | } | ||
435 | dev->dev_addr[i] = da; | ||
436 | } | ||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | /*====================================================================*/ | ||
441 | |||
442 | static int first_tuple(client_handle_t handle, tuple_t *tuple, | ||
443 | cisparse_t *parse) | ||
444 | { | ||
445 | int i; | ||
446 | |||
447 | if ((i = pcmcia_get_first_tuple(handle, tuple)) != CS_SUCCESS || | ||
448 | (i = pcmcia_get_tuple_data(handle, tuple)) != CS_SUCCESS) | ||
449 | return i; | ||
450 | return pcmcia_parse_tuple(handle, tuple, parse); | ||
451 | } | ||
452 | |||
453 | static int next_tuple(client_handle_t handle, tuple_t *tuple, | ||
454 | cisparse_t *parse) | ||
455 | { | ||
456 | int i; | ||
457 | |||
458 | if ((i = pcmcia_get_next_tuple(handle, tuple)) != CS_SUCCESS || | ||
459 | (i = pcmcia_get_tuple_data(handle, tuple)) != CS_SUCCESS) | ||
460 | return i; | ||
461 | return pcmcia_parse_tuple(handle, tuple, parse); | ||
462 | } | ||
463 | |||
464 | /*====================================================================== | ||
465 | |||
466 | Configuration stuff for Megahertz cards | ||
467 | |||
468 | mhz_3288_power() is used to power up a 3288's ethernet chip. | ||
469 | mhz_mfc_config() handles socket setup for multifunction (1144 | ||
470 | and 3288) cards. mhz_setup() gets a card's hardware ethernet | ||
471 | address. | ||
472 | |||
473 | ======================================================================*/ | ||
474 | |||
475 | static int mhz_3288_power(dev_link_t *link) | ||
476 | { | ||
477 | struct net_device *dev = link->priv; | ||
478 | struct smc_private *smc = netdev_priv(dev); | ||
479 | u_char tmp; | ||
480 | |||
481 | /* Read the ISR twice... */ | ||
482 | readb(smc->base+MEGAHERTZ_ISR); | ||
483 | udelay(5); | ||
484 | readb(smc->base+MEGAHERTZ_ISR); | ||
485 | |||
486 | /* Pause 200ms... */ | ||
487 | mdelay(200); | ||
488 | |||
489 | /* Now read and write the COR... */ | ||
490 | tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR); | ||
491 | udelay(5); | ||
492 | writeb(tmp, smc->base + link->conf.ConfigBase + CISREG_COR); | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static int mhz_mfc_config(dev_link_t *link) | ||
498 | { | ||
499 | struct net_device *dev = link->priv; | ||
500 | struct smc_private *smc = netdev_priv(dev); | ||
501 | tuple_t tuple; | ||
502 | cisparse_t parse; | ||
503 | u_char buf[255]; | ||
504 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | ||
505 | win_req_t req; | ||
506 | memreq_t mem; | ||
507 | int i, k; | ||
508 | |||
509 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
510 | link->conf.Status = CCSR_AUDIO_ENA; | ||
511 | link->irq.Attributes = | ||
512 | IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT; | ||
513 | link->io.IOAddrLines = 16; | ||
514 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; | ||
515 | link->io.NumPorts2 = 8; | ||
516 | |||
517 | tuple.Attributes = tuple.TupleOffset = 0; | ||
518 | tuple.TupleData = (cisdata_t *)buf; | ||
519 | tuple.TupleDataMax = sizeof(buf); | ||
520 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
521 | |||
522 | i = first_tuple(link->handle, &tuple, &parse); | ||
523 | /* The Megahertz combo cards have modem-like CIS entries, so | ||
524 | we have to explicitly try a bunch of port combinations. */ | ||
525 | while (i == CS_SUCCESS) { | ||
526 | link->conf.ConfigIndex = cf->index; | ||
527 | link->io.BasePort2 = cf->io.win[0].base; | ||
528 | for (k = 0; k < 0x400; k += 0x10) { | ||
529 | if (k & 0x80) continue; | ||
530 | link->io.BasePort1 = k ^ 0x300; | ||
531 | i = pcmcia_request_io(link->handle, &link->io); | ||
532 | if (i == CS_SUCCESS) break; | ||
533 | } | ||
534 | if (i == CS_SUCCESS) break; | ||
535 | i = next_tuple(link->handle, &tuple, &parse); | ||
536 | } | ||
537 | if (i != CS_SUCCESS) | ||
538 | return i; | ||
539 | dev->base_addr = link->io.BasePort1; | ||
540 | |||
541 | /* Allocate a memory window, for accessing the ISR */ | ||
542 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | ||
543 | req.Base = req.Size = 0; | ||
544 | req.AccessSpeed = 0; | ||
545 | i = pcmcia_request_window(&link->handle, &req, &link->win); | ||
546 | if (i != CS_SUCCESS) | ||
547 | return i; | ||
548 | smc->base = ioremap(req.Base, req.Size); | ||
549 | mem.CardOffset = mem.Page = 0; | ||
550 | if (smc->manfid == MANFID_MOTOROLA) | ||
551 | mem.CardOffset = link->conf.ConfigBase; | ||
552 | i = pcmcia_map_mem_page(link->win, &mem); | ||
553 | |||
554 | if ((i == CS_SUCCESS) | ||
555 | && (smc->manfid == MANFID_MEGAHERTZ) | ||
556 | && (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | ||
557 | mhz_3288_power(link); | ||
558 | |||
559 | return i; | ||
560 | } | ||
561 | |||
562 | static int mhz_setup(dev_link_t *link) | ||
563 | { | ||
564 | client_handle_t handle = link->handle; | ||
565 | struct net_device *dev = link->priv; | ||
566 | tuple_t tuple; | ||
567 | cisparse_t parse; | ||
568 | u_char buf[255], *station_addr; | ||
569 | |||
570 | tuple.Attributes = tuple.TupleOffset = 0; | ||
571 | tuple.TupleData = buf; | ||
572 | tuple.TupleDataMax = sizeof(buf); | ||
573 | |||
574 | /* Read the station address from the CIS. It is stored as the last | ||
575 | (fourth) string in the Version 1 Version/ID tuple. */ | ||
576 | tuple.DesiredTuple = CISTPL_VERS_1; | ||
577 | if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS) | ||
578 | return -1; | ||
579 | /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ | ||
580 | if (next_tuple(handle, &tuple, &parse) != CS_SUCCESS) | ||
581 | first_tuple(handle, &tuple, &parse); | ||
582 | if (parse.version_1.ns > 3) { | ||
583 | station_addr = parse.version_1.str + parse.version_1.ofs[3]; | ||
584 | if (cvt_ascii_address(dev, station_addr) == 0) | ||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | /* Another possibility: for the EM3288, in a special tuple */ | ||
589 | tuple.DesiredTuple = 0x81; | ||
590 | if (pcmcia_get_first_tuple(handle, &tuple) != CS_SUCCESS) | ||
591 | return -1; | ||
592 | if (pcmcia_get_tuple_data(handle, &tuple) != CS_SUCCESS) | ||
593 | return -1; | ||
594 | buf[12] = '\0'; | ||
595 | if (cvt_ascii_address(dev, buf) == 0) | ||
596 | return 0; | ||
597 | |||
598 | return -1; | ||
599 | } | ||
600 | |||
601 | /*====================================================================== | ||
602 | |||
603 | Configuration stuff for the Motorola Mariner | ||
604 | |||
605 | mot_config() writes directly to the Mariner configuration | ||
606 | registers because the CIS is just bogus. | ||
607 | |||
608 | ======================================================================*/ | ||
609 | |||
610 | static void mot_config(dev_link_t *link) | ||
611 | { | ||
612 | struct net_device *dev = link->priv; | ||
613 | struct smc_private *smc = netdev_priv(dev); | ||
614 | kio_addr_t ioaddr = dev->base_addr; | ||
615 | kio_addr_t iouart = link->io.BasePort2; | ||
616 | |||
617 | /* Set UART base address and force map with COR bit 1 */ | ||
618 | writeb(iouart & 0xff, smc->base + MOT_UART + CISREG_IOBASE_0); | ||
619 | writeb((iouart >> 8) & 0xff, smc->base + MOT_UART + CISREG_IOBASE_1); | ||
620 | writeb(MOT_NORMAL, smc->base + MOT_UART + CISREG_COR); | ||
621 | |||
622 | /* Set SMC base address and force map with COR bit 1 */ | ||
623 | writeb(ioaddr & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_0); | ||
624 | writeb((ioaddr >> 8) & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_1); | ||
625 | writeb(MOT_NORMAL, smc->base + MOT_LAN + CISREG_COR); | ||
626 | |||
627 | /* Wait for things to settle down */ | ||
628 | mdelay(100); | ||
629 | } | ||
630 | |||
631 | static int mot_setup(dev_link_t *link) | ||
632 | { | ||
633 | struct net_device *dev = link->priv; | ||
634 | kio_addr_t ioaddr = dev->base_addr; | ||
635 | int i, wait, loop; | ||
636 | u_int addr; | ||
637 | |||
638 | /* Read Ethernet address from Serial EEPROM */ | ||
639 | |||
640 | for (i = 0; i < 3; i++) { | ||
641 | SMC_SELECT_BANK(2); | ||
642 | outw(MOT_EEPROM + i, ioaddr + POINTER); | ||
643 | SMC_SELECT_BANK(1); | ||
644 | outw((CTL_RELOAD | CTL_EE_SELECT), ioaddr + CONTROL); | ||
645 | |||
646 | for (loop = wait = 0; loop < 200; loop++) { | ||
647 | udelay(10); | ||
648 | wait = ((CTL_RELOAD | CTL_STORE) & inw(ioaddr + CONTROL)); | ||
649 | if (wait == 0) break; | ||
650 | } | ||
651 | |||
652 | if (wait) | ||
653 | return -1; | ||
654 | |||
655 | addr = inw(ioaddr + GENERAL); | ||
656 | dev->dev_addr[2*i] = addr & 0xff; | ||
657 | dev->dev_addr[2*i+1] = (addr >> 8) & 0xff; | ||
658 | } | ||
659 | |||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | /*====================================================================*/ | ||
664 | |||
665 | static int smc_config(dev_link_t *link) | ||
666 | { | ||
667 | struct net_device *dev = link->priv; | ||
668 | tuple_t tuple; | ||
669 | cisparse_t parse; | ||
670 | u_char buf[255]; | ||
671 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | ||
672 | int i; | ||
673 | |||
674 | tuple.Attributes = tuple.TupleOffset = 0; | ||
675 | tuple.TupleData = (cisdata_t *)buf; | ||
676 | tuple.TupleDataMax = sizeof(buf); | ||
677 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
678 | |||
679 | link->io.NumPorts1 = 16; | ||
680 | i = first_tuple(link->handle, &tuple, &parse); | ||
681 | while (i != CS_NO_MORE_ITEMS) { | ||
682 | if (i == CS_SUCCESS) { | ||
683 | link->conf.ConfigIndex = cf->index; | ||
684 | link->io.BasePort1 = cf->io.win[0].base; | ||
685 | link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; | ||
686 | i = pcmcia_request_io(link->handle, &link->io); | ||
687 | if (i == CS_SUCCESS) break; | ||
688 | } | ||
689 | i = next_tuple(link->handle, &tuple, &parse); | ||
690 | } | ||
691 | if (i == CS_SUCCESS) | ||
692 | dev->base_addr = link->io.BasePort1; | ||
693 | return i; | ||
694 | } | ||
695 | |||
696 | static int smc_setup(dev_link_t *link) | ||
697 | { | ||
698 | client_handle_t handle = link->handle; | ||
699 | struct net_device *dev = link->priv; | ||
700 | tuple_t tuple; | ||
701 | cisparse_t parse; | ||
702 | cistpl_lan_node_id_t *node_id; | ||
703 | u_char buf[255], *station_addr; | ||
704 | int i; | ||
705 | |||
706 | tuple.Attributes = tuple.TupleOffset = 0; | ||
707 | tuple.TupleData = buf; | ||
708 | tuple.TupleDataMax = sizeof(buf); | ||
709 | |||
710 | /* Check for a LAN function extension tuple */ | ||
711 | tuple.DesiredTuple = CISTPL_FUNCE; | ||
712 | i = first_tuple(handle, &tuple, &parse); | ||
713 | while (i == CS_SUCCESS) { | ||
714 | if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID) | ||
715 | break; | ||
716 | i = next_tuple(handle, &tuple, &parse); | ||
717 | } | ||
718 | if (i == CS_SUCCESS) { | ||
719 | node_id = (cistpl_lan_node_id_t *)parse.funce.data; | ||
720 | if (node_id->nb == 6) { | ||
721 | for (i = 0; i < 6; i++) | ||
722 | dev->dev_addr[i] = node_id->id[i]; | ||
723 | return 0; | ||
724 | } | ||
725 | } | ||
726 | /* Try the third string in the Version 1 Version/ID tuple. */ | ||
727 | tuple.DesiredTuple = CISTPL_VERS_1; | ||
728 | if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS) | ||
729 | return -1; | ||
730 | station_addr = parse.version_1.str + parse.version_1.ofs[2]; | ||
731 | if (cvt_ascii_address(dev, station_addr) == 0) | ||
732 | return 0; | ||
733 | |||
734 | return -1; | ||
735 | } | ||
736 | |||
737 | /*====================================================================*/ | ||
738 | |||
739 | static int osi_config(dev_link_t *link) | ||
740 | { | ||
741 | struct net_device *dev = link->priv; | ||
742 | static kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; | ||
743 | int i, j; | ||
744 | |||
745 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
746 | link->conf.Status = CCSR_AUDIO_ENA; | ||
747 | link->irq.Attributes = | ||
748 | IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT; | ||
749 | link->io.NumPorts1 = 64; | ||
750 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; | ||
751 | link->io.NumPorts2 = 8; | ||
752 | link->io.IOAddrLines = 16; | ||
753 | |||
754 | /* Enable Hard Decode, LAN, Modem */ | ||
755 | link->conf.ConfigIndex = 0x23; | ||
756 | |||
757 | for (i = j = 0; j < 4; j++) { | ||
758 | link->io.BasePort2 = com[j]; | ||
759 | i = pcmcia_request_io(link->handle, &link->io); | ||
760 | if (i == CS_SUCCESS) break; | ||
761 | } | ||
762 | if (i != CS_SUCCESS) { | ||
763 | /* Fallback: turn off hard decode */ | ||
764 | link->conf.ConfigIndex = 0x03; | ||
765 | link->io.NumPorts2 = 0; | ||
766 | i = pcmcia_request_io(link->handle, &link->io); | ||
767 | } | ||
768 | dev->base_addr = link->io.BasePort1 + 0x10; | ||
769 | return i; | ||
770 | } | ||
771 | |||
772 | static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) | ||
773 | { | ||
774 | client_handle_t handle = link->handle; | ||
775 | struct net_device *dev = link->priv; | ||
776 | tuple_t tuple; | ||
777 | u_char buf[255]; | ||
778 | int i; | ||
779 | |||
780 | tuple.Attributes = TUPLE_RETURN_COMMON; | ||
781 | tuple.TupleData = buf; | ||
782 | tuple.TupleDataMax = sizeof(buf); | ||
783 | tuple.TupleOffset = 0; | ||
784 | |||
785 | /* Read the station address from tuple 0x90, subtuple 0x04 */ | ||
786 | tuple.DesiredTuple = 0x90; | ||
787 | i = pcmcia_get_first_tuple(handle, &tuple); | ||
788 | while (i == CS_SUCCESS) { | ||
789 | i = pcmcia_get_tuple_data(handle, &tuple); | ||
790 | if ((i != CS_SUCCESS) || (buf[0] == 0x04)) | ||
791 | break; | ||
792 | i = pcmcia_get_next_tuple(handle, &tuple); | ||
793 | } | ||
794 | if (i != CS_SUCCESS) | ||
795 | return -1; | ||
796 | for (i = 0; i < 6; i++) | ||
797 | dev->dev_addr[i] = buf[i+2]; | ||
798 | |||
799 | if (((manfid == MANFID_OSITECH) && | ||
800 | (cardid == PRODID_OSITECH_SEVEN)) || | ||
801 | ((manfid == MANFID_PSION) && | ||
802 | (cardid == PRODID_PSION_NET100))) { | ||
803 | /* Download the Seven of Diamonds firmware */ | ||
804 | for (i = 0; i < sizeof(__Xilinx7OD); i++) { | ||
805 | outb(__Xilinx7OD[i], link->io.BasePort1+2); | ||
806 | udelay(50); | ||
807 | } | ||
808 | } else if (manfid == MANFID_OSITECH) { | ||
809 | /* Make sure both functions are powered up */ | ||
810 | set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR); | ||
811 | /* Now, turn on the interrupt for both card functions */ | ||
812 | set_bits(0x300, link->io.BasePort1 + OSITECH_RESET_ISR); | ||
813 | DEBUG(2, "AUI/PWR: %4.4x RESET/ISR: %4.4x\n", | ||
814 | inw(link->io.BasePort1 + OSITECH_AUI_PWR), | ||
815 | inw(link->io.BasePort1 + OSITECH_RESET_ISR)); | ||
816 | } | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | /*====================================================================== | ||
822 | |||
823 | This verifies that the chip is some SMC91cXX variant, and returns | ||
824 | the revision code if successful. Otherwise, it returns -ENODEV. | ||
825 | |||
826 | ======================================================================*/ | ||
827 | |||
828 | static int check_sig(dev_link_t *link) | ||
829 | { | ||
830 | struct net_device *dev = link->priv; | ||
831 | kio_addr_t ioaddr = dev->base_addr; | ||
832 | int width; | ||
833 | u_short s; | ||
834 | |||
835 | SMC_SELECT_BANK(1); | ||
836 | if (inw(ioaddr + BANK_SELECT) >> 8 != 0x33) { | ||
837 | /* Try powering up the chip */ | ||
838 | outw(0, ioaddr + CONTROL); | ||
839 | mdelay(55); | ||
840 | } | ||
841 | |||
842 | /* Try setting bus width */ | ||
843 | width = (link->io.Attributes1 == IO_DATA_PATH_WIDTH_AUTO); | ||
844 | s = inb(ioaddr + CONFIG); | ||
845 | if (width) | ||
846 | s |= CFG_16BIT; | ||
847 | else | ||
848 | s &= ~CFG_16BIT; | ||
849 | outb(s, ioaddr + CONFIG); | ||
850 | |||
851 | /* Check Base Address Register to make sure bus width is OK */ | ||
852 | s = inw(ioaddr + BASE_ADDR); | ||
853 | if ((inw(ioaddr + BANK_SELECT) >> 8 == 0x33) && | ||
854 | ((s >> 8) != (s & 0xff))) { | ||
855 | SMC_SELECT_BANK(3); | ||
856 | s = inw(ioaddr + REVISION); | ||
857 | return (s & 0xff); | ||
858 | } | ||
859 | |||
860 | if (width) { | ||
861 | event_callback_args_t args; | ||
862 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); | ||
863 | args.client_data = link; | ||
864 | smc91c92_event(CS_EVENT_RESET_PHYSICAL, 0, &args); | ||
865 | pcmcia_release_io(link->handle, &link->io); | ||
866 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
867 | pcmcia_request_io(link->handle, &link->io); | ||
868 | smc91c92_event(CS_EVENT_CARD_RESET, 0, &args); | ||
869 | return check_sig(link); | ||
870 | } | ||
871 | return -ENODEV; | ||
872 | } | ||
873 | |||
874 | /*====================================================================== | ||
875 | |||
876 | smc91c92_config() is scheduled to run after a CARD_INSERTION event | ||
877 | is received, to configure the PCMCIA socket, and to make the | ||
878 | ethernet device available to the system. | ||
879 | |||
880 | ======================================================================*/ | ||
881 | |||
882 | #define CS_EXIT_TEST(ret, svc, label) \ | ||
883 | if (ret != CS_SUCCESS) { cs_error(link->handle, svc, ret); goto label; } | ||
884 | |||
885 | static void smc91c92_config(dev_link_t *link) | ||
886 | { | ||
887 | client_handle_t handle = link->handle; | ||
888 | struct net_device *dev = link->priv; | ||
889 | struct smc_private *smc = netdev_priv(dev); | ||
890 | tuple_t tuple; | ||
891 | cisparse_t parse; | ||
892 | u_short buf[32]; | ||
893 | char *name; | ||
894 | int i, j, rev; | ||
895 | kio_addr_t ioaddr; | ||
896 | u_long mir; | ||
897 | |||
898 | DEBUG(0, "smc91c92_config(0x%p)\n", link); | ||
899 | |||
900 | tuple.Attributes = tuple.TupleOffset = 0; | ||
901 | tuple.TupleData = (cisdata_t *)buf; | ||
902 | tuple.TupleDataMax = sizeof(buf); | ||
903 | |||
904 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
905 | i = first_tuple(handle, &tuple, &parse); | ||
906 | CS_EXIT_TEST(i, ParseTuple, config_failed); | ||
907 | link->conf.ConfigBase = parse.config.base; | ||
908 | link->conf.Present = parse.config.rmask[0]; | ||
909 | |||
910 | tuple.DesiredTuple = CISTPL_MANFID; | ||
911 | tuple.Attributes = TUPLE_RETURN_COMMON; | ||
912 | if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { | ||
913 | smc->manfid = parse.manfid.manf; | ||
914 | smc->cardid = parse.manfid.card; | ||
915 | } | ||
916 | |||
917 | /* Configure card */ | ||
918 | link->state |= DEV_CONFIG; | ||
919 | |||
920 | if ((smc->manfid == MANFID_OSITECH) && | ||
921 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | ||
922 | i = osi_config(link); | ||
923 | } else if ((smc->manfid == MANFID_MOTOROLA) || | ||
924 | ((smc->manfid == MANFID_MEGAHERTZ) && | ||
925 | ((smc->cardid == PRODID_MEGAHERTZ_VARIOUS) || | ||
926 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)))) { | ||
927 | i = mhz_mfc_config(link); | ||
928 | } else { | ||
929 | i = smc_config(link); | ||
930 | } | ||
931 | CS_EXIT_TEST(i, RequestIO, config_failed); | ||
932 | |||
933 | i = pcmcia_request_irq(link->handle, &link->irq); | ||
934 | CS_EXIT_TEST(i, RequestIRQ, config_failed); | ||
935 | i = pcmcia_request_configuration(link->handle, &link->conf); | ||
936 | CS_EXIT_TEST(i, RequestConfiguration, config_failed); | ||
937 | |||
938 | if (smc->manfid == MANFID_MOTOROLA) | ||
939 | mot_config(link); | ||
940 | |||
941 | dev->irq = link->irq.AssignedIRQ; | ||
942 | |||
943 | if ((if_port >= 0) && (if_port <= 2)) | ||
944 | dev->if_port = if_port; | ||
945 | else | ||
946 | printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n"); | ||
947 | |||
948 | switch (smc->manfid) { | ||
949 | case MANFID_OSITECH: | ||
950 | case MANFID_PSION: | ||
951 | i = osi_setup(link, smc->manfid, smc->cardid); break; | ||
952 | case MANFID_SMC: | ||
953 | case MANFID_NEW_MEDIA: | ||
954 | i = smc_setup(link); break; | ||
955 | case 0x128: /* For broken Megahertz cards */ | ||
956 | case MANFID_MEGAHERTZ: | ||
957 | i = mhz_setup(link); break; | ||
958 | case MANFID_MOTOROLA: | ||
959 | default: /* get the hw address from EEPROM */ | ||
960 | i = mot_setup(link); break; | ||
961 | } | ||
962 | |||
963 | if (i != 0) { | ||
964 | printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n"); | ||
965 | goto config_undo; | ||
966 | } | ||
967 | |||
968 | smc->duplex = 0; | ||
969 | smc->rx_ovrn = 0; | ||
970 | |||
971 | rev = check_sig(link); | ||
972 | name = "???"; | ||
973 | if (rev > 0) | ||
974 | switch (rev >> 4) { | ||
975 | case 3: name = "92"; break; | ||
976 | case 4: name = ((rev & 15) >= 6) ? "96" : "94"; break; | ||
977 | case 5: name = "95"; break; | ||
978 | case 7: name = "100"; break; | ||
979 | case 8: name = "100-FD"; break; | ||
980 | case 9: name = "110"; break; | ||
981 | } | ||
982 | |||
983 | ioaddr = dev->base_addr; | ||
984 | if (rev > 0) { | ||
985 | u_long mcr; | ||
986 | SMC_SELECT_BANK(0); | ||
987 | mir = inw(ioaddr + MEMINFO) & 0xff; | ||
988 | if (mir == 0xff) mir++; | ||
989 | /* Get scale factor for memory size */ | ||
990 | mcr = ((rev >> 4) > 3) ? inw(ioaddr + MEMCFG) : 0x0200; | ||
991 | mir *= 128 * (1<<((mcr >> 9) & 7)); | ||
992 | SMC_SELECT_BANK(1); | ||
993 | smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT; | ||
994 | smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC; | ||
995 | if (smc->manfid == MANFID_OSITECH) | ||
996 | smc->cfg |= CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0; | ||
997 | if ((rev >> 4) >= 7) | ||
998 | smc->cfg |= CFG_MII_SELECT; | ||
999 | } else | ||
1000 | mir = 0; | ||
1001 | |||
1002 | if (smc->cfg & CFG_MII_SELECT) { | ||
1003 | SMC_SELECT_BANK(3); | ||
1004 | |||
1005 | for (i = 0; i < 32; i++) { | ||
1006 | j = mdio_read(dev, i, 1); | ||
1007 | if ((j != 0) && (j != 0xffff)) break; | ||
1008 | } | ||
1009 | smc->mii_if.phy_id = (i < 32) ? i : -1; | ||
1010 | |||
1011 | SMC_SELECT_BANK(0); | ||
1012 | } | ||
1013 | |||
1014 | link->dev = &smc->node; | ||
1015 | link->state &= ~DEV_CONFIG_PENDING; | ||
1016 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
1017 | |||
1018 | if (register_netdev(dev) != 0) { | ||
1019 | printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n"); | ||
1020 | link->dev = NULL; | ||
1021 | goto config_undo; | ||
1022 | } | ||
1023 | |||
1024 | strcpy(smc->node.dev_name, dev->name); | ||
1025 | |||
1026 | printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, " | ||
1027 | "hw_addr ", dev->name, name, (rev & 0x0f), dev->base_addr, | ||
1028 | dev->irq); | ||
1029 | for (i = 0; i < 6; i++) | ||
1030 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); | ||
1031 | |||
1032 | if (rev > 0) { | ||
1033 | if (mir & 0x3ff) | ||
1034 | printk(KERN_INFO " %lu byte", mir); | ||
1035 | else | ||
1036 | printk(KERN_INFO " %lu kb", mir>>10); | ||
1037 | printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ? | ||
1038 | "MII" : if_names[dev->if_port]); | ||
1039 | } | ||
1040 | |||
1041 | if (smc->cfg & CFG_MII_SELECT) { | ||
1042 | if (smc->mii_if.phy_id != -1) { | ||
1043 | DEBUG(0, " MII transceiver at index %d, status %x.\n", | ||
1044 | smc->mii_if.phy_id, j); | ||
1045 | } else { | ||
1046 | printk(KERN_NOTICE " No MII transceivers found!\n"); | ||
1047 | } | ||
1048 | } | ||
1049 | |||
1050 | return; | ||
1051 | |||
1052 | config_undo: | ||
1053 | unregister_netdev(dev); | ||
1054 | config_failed: /* CS_EXIT_TEST() calls jump to here... */ | ||
1055 | smc91c92_release(link); | ||
1056 | link->state &= ~DEV_CONFIG_PENDING; | ||
1057 | |||
1058 | } /* smc91c92_config */ | ||
1059 | |||
1060 | /*====================================================================== | ||
1061 | |||
1062 | After a card is removed, smc91c92_release() will unregister the net | ||
1063 | device, and release the PCMCIA configuration. If the device is | ||
1064 | still open, this will be postponed until it is closed. | ||
1065 | |||
1066 | ======================================================================*/ | ||
1067 | |||
1068 | static void smc91c92_release(dev_link_t *link) | ||
1069 | { | ||
1070 | |||
1071 | DEBUG(0, "smc91c92_release(0x%p)\n", link); | ||
1072 | |||
1073 | pcmcia_release_configuration(link->handle); | ||
1074 | pcmcia_release_io(link->handle, &link->io); | ||
1075 | pcmcia_release_irq(link->handle, &link->irq); | ||
1076 | if (link->win) { | ||
1077 | struct net_device *dev = link->priv; | ||
1078 | struct smc_private *smc = netdev_priv(dev); | ||
1079 | iounmap(smc->base); | ||
1080 | pcmcia_release_window(link->win); | ||
1081 | } | ||
1082 | |||
1083 | link->state &= ~DEV_CONFIG; | ||
1084 | } | ||
1085 | |||
1086 | /*====================================================================== | ||
1087 | |||
1088 | The card status event handler. Mostly, this schedules other | ||
1089 | stuff to run after an event is received. A CARD_REMOVAL event | ||
1090 | also sets some flags to discourage the net drivers from trying | ||
1091 | to talk to the card any more. | ||
1092 | |||
1093 | ======================================================================*/ | ||
1094 | |||
1095 | static int smc91c92_event(event_t event, int priority, | ||
1096 | event_callback_args_t *args) | ||
1097 | { | ||
1098 | dev_link_t *link = args->client_data; | ||
1099 | struct net_device *dev = link->priv; | ||
1100 | struct smc_private *smc = netdev_priv(dev); | ||
1101 | int i; | ||
1102 | |||
1103 | DEBUG(1, "smc91c92_event(0x%06x)\n", event); | ||
1104 | |||
1105 | switch (event) { | ||
1106 | case CS_EVENT_CARD_REMOVAL: | ||
1107 | link->state &= ~DEV_PRESENT; | ||
1108 | if (link->state & DEV_CONFIG) | ||
1109 | netif_device_detach(dev); | ||
1110 | break; | ||
1111 | case CS_EVENT_CARD_INSERTION: | ||
1112 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
1113 | smc91c92_config(link); | ||
1114 | break; | ||
1115 | case CS_EVENT_PM_SUSPEND: | ||
1116 | link->state |= DEV_SUSPEND; | ||
1117 | /* Fall through... */ | ||
1118 | case CS_EVENT_RESET_PHYSICAL: | ||
1119 | if (link->state & DEV_CONFIG) { | ||
1120 | if (link->open) | ||
1121 | netif_device_detach(dev); | ||
1122 | pcmcia_release_configuration(link->handle); | ||
1123 | } | ||
1124 | break; | ||
1125 | case CS_EVENT_PM_RESUME: | ||
1126 | link->state &= ~DEV_SUSPEND; | ||
1127 | /* Fall through... */ | ||
1128 | case CS_EVENT_CARD_RESET: | ||
1129 | if (link->state & DEV_CONFIG) { | ||
1130 | if ((smc->manfid == MANFID_MEGAHERTZ) && | ||
1131 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | ||
1132 | mhz_3288_power(link); | ||
1133 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1134 | if (smc->manfid == MANFID_MOTOROLA) | ||
1135 | mot_config(link); | ||
1136 | if ((smc->manfid == MANFID_OSITECH) && | ||
1137 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | ||
1138 | /* Power up the card and enable interrupts */ | ||
1139 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); | ||
1140 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); | ||
1141 | } | ||
1142 | if (((smc->manfid == MANFID_OSITECH) && | ||
1143 | (smc->cardid == PRODID_OSITECH_SEVEN)) || | ||
1144 | ((smc->manfid == MANFID_PSION) && | ||
1145 | (smc->cardid == PRODID_PSION_NET100))) { | ||
1146 | /* Download the Seven of Diamonds firmware */ | ||
1147 | for (i = 0; i < sizeof(__Xilinx7OD); i++) { | ||
1148 | outb(__Xilinx7OD[i], link->io.BasePort1+2); | ||
1149 | udelay(50); | ||
1150 | } | ||
1151 | } | ||
1152 | if (link->open) { | ||
1153 | smc_reset(dev); | ||
1154 | netif_device_attach(dev); | ||
1155 | } | ||
1156 | } | ||
1157 | break; | ||
1158 | } | ||
1159 | return 0; | ||
1160 | } /* smc91c92_event */ | ||
1161 | |||
1162 | /*====================================================================== | ||
1163 | |||
1164 | MII interface support for SMC91cXX based cards | ||
1165 | ======================================================================*/ | ||
1166 | |||
1167 | #define MDIO_SHIFT_CLK 0x04 | ||
1168 | #define MDIO_DATA_OUT 0x01 | ||
1169 | #define MDIO_DIR_WRITE 0x08 | ||
1170 | #define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE) | ||
1171 | #define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT) | ||
1172 | #define MDIO_DATA_READ 0x02 | ||
1173 | |||
1174 | static void mdio_sync(kio_addr_t addr) | ||
1175 | { | ||
1176 | int bits; | ||
1177 | for (bits = 0; bits < 32; bits++) { | ||
1178 | outb(MDIO_DATA_WRITE1, addr); | ||
1179 | outb(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr); | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | static int mdio_read(struct net_device *dev, int phy_id, int loc) | ||
1184 | { | ||
1185 | kio_addr_t addr = dev->base_addr + MGMT; | ||
1186 | u_int cmd = (0x06<<10)|(phy_id<<5)|loc; | ||
1187 | int i, retval = 0; | ||
1188 | |||
1189 | mdio_sync(addr); | ||
1190 | for (i = 13; i >= 0; i--) { | ||
1191 | int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; | ||
1192 | outb(dat, addr); | ||
1193 | outb(dat | MDIO_SHIFT_CLK, addr); | ||
1194 | } | ||
1195 | for (i = 19; i > 0; i--) { | ||
1196 | outb(0, addr); | ||
1197 | retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0); | ||
1198 | outb(MDIO_SHIFT_CLK, addr); | ||
1199 | } | ||
1200 | return (retval>>1) & 0xffff; | ||
1201 | } | ||
1202 | |||
1203 | static void mdio_write(struct net_device *dev, int phy_id, int loc, int value) | ||
1204 | { | ||
1205 | kio_addr_t addr = dev->base_addr + MGMT; | ||
1206 | u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value; | ||
1207 | int i; | ||
1208 | |||
1209 | mdio_sync(addr); | ||
1210 | for (i = 31; i >= 0; i--) { | ||
1211 | int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; | ||
1212 | outb(dat, addr); | ||
1213 | outb(dat | MDIO_SHIFT_CLK, addr); | ||
1214 | } | ||
1215 | for (i = 1; i >= 0; i--) { | ||
1216 | outb(0, addr); | ||
1217 | outb(MDIO_SHIFT_CLK, addr); | ||
1218 | } | ||
1219 | } | ||
1220 | |||
1221 | /*====================================================================== | ||
1222 | |||
1223 | The driver core code, most of which should be common with a | ||
1224 | non-PCMCIA implementation. | ||
1225 | |||
1226 | ======================================================================*/ | ||
1227 | |||
1228 | #ifdef PCMCIA_DEBUG | ||
1229 | static void smc_dump(struct net_device *dev) | ||
1230 | { | ||
1231 | kio_addr_t ioaddr = dev->base_addr; | ||
1232 | u_short i, w, save; | ||
1233 | save = inw(ioaddr + BANK_SELECT); | ||
1234 | for (w = 0; w < 4; w++) { | ||
1235 | SMC_SELECT_BANK(w); | ||
1236 | printk(KERN_DEBUG "bank %d: ", w); | ||
1237 | for (i = 0; i < 14; i += 2) | ||
1238 | printk(" %04x", inw(ioaddr + i)); | ||
1239 | printk("\n"); | ||
1240 | } | ||
1241 | outw(save, ioaddr + BANK_SELECT); | ||
1242 | } | ||
1243 | #endif | ||
1244 | |||
1245 | static int smc_open(struct net_device *dev) | ||
1246 | { | ||
1247 | struct smc_private *smc = netdev_priv(dev); | ||
1248 | dev_link_t *link = &smc->link; | ||
1249 | |||
1250 | #ifdef PCMCIA_DEBUG | ||
1251 | DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n", | ||
1252 | dev->name, dev, inw(dev->base_addr + BANK_SELECT)); | ||
1253 | if (pc_debug > 1) smc_dump(dev); | ||
1254 | #endif | ||
1255 | |||
1256 | /* Check that the PCMCIA card is still here. */ | ||
1257 | if (!DEV_OK(link)) | ||
1258 | return -ENODEV; | ||
1259 | /* Physical device present signature. */ | ||
1260 | if (check_sig(link) < 0) { | ||
1261 | printk("smc91c92_cs: Yikes! Bad chip signature!\n"); | ||
1262 | return -ENODEV; | ||
1263 | } | ||
1264 | link->open++; | ||
1265 | |||
1266 | netif_start_queue(dev); | ||
1267 | smc->saved_skb = NULL; | ||
1268 | smc->packets_waiting = 0; | ||
1269 | |||
1270 | smc_reset(dev); | ||
1271 | init_timer(&smc->media); | ||
1272 | smc->media.function = &media_check; | ||
1273 | smc->media.data = (u_long) dev; | ||
1274 | smc->media.expires = jiffies + HZ; | ||
1275 | add_timer(&smc->media); | ||
1276 | |||
1277 | return 0; | ||
1278 | } /* smc_open */ | ||
1279 | |||
1280 | /*====================================================================*/ | ||
1281 | |||
1282 | static int smc_close(struct net_device *dev) | ||
1283 | { | ||
1284 | struct smc_private *smc = netdev_priv(dev); | ||
1285 | dev_link_t *link = &smc->link; | ||
1286 | kio_addr_t ioaddr = dev->base_addr; | ||
1287 | |||
1288 | DEBUG(0, "%s: smc_close(), status %4.4x.\n", | ||
1289 | dev->name, inw(ioaddr + BANK_SELECT)); | ||
1290 | |||
1291 | netif_stop_queue(dev); | ||
1292 | |||
1293 | /* Shut off all interrupts, and turn off the Tx and Rx sections. | ||
1294 | Don't bother to check for chip present. */ | ||
1295 | SMC_SELECT_BANK(2); /* Nominally paranoia, but do no assume... */ | ||
1296 | outw(0, ioaddr + INTERRUPT); | ||
1297 | SMC_SELECT_BANK(0); | ||
1298 | mask_bits(0xff00, ioaddr + RCR); | ||
1299 | mask_bits(0xff00, ioaddr + TCR); | ||
1300 | |||
1301 | /* Put the chip into power-down mode. */ | ||
1302 | SMC_SELECT_BANK(1); | ||
1303 | outw(CTL_POWERDOWN, ioaddr + CONTROL ); | ||
1304 | |||
1305 | link->open--; | ||
1306 | del_timer_sync(&smc->media); | ||
1307 | |||
1308 | return 0; | ||
1309 | } /* smc_close */ | ||
1310 | |||
1311 | /*====================================================================== | ||
1312 | |||
1313 | Transfer a packet to the hardware and trigger the packet send. | ||
1314 | This may be called at either from either the Tx queue code | ||
1315 | or the interrupt handler. | ||
1316 | |||
1317 | ======================================================================*/ | ||
1318 | |||
1319 | static void smc_hardware_send_packet(struct net_device * dev) | ||
1320 | { | ||
1321 | struct smc_private *smc = netdev_priv(dev); | ||
1322 | struct sk_buff *skb = smc->saved_skb; | ||
1323 | kio_addr_t ioaddr = dev->base_addr; | ||
1324 | u_char packet_no; | ||
1325 | |||
1326 | if (!skb) { | ||
1327 | printk(KERN_ERR "%s: In XMIT with no packet to send.\n", dev->name); | ||
1328 | return; | ||
1329 | } | ||
1330 | |||
1331 | /* There should be a packet slot waiting. */ | ||
1332 | packet_no = inw(ioaddr + PNR_ARR) >> 8; | ||
1333 | if (packet_no & 0x80) { | ||
1334 | /* If not, there is a hardware problem! Likely an ejected card. */ | ||
1335 | printk(KERN_WARNING "%s: 91c92 hardware Tx buffer allocation" | ||
1336 | " failed, status %#2.2x.\n", dev->name, packet_no); | ||
1337 | dev_kfree_skb_irq(skb); | ||
1338 | smc->saved_skb = NULL; | ||
1339 | netif_start_queue(dev); | ||
1340 | return; | ||
1341 | } | ||
1342 | |||
1343 | smc->stats.tx_bytes += skb->len; | ||
1344 | /* The card should use the just-allocated buffer. */ | ||
1345 | outw(packet_no, ioaddr + PNR_ARR); | ||
1346 | /* point to the beginning of the packet */ | ||
1347 | outw(PTR_AUTOINC , ioaddr + POINTER); | ||
1348 | |||
1349 | /* Send the packet length (+6 for status, length and ctl byte) | ||
1350 | and the status word (set to zeros). */ | ||
1351 | { | ||
1352 | u_char *buf = skb->data; | ||
1353 | u_int length = skb->len; /* The chip will pad to ethernet min. */ | ||
1354 | |||
1355 | DEBUG(2, "%s: Trying to xmit packet of length %d.\n", | ||
1356 | dev->name, length); | ||
1357 | |||
1358 | /* send the packet length: +6 for status word, length, and ctl */ | ||
1359 | outw(0, ioaddr + DATA_1); | ||
1360 | outw(length + 6, ioaddr + DATA_1); | ||
1361 | outsw(ioaddr + DATA_1, buf, length >> 1); | ||
1362 | |||
1363 | /* The odd last byte, if there is one, goes in the control word. */ | ||
1364 | outw((length & 1) ? 0x2000 | buf[length-1] : 0, ioaddr + DATA_1); | ||
1365 | } | ||
1366 | |||
1367 | /* Enable the Tx interrupts, both Tx (TxErr) and TxEmpty. */ | ||
1368 | outw(((IM_TX_INT|IM_TX_EMPTY_INT)<<8) | | ||
1369 | (inw(ioaddr + INTERRUPT) & 0xff00), | ||
1370 | ioaddr + INTERRUPT); | ||
1371 | |||
1372 | /* The chip does the rest of the work. */ | ||
1373 | outw(MC_ENQUEUE , ioaddr + MMU_CMD); | ||
1374 | |||
1375 | smc->saved_skb = NULL; | ||
1376 | dev_kfree_skb_irq(skb); | ||
1377 | dev->trans_start = jiffies; | ||
1378 | netif_start_queue(dev); | ||
1379 | return; | ||
1380 | } | ||
1381 | |||
1382 | /*====================================================================*/ | ||
1383 | |||
1384 | static void smc_tx_timeout(struct net_device *dev) | ||
1385 | { | ||
1386 | struct smc_private *smc = netdev_priv(dev); | ||
1387 | kio_addr_t ioaddr = dev->base_addr; | ||
1388 | |||
1389 | printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, " | ||
1390 | "Tx_status %2.2x status %4.4x.\n", | ||
1391 | dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2)); | ||
1392 | smc->stats.tx_errors++; | ||
1393 | smc_reset(dev); | ||
1394 | dev->trans_start = jiffies; | ||
1395 | smc->saved_skb = NULL; | ||
1396 | netif_wake_queue(dev); | ||
1397 | } | ||
1398 | |||
1399 | static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
1400 | { | ||
1401 | struct smc_private *smc = netdev_priv(dev); | ||
1402 | kio_addr_t ioaddr = dev->base_addr; | ||
1403 | u_short num_pages; | ||
1404 | short time_out, ir; | ||
1405 | |||
1406 | netif_stop_queue(dev); | ||
1407 | |||
1408 | DEBUG(2, "%s: smc_start_xmit(length = %d) called," | ||
1409 | " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2)); | ||
1410 | |||
1411 | if (smc->saved_skb) { | ||
1412 | /* THIS SHOULD NEVER HAPPEN. */ | ||
1413 | smc->stats.tx_aborted_errors++; | ||
1414 | printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n", | ||
1415 | dev->name); | ||
1416 | return 1; | ||
1417 | } | ||
1418 | smc->saved_skb = skb; | ||
1419 | |||
1420 | num_pages = skb->len >> 8; | ||
1421 | |||
1422 | if (num_pages > 7) { | ||
1423 | printk(KERN_ERR "%s: Far too big packet error.\n", dev->name); | ||
1424 | dev_kfree_skb (skb); | ||
1425 | smc->saved_skb = NULL; | ||
1426 | smc->stats.tx_dropped++; | ||
1427 | return 0; /* Do not re-queue this packet. */ | ||
1428 | } | ||
1429 | /* A packet is now waiting. */ | ||
1430 | smc->packets_waiting++; | ||
1431 | |||
1432 | SMC_SELECT_BANK(2); /* Paranoia, we should always be in window 2 */ | ||
1433 | |||
1434 | /* need MC_RESET to keep the memory consistent. errata? */ | ||
1435 | if (smc->rx_ovrn) { | ||
1436 | outw(MC_RESET, ioaddr + MMU_CMD); | ||
1437 | smc->rx_ovrn = 0; | ||
1438 | } | ||
1439 | |||
1440 | /* Allocate the memory; send the packet now if we win. */ | ||
1441 | outw(MC_ALLOC | num_pages, ioaddr + MMU_CMD); | ||
1442 | for (time_out = MEMORY_WAIT_TIME; time_out >= 0; time_out--) { | ||
1443 | ir = inw(ioaddr+INTERRUPT); | ||
1444 | if (ir & IM_ALLOC_INT) { | ||
1445 | /* Acknowledge the interrupt, send the packet. */ | ||
1446 | outw((ir&0xff00) | IM_ALLOC_INT, ioaddr + INTERRUPT); | ||
1447 | smc_hardware_send_packet(dev); /* Send the packet now.. */ | ||
1448 | return 0; | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1452 | /* Otherwise defer until the Tx-space-allocated interrupt. */ | ||
1453 | DEBUG(2, "%s: memory allocation deferred.\n", dev->name); | ||
1454 | outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT); | ||
1455 | |||
1456 | return 0; | ||
1457 | } | ||
1458 | |||
1459 | /*====================================================================== | ||
1460 | |||
1461 | Handle a Tx anomolous event. Entered while in Window 2. | ||
1462 | |||
1463 | ======================================================================*/ | ||
1464 | |||
1465 | static void smc_tx_err(struct net_device * dev) | ||
1466 | { | ||
1467 | struct smc_private *smc = netdev_priv(dev); | ||
1468 | kio_addr_t ioaddr = dev->base_addr; | ||
1469 | int saved_packet = inw(ioaddr + PNR_ARR) & 0xff; | ||
1470 | int packet_no = inw(ioaddr + FIFO_PORTS) & 0x7f; | ||
1471 | int tx_status; | ||
1472 | |||
1473 | /* select this as the packet to read from */ | ||
1474 | outw(packet_no, ioaddr + PNR_ARR); | ||
1475 | |||
1476 | /* read the first word from this packet */ | ||
1477 | outw(PTR_AUTOINC | PTR_READ | 0, ioaddr + POINTER); | ||
1478 | |||
1479 | tx_status = inw(ioaddr + DATA_1); | ||
1480 | |||
1481 | smc->stats.tx_errors++; | ||
1482 | if (tx_status & TS_LOSTCAR) smc->stats.tx_carrier_errors++; | ||
1483 | if (tx_status & TS_LATCOL) smc->stats.tx_window_errors++; | ||
1484 | if (tx_status & TS_16COL) { | ||
1485 | smc->stats.tx_aborted_errors++; | ||
1486 | smc->tx_err++; | ||
1487 | } | ||
1488 | |||
1489 | if (tx_status & TS_SUCCESS) { | ||
1490 | printk(KERN_NOTICE "%s: Successful packet caused error " | ||
1491 | "interrupt?\n", dev->name); | ||
1492 | } | ||
1493 | /* re-enable transmit */ | ||
1494 | SMC_SELECT_BANK(0); | ||
1495 | outw(inw(ioaddr + TCR) | TCR_ENABLE | smc->duplex, ioaddr + TCR); | ||
1496 | SMC_SELECT_BANK(2); | ||
1497 | |||
1498 | outw(MC_FREEPKT, ioaddr + MMU_CMD); /* Free the packet memory. */ | ||
1499 | |||
1500 | /* one less packet waiting for me */ | ||
1501 | smc->packets_waiting--; | ||
1502 | |||
1503 | outw(saved_packet, ioaddr + PNR_ARR); | ||
1504 | return; | ||
1505 | } | ||
1506 | |||
1507 | /*====================================================================*/ | ||
1508 | |||
1509 | static void smc_eph_irq(struct net_device *dev) | ||
1510 | { | ||
1511 | struct smc_private *smc = netdev_priv(dev); | ||
1512 | kio_addr_t ioaddr = dev->base_addr; | ||
1513 | u_short card_stats, ephs; | ||
1514 | |||
1515 | SMC_SELECT_BANK(0); | ||
1516 | ephs = inw(ioaddr + EPH); | ||
1517 | DEBUG(2, "%s: Ethernet protocol handler interrupt, status" | ||
1518 | " %4.4x.\n", dev->name, ephs); | ||
1519 | /* Could be a counter roll-over warning: update stats. */ | ||
1520 | card_stats = inw(ioaddr + COUNTER); | ||
1521 | /* single collisions */ | ||
1522 | smc->stats.collisions += card_stats & 0xF; | ||
1523 | card_stats >>= 4; | ||
1524 | /* multiple collisions */ | ||
1525 | smc->stats.collisions += card_stats & 0xF; | ||
1526 | #if 0 /* These are for when linux supports these statistics */ | ||
1527 | card_stats >>= 4; /* deferred */ | ||
1528 | card_stats >>= 4; /* excess deferred */ | ||
1529 | #endif | ||
1530 | /* If we had a transmit error we must re-enable the transmitter. */ | ||
1531 | outw(inw(ioaddr + TCR) | TCR_ENABLE | smc->duplex, ioaddr + TCR); | ||
1532 | |||
1533 | /* Clear a link error interrupt. */ | ||
1534 | SMC_SELECT_BANK(1); | ||
1535 | outw(CTL_AUTO_RELEASE | 0x0000, ioaddr + CONTROL); | ||
1536 | outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE, | ||
1537 | ioaddr + CONTROL); | ||
1538 | SMC_SELECT_BANK(2); | ||
1539 | } | ||
1540 | |||
1541 | /*====================================================================*/ | ||
1542 | |||
1543 | static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
1544 | { | ||
1545 | struct net_device *dev = dev_id; | ||
1546 | struct smc_private *smc = netdev_priv(dev); | ||
1547 | kio_addr_t ioaddr; | ||
1548 | u_short saved_bank, saved_pointer, mask, status; | ||
1549 | unsigned int handled = 1; | ||
1550 | char bogus_cnt = INTR_WORK; /* Work we are willing to do. */ | ||
1551 | |||
1552 | if (!netif_device_present(dev)) | ||
1553 | return IRQ_NONE; | ||
1554 | |||
1555 | ioaddr = dev->base_addr; | ||
1556 | |||
1557 | DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name, | ||
1558 | irq, ioaddr); | ||
1559 | |||
1560 | smc->watchdog = 0; | ||
1561 | saved_bank = inw(ioaddr + BANK_SELECT); | ||
1562 | if ((saved_bank & 0xff00) != 0x3300) { | ||
1563 | /* The device does not exist -- the card could be off-line, or | ||
1564 | maybe it has been ejected. */ | ||
1565 | DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent" | ||
1566 | "/ejected device.\n", dev->name, irq); | ||
1567 | handled = 0; | ||
1568 | goto irq_done; | ||
1569 | } | ||
1570 | |||
1571 | SMC_SELECT_BANK(2); | ||
1572 | saved_pointer = inw(ioaddr + POINTER); | ||
1573 | mask = inw(ioaddr + INTERRUPT) >> 8; | ||
1574 | /* clear all interrupts */ | ||
1575 | outw(0, ioaddr + INTERRUPT); | ||
1576 | |||
1577 | do { /* read the status flag, and mask it */ | ||
1578 | status = inw(ioaddr + INTERRUPT) & 0xff; | ||
1579 | DEBUG(3, "%s: Status is %#2.2x (mask %#2.2x).\n", dev->name, | ||
1580 | status, mask); | ||
1581 | if ((status & mask) == 0) { | ||
1582 | if (bogus_cnt == INTR_WORK) | ||
1583 | handled = 0; | ||
1584 | break; | ||
1585 | } | ||
1586 | if (status & IM_RCV_INT) { | ||
1587 | /* Got a packet(s). */ | ||
1588 | smc_rx(dev); | ||
1589 | } | ||
1590 | if (status & IM_TX_INT) { | ||
1591 | smc_tx_err(dev); | ||
1592 | outw(IM_TX_INT, ioaddr + INTERRUPT); | ||
1593 | } | ||
1594 | status &= mask; | ||
1595 | if (status & IM_TX_EMPTY_INT) { | ||
1596 | outw(IM_TX_EMPTY_INT, ioaddr + INTERRUPT); | ||
1597 | mask &= ~IM_TX_EMPTY_INT; | ||
1598 | smc->stats.tx_packets += smc->packets_waiting; | ||
1599 | smc->packets_waiting = 0; | ||
1600 | } | ||
1601 | if (status & IM_ALLOC_INT) { | ||
1602 | /* Clear this interrupt so it doesn't happen again */ | ||
1603 | mask &= ~IM_ALLOC_INT; | ||
1604 | |||
1605 | smc_hardware_send_packet(dev); | ||
1606 | |||
1607 | /* enable xmit interrupts based on this */ | ||
1608 | mask |= (IM_TX_EMPTY_INT | IM_TX_INT); | ||
1609 | |||
1610 | /* and let the card send more packets to me */ | ||
1611 | netif_wake_queue(dev); | ||
1612 | } | ||
1613 | if (status & IM_RX_OVRN_INT) { | ||
1614 | smc->stats.rx_errors++; | ||
1615 | smc->stats.rx_fifo_errors++; | ||
1616 | if (smc->duplex) | ||
1617 | smc->rx_ovrn = 1; /* need MC_RESET outside smc_interrupt */ | ||
1618 | outw(IM_RX_OVRN_INT, ioaddr + INTERRUPT); | ||
1619 | } | ||
1620 | if (status & IM_EPH_INT) | ||
1621 | smc_eph_irq(dev); | ||
1622 | } while (--bogus_cnt); | ||
1623 | |||
1624 | DEBUG(3, " Restoring saved registers mask %2.2x bank %4.4x" | ||
1625 | " pointer %4.4x.\n", mask, saved_bank, saved_pointer); | ||
1626 | |||
1627 | /* restore state register */ | ||
1628 | outw((mask<<8), ioaddr + INTERRUPT); | ||
1629 | outw(saved_pointer, ioaddr + POINTER); | ||
1630 | SMC_SELECT_BANK(saved_bank); | ||
1631 | |||
1632 | DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq); | ||
1633 | |||
1634 | irq_done: | ||
1635 | |||
1636 | if ((smc->manfid == MANFID_OSITECH) && | ||
1637 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | ||
1638 | /* Retrigger interrupt if needed */ | ||
1639 | mask_bits(0x00ff, ioaddr-0x10+OSITECH_RESET_ISR); | ||
1640 | set_bits(0x0300, ioaddr-0x10+OSITECH_RESET_ISR); | ||
1641 | } | ||
1642 | if (smc->manfid == MANFID_MOTOROLA) { | ||
1643 | u_char cor; | ||
1644 | cor = readb(smc->base + MOT_UART + CISREG_COR); | ||
1645 | writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_UART + CISREG_COR); | ||
1646 | writeb(cor, smc->base + MOT_UART + CISREG_COR); | ||
1647 | cor = readb(smc->base + MOT_LAN + CISREG_COR); | ||
1648 | writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR); | ||
1649 | writeb(cor, smc->base + MOT_LAN + CISREG_COR); | ||
1650 | } | ||
1651 | #ifdef DOES_NOT_WORK | ||
1652 | if (smc->base != NULL) { /* Megahertz MFC's */ | ||
1653 | readb(smc->base+MEGAHERTZ_ISR); | ||
1654 | readb(smc->base+MEGAHERTZ_ISR); | ||
1655 | } | ||
1656 | #endif | ||
1657 | return IRQ_RETVAL(handled); | ||
1658 | } | ||
1659 | |||
1660 | /*====================================================================*/ | ||
1661 | |||
1662 | static void smc_rx(struct net_device *dev) | ||
1663 | { | ||
1664 | struct smc_private *smc = netdev_priv(dev); | ||
1665 | kio_addr_t ioaddr = dev->base_addr; | ||
1666 | int rx_status; | ||
1667 | int packet_length; /* Caution: not frame length, rather words | ||
1668 | to transfer from the chip. */ | ||
1669 | |||
1670 | /* Assertion: we are in Window 2. */ | ||
1671 | |||
1672 | if (inw(ioaddr + FIFO_PORTS) & FP_RXEMPTY) { | ||
1673 | printk(KERN_ERR "%s: smc_rx() with nothing on Rx FIFO.\n", | ||
1674 | dev->name); | ||
1675 | return; | ||
1676 | } | ||
1677 | |||
1678 | /* Reset the read pointer, and read the status and packet length. */ | ||
1679 | outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER); | ||
1680 | rx_status = inw(ioaddr + DATA_1); | ||
1681 | packet_length = inw(ioaddr + DATA_1) & 0x07ff; | ||
1682 | |||
1683 | DEBUG(2, "%s: Receive status %4.4x length %d.\n", | ||
1684 | dev->name, rx_status, packet_length); | ||
1685 | |||
1686 | if (!(rx_status & RS_ERRORS)) { | ||
1687 | /* do stuff to make a new packet */ | ||
1688 | struct sk_buff *skb; | ||
1689 | |||
1690 | /* Note: packet_length adds 5 or 6 extra bytes here! */ | ||
1691 | skb = dev_alloc_skb(packet_length+2); | ||
1692 | |||
1693 | if (skb == NULL) { | ||
1694 | DEBUG(1, "%s: Low memory, packet dropped.\n", dev->name); | ||
1695 | smc->stats.rx_dropped++; | ||
1696 | outw(MC_RELEASE, ioaddr + MMU_CMD); | ||
1697 | return; | ||
1698 | } | ||
1699 | |||
1700 | packet_length -= (rx_status & RS_ODDFRAME ? 5 : 6); | ||
1701 | skb_reserve(skb, 2); | ||
1702 | insw(ioaddr+DATA_1, skb_put(skb, packet_length), | ||
1703 | (packet_length+1)>>1); | ||
1704 | skb->protocol = eth_type_trans(skb, dev); | ||
1705 | |||
1706 | skb->dev = dev; | ||
1707 | netif_rx(skb); | ||
1708 | dev->last_rx = jiffies; | ||
1709 | smc->stats.rx_packets++; | ||
1710 | smc->stats.rx_bytes += packet_length; | ||
1711 | if (rx_status & RS_MULTICAST) | ||
1712 | smc->stats.multicast++; | ||
1713 | } else { | ||
1714 | /* error ... */ | ||
1715 | smc->stats.rx_errors++; | ||
1716 | |||
1717 | if (rx_status & RS_ALGNERR) smc->stats.rx_frame_errors++; | ||
1718 | if (rx_status & (RS_TOOSHORT | RS_TOOLONG)) | ||
1719 | smc->stats.rx_length_errors++; | ||
1720 | if (rx_status & RS_BADCRC) smc->stats.rx_crc_errors++; | ||
1721 | } | ||
1722 | /* Let the MMU free the memory of this packet. */ | ||
1723 | outw(MC_RELEASE, ioaddr + MMU_CMD); | ||
1724 | |||
1725 | return; | ||
1726 | } | ||
1727 | |||
1728 | /*====================================================================*/ | ||
1729 | |||
1730 | static struct net_device_stats *smc_get_stats(struct net_device *dev) | ||
1731 | { | ||
1732 | struct smc_private *smc = netdev_priv(dev); | ||
1733 | /* Nothing to update - the 91c92 is a pretty primative chip. */ | ||
1734 | return &smc->stats; | ||
1735 | } | ||
1736 | |||
1737 | /*====================================================================== | ||
1738 | |||
1739 | Calculate values for the hardware multicast filter hash table. | ||
1740 | |||
1741 | ======================================================================*/ | ||
1742 | |||
1743 | static void fill_multicast_tbl(int count, struct dev_mc_list *addrs, | ||
1744 | u_char *multicast_table) | ||
1745 | { | ||
1746 | struct dev_mc_list *mc_addr; | ||
1747 | |||
1748 | for (mc_addr = addrs; mc_addr && --count > 0; mc_addr = mc_addr->next) { | ||
1749 | u_int position = ether_crc(6, mc_addr->dmi_addr); | ||
1750 | #ifndef final_version /* Verify multicast address. */ | ||
1751 | if ((mc_addr->dmi_addr[0] & 1) == 0) | ||
1752 | continue; | ||
1753 | #endif | ||
1754 | multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); | ||
1755 | } | ||
1756 | } | ||
1757 | |||
1758 | /*====================================================================== | ||
1759 | |||
1760 | Set the receive mode. | ||
1761 | |||
1762 | This routine is used by both the protocol level to notify us of | ||
1763 | promiscuous/multicast mode changes, and by the open/reset code to | ||
1764 | initialize the Rx registers. We always set the multicast list and | ||
1765 | leave the receiver running. | ||
1766 | |||
1767 | ======================================================================*/ | ||
1768 | |||
1769 | static void set_rx_mode(struct net_device *dev) | ||
1770 | { | ||
1771 | kio_addr_t ioaddr = dev->base_addr; | ||
1772 | struct smc_private *smc = netdev_priv(dev); | ||
1773 | u_int multicast_table[ 2 ] = { 0, }; | ||
1774 | unsigned long flags; | ||
1775 | u_short rx_cfg_setting; | ||
1776 | |||
1777 | if (dev->flags & IFF_PROMISC) { | ||
1778 | printk(KERN_NOTICE "%s: setting Rx mode to promiscuous.\n", dev->name); | ||
1779 | rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti; | ||
1780 | } else if (dev->flags & IFF_ALLMULTI) | ||
1781 | rx_cfg_setting = RxStripCRC | RxEnable | RxAllMulti; | ||
1782 | else { | ||
1783 | if (dev->mc_count) { | ||
1784 | fill_multicast_tbl(dev->mc_count, dev->mc_list, | ||
1785 | (u_char *)multicast_table); | ||
1786 | } | ||
1787 | rx_cfg_setting = RxStripCRC | RxEnable; | ||
1788 | } | ||
1789 | |||
1790 | /* Load MC table and Rx setting into the chip without interrupts. */ | ||
1791 | spin_lock_irqsave(&smc->lock, flags); | ||
1792 | SMC_SELECT_BANK(3); | ||
1793 | outl(multicast_table[0], ioaddr + MULTICAST0); | ||
1794 | outl(multicast_table[1], ioaddr + MULTICAST4); | ||
1795 | SMC_SELECT_BANK(0); | ||
1796 | outw(rx_cfg_setting, ioaddr + RCR); | ||
1797 | SMC_SELECT_BANK(2); | ||
1798 | spin_unlock_irqrestore(&smc->lock, flags); | ||
1799 | |||
1800 | return; | ||
1801 | } | ||
1802 | |||
1803 | /*====================================================================== | ||
1804 | |||
1805 | Senses when a card's config changes. Here, it's coax or TP. | ||
1806 | |||
1807 | ======================================================================*/ | ||
1808 | |||
1809 | static int s9k_config(struct net_device *dev, struct ifmap *map) | ||
1810 | { | ||
1811 | struct smc_private *smc = netdev_priv(dev); | ||
1812 | if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { | ||
1813 | if (smc->cfg & CFG_MII_SELECT) | ||
1814 | return -EOPNOTSUPP; | ||
1815 | else if (map->port > 2) | ||
1816 | return -EINVAL; | ||
1817 | dev->if_port = map->port; | ||
1818 | printk(KERN_INFO "%s: switched to %s port\n", | ||
1819 | dev->name, if_names[dev->if_port]); | ||
1820 | smc_reset(dev); | ||
1821 | } | ||
1822 | return 0; | ||
1823 | } | ||
1824 | |||
1825 | /*====================================================================== | ||
1826 | |||
1827 | Reset the chip, reloading every register that might be corrupted. | ||
1828 | |||
1829 | ======================================================================*/ | ||
1830 | |||
1831 | /* | ||
1832 | Set transceiver type, perhaps to something other than what the user | ||
1833 | specified in dev->if_port. | ||
1834 | */ | ||
1835 | static void smc_set_xcvr(struct net_device *dev, int if_port) | ||
1836 | { | ||
1837 | struct smc_private *smc = netdev_priv(dev); | ||
1838 | kio_addr_t ioaddr = dev->base_addr; | ||
1839 | u_short saved_bank; | ||
1840 | |||
1841 | saved_bank = inw(ioaddr + BANK_SELECT); | ||
1842 | SMC_SELECT_BANK(1); | ||
1843 | if (if_port == 2) { | ||
1844 | outw(smc->cfg | CFG_AUI_SELECT, ioaddr + CONFIG); | ||
1845 | if ((smc->manfid == MANFID_OSITECH) && | ||
1846 | (smc->cardid != PRODID_OSITECH_SEVEN)) | ||
1847 | set_bits(OSI_AUI_PWR, ioaddr - 0x10 + OSITECH_AUI_PWR); | ||
1848 | smc->media_status = ((dev->if_port == 0) ? 0x0001 : 0x0002); | ||
1849 | } else { | ||
1850 | outw(smc->cfg, ioaddr + CONFIG); | ||
1851 | if ((smc->manfid == MANFID_OSITECH) && | ||
1852 | (smc->cardid != PRODID_OSITECH_SEVEN)) | ||
1853 | mask_bits(~OSI_AUI_PWR, ioaddr - 0x10 + OSITECH_AUI_PWR); | ||
1854 | smc->media_status = ((dev->if_port == 0) ? 0x0012 : 0x4001); | ||
1855 | } | ||
1856 | SMC_SELECT_BANK(saved_bank); | ||
1857 | } | ||
1858 | |||
1859 | static void smc_reset(struct net_device *dev) | ||
1860 | { | ||
1861 | kio_addr_t ioaddr = dev->base_addr; | ||
1862 | struct smc_private *smc = netdev_priv(dev); | ||
1863 | int i; | ||
1864 | |||
1865 | DEBUG(0, "%s: smc91c92 reset called.\n", dev->name); | ||
1866 | |||
1867 | /* The first interaction must be a write to bring the chip out | ||
1868 | of sleep mode. */ | ||
1869 | SMC_SELECT_BANK(0); | ||
1870 | /* Reset the chip. */ | ||
1871 | outw(RCR_SOFTRESET, ioaddr + RCR); | ||
1872 | udelay(10); | ||
1873 | |||
1874 | /* Clear the transmit and receive configuration registers. */ | ||
1875 | outw(RCR_CLEAR, ioaddr + RCR); | ||
1876 | outw(TCR_CLEAR, ioaddr + TCR); | ||
1877 | |||
1878 | /* Set the Window 1 control, configuration and station addr registers. | ||
1879 | No point in writing the I/O base register ;-> */ | ||
1880 | SMC_SELECT_BANK(1); | ||
1881 | /* Automatically release succesfully transmitted packets, | ||
1882 | Accept link errors, counter and Tx error interrupts. */ | ||
1883 | outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE, | ||
1884 | ioaddr + CONTROL); | ||
1885 | smc_set_xcvr(dev, dev->if_port); | ||
1886 | if ((smc->manfid == MANFID_OSITECH) && | ||
1887 | (smc->cardid != PRODID_OSITECH_SEVEN)) | ||
1888 | outw((dev->if_port == 2 ? OSI_AUI_PWR : 0) | | ||
1889 | (inw(ioaddr-0x10+OSITECH_AUI_PWR) & 0xff00), | ||
1890 | ioaddr - 0x10 + OSITECH_AUI_PWR); | ||
1891 | |||
1892 | /* Fill in the physical address. The databook is wrong about the order! */ | ||
1893 | for (i = 0; i < 6; i += 2) | ||
1894 | outw((dev->dev_addr[i+1]<<8)+dev->dev_addr[i], | ||
1895 | ioaddr + ADDR0 + i); | ||
1896 | |||
1897 | /* Reset the MMU */ | ||
1898 | SMC_SELECT_BANK(2); | ||
1899 | outw(MC_RESET, ioaddr + MMU_CMD); | ||
1900 | outw(0, ioaddr + INTERRUPT); | ||
1901 | |||
1902 | /* Re-enable the chip. */ | ||
1903 | SMC_SELECT_BANK(0); | ||
1904 | outw(((smc->cfg & CFG_MII_SELECT) ? 0 : TCR_MONCSN) | | ||
1905 | TCR_ENABLE | TCR_PAD_EN | smc->duplex, ioaddr + TCR); | ||
1906 | set_rx_mode(dev); | ||
1907 | |||
1908 | if (smc->cfg & CFG_MII_SELECT) { | ||
1909 | SMC_SELECT_BANK(3); | ||
1910 | |||
1911 | /* Reset MII */ | ||
1912 | mdio_write(dev, smc->mii_if.phy_id, 0, 0x8000); | ||
1913 | |||
1914 | /* Advertise 100F, 100H, 10F, 10H */ | ||
1915 | mdio_write(dev, smc->mii_if.phy_id, 4, 0x01e1); | ||
1916 | |||
1917 | /* Restart MII autonegotiation */ | ||
1918 | mdio_write(dev, smc->mii_if.phy_id, 0, 0x0000); | ||
1919 | mdio_write(dev, smc->mii_if.phy_id, 0, 0x1200); | ||
1920 | } | ||
1921 | |||
1922 | /* Enable interrupts. */ | ||
1923 | SMC_SELECT_BANK(2); | ||
1924 | outw((IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT) << 8, | ||
1925 | ioaddr + INTERRUPT); | ||
1926 | } | ||
1927 | |||
1928 | /*====================================================================== | ||
1929 | |||
1930 | Media selection timer routine | ||
1931 | |||
1932 | ======================================================================*/ | ||
1933 | |||
1934 | static void media_check(u_long arg) | ||
1935 | { | ||
1936 | struct net_device *dev = (struct net_device *) arg; | ||
1937 | struct smc_private *smc = netdev_priv(dev); | ||
1938 | kio_addr_t ioaddr = dev->base_addr; | ||
1939 | u_short i, media, saved_bank; | ||
1940 | u_short link; | ||
1941 | |||
1942 | saved_bank = inw(ioaddr + BANK_SELECT); | ||
1943 | |||
1944 | if (!netif_device_present(dev)) | ||
1945 | goto reschedule; | ||
1946 | |||
1947 | SMC_SELECT_BANK(2); | ||
1948 | |||
1949 | /* need MC_RESET to keep the memory consistent. errata? */ | ||
1950 | if (smc->rx_ovrn) { | ||
1951 | outw(MC_RESET, ioaddr + MMU_CMD); | ||
1952 | smc->rx_ovrn = 0; | ||
1953 | } | ||
1954 | i = inw(ioaddr + INTERRUPT); | ||
1955 | SMC_SELECT_BANK(0); | ||
1956 | media = inw(ioaddr + EPH) & EPH_LINK_OK; | ||
1957 | SMC_SELECT_BANK(1); | ||
1958 | media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1; | ||
1959 | |||
1960 | /* Check for pending interrupt with watchdog flag set: with | ||
1961 | this, we can limp along even if the interrupt is blocked */ | ||
1962 | if (smc->watchdog++ && ((i>>8) & i)) { | ||
1963 | if (!smc->fast_poll) | ||
1964 | printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); | ||
1965 | smc_interrupt(dev->irq, smc, NULL); | ||
1966 | smc->fast_poll = HZ; | ||
1967 | } | ||
1968 | if (smc->fast_poll) { | ||
1969 | smc->fast_poll--; | ||
1970 | smc->media.expires = jiffies + HZ/100; | ||
1971 | add_timer(&smc->media); | ||
1972 | SMC_SELECT_BANK(saved_bank); | ||
1973 | return; | ||
1974 | } | ||
1975 | |||
1976 | if (smc->cfg & CFG_MII_SELECT) { | ||
1977 | if (smc->mii_if.phy_id < 0) | ||
1978 | goto reschedule; | ||
1979 | |||
1980 | SMC_SELECT_BANK(3); | ||
1981 | link = mdio_read(dev, smc->mii_if.phy_id, 1); | ||
1982 | if (!link || (link == 0xffff)) { | ||
1983 | printk(KERN_INFO "%s: MII is missing!\n", dev->name); | ||
1984 | smc->mii_if.phy_id = -1; | ||
1985 | goto reschedule; | ||
1986 | } | ||
1987 | |||
1988 | link &= 0x0004; | ||
1989 | if (link != smc->link_status) { | ||
1990 | u_short p = mdio_read(dev, smc->mii_if.phy_id, 5); | ||
1991 | printk(KERN_INFO "%s: %s link beat\n", dev->name, | ||
1992 | (link) ? "found" : "lost"); | ||
1993 | smc->duplex = (((p & 0x0100) || ((p & 0x1c0) == 0x40)) | ||
1994 | ? TCR_FDUPLX : 0); | ||
1995 | if (link) { | ||
1996 | printk(KERN_INFO "%s: autonegotiation complete: " | ||
1997 | "%sbaseT-%cD selected\n", dev->name, | ||
1998 | ((p & 0x0180) ? "100" : "10"), | ||
1999 | (smc->duplex ? 'F' : 'H')); | ||
2000 | } | ||
2001 | SMC_SELECT_BANK(0); | ||
2002 | outw(inw(ioaddr + TCR) | smc->duplex, ioaddr + TCR); | ||
2003 | smc->link_status = link; | ||
2004 | } | ||
2005 | goto reschedule; | ||
2006 | } | ||
2007 | |||
2008 | /* Ignore collisions unless we've had no rx's recently */ | ||
2009 | if (jiffies - dev->last_rx > HZ) { | ||
2010 | if (smc->tx_err || (smc->media_status & EPH_16COL)) | ||
2011 | media |= EPH_16COL; | ||
2012 | } | ||
2013 | smc->tx_err = 0; | ||
2014 | |||
2015 | if (media != smc->media_status) { | ||
2016 | if ((media & smc->media_status & 1) && | ||
2017 | ((smc->media_status ^ media) & EPH_LINK_OK)) | ||
2018 | printk(KERN_INFO "%s: %s link beat\n", dev->name, | ||
2019 | (smc->media_status & EPH_LINK_OK ? "lost" : "found")); | ||
2020 | else if ((media & smc->media_status & 2) && | ||
2021 | ((smc->media_status ^ media) & EPH_16COL)) | ||
2022 | printk(KERN_INFO "%s: coax cable %s\n", dev->name, | ||
2023 | (media & EPH_16COL ? "problem" : "ok")); | ||
2024 | if (dev->if_port == 0) { | ||
2025 | if (media & 1) { | ||
2026 | if (media & EPH_LINK_OK) | ||
2027 | printk(KERN_INFO "%s: flipped to 10baseT\n", | ||
2028 | dev->name); | ||
2029 | else | ||
2030 | smc_set_xcvr(dev, 2); | ||
2031 | } else { | ||
2032 | if (media & EPH_16COL) | ||
2033 | smc_set_xcvr(dev, 1); | ||
2034 | else | ||
2035 | printk(KERN_INFO "%s: flipped to 10base2\n", | ||
2036 | dev->name); | ||
2037 | } | ||
2038 | } | ||
2039 | smc->media_status = media; | ||
2040 | } | ||
2041 | |||
2042 | reschedule: | ||
2043 | smc->media.expires = jiffies + HZ; | ||
2044 | add_timer(&smc->media); | ||
2045 | SMC_SELECT_BANK(saved_bank); | ||
2046 | } | ||
2047 | |||
2048 | static int smc_link_ok(struct net_device *dev) | ||
2049 | { | ||
2050 | kio_addr_t ioaddr = dev->base_addr; | ||
2051 | struct smc_private *smc = netdev_priv(dev); | ||
2052 | |||
2053 | if (smc->cfg & CFG_MII_SELECT) { | ||
2054 | return mii_link_ok(&smc->mii_if); | ||
2055 | } else { | ||
2056 | SMC_SELECT_BANK(0); | ||
2057 | return inw(ioaddr + EPH) & EPH_LINK_OK; | ||
2058 | } | ||
2059 | } | ||
2060 | |||
2061 | static int smc_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) | ||
2062 | { | ||
2063 | u16 tmp; | ||
2064 | kio_addr_t ioaddr = dev->base_addr; | ||
2065 | |||
2066 | ecmd->supported = (SUPPORTED_TP | SUPPORTED_AUI | | ||
2067 | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full); | ||
2068 | |||
2069 | SMC_SELECT_BANK(1); | ||
2070 | tmp = inw(ioaddr + CONFIG); | ||
2071 | ecmd->port = (tmp & CFG_AUI_SELECT) ? PORT_AUI : PORT_TP; | ||
2072 | ecmd->transceiver = XCVR_INTERNAL; | ||
2073 | ecmd->speed = SPEED_10; | ||
2074 | ecmd->phy_address = ioaddr + MGMT; | ||
2075 | |||
2076 | SMC_SELECT_BANK(0); | ||
2077 | tmp = inw(ioaddr + TCR); | ||
2078 | ecmd->duplex = (tmp & TCR_FDUPLX) ? DUPLEX_FULL : DUPLEX_HALF; | ||
2079 | |||
2080 | return 0; | ||
2081 | } | ||
2082 | |||
2083 | static int smc_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) | ||
2084 | { | ||
2085 | u16 tmp; | ||
2086 | kio_addr_t ioaddr = dev->base_addr; | ||
2087 | |||
2088 | if (ecmd->speed != SPEED_10) | ||
2089 | return -EINVAL; | ||
2090 | if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) | ||
2091 | return -EINVAL; | ||
2092 | if (ecmd->port != PORT_TP && ecmd->port != PORT_AUI) | ||
2093 | return -EINVAL; | ||
2094 | if (ecmd->transceiver != XCVR_INTERNAL) | ||
2095 | return -EINVAL; | ||
2096 | |||
2097 | if (ecmd->port == PORT_AUI) | ||
2098 | smc_set_xcvr(dev, 1); | ||
2099 | else | ||
2100 | smc_set_xcvr(dev, 0); | ||
2101 | |||
2102 | SMC_SELECT_BANK(0); | ||
2103 | tmp = inw(ioaddr + TCR); | ||
2104 | if (ecmd->duplex == DUPLEX_FULL) | ||
2105 | tmp |= TCR_FDUPLX; | ||
2106 | else | ||
2107 | tmp &= ~TCR_FDUPLX; | ||
2108 | outw(tmp, ioaddr + TCR); | ||
2109 | |||
2110 | return 0; | ||
2111 | } | ||
2112 | |||
2113 | static int check_if_running(struct net_device *dev) | ||
2114 | { | ||
2115 | if (!netif_running(dev)) | ||
2116 | return -EINVAL; | ||
2117 | return 0; | ||
2118 | } | ||
2119 | |||
2120 | static void smc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | ||
2121 | { | ||
2122 | strcpy(info->driver, DRV_NAME); | ||
2123 | strcpy(info->version, DRV_VERSION); | ||
2124 | } | ||
2125 | |||
2126 | static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | ||
2127 | { | ||
2128 | struct smc_private *smc = netdev_priv(dev); | ||
2129 | kio_addr_t ioaddr = dev->base_addr; | ||
2130 | u16 saved_bank = inw(ioaddr + BANK_SELECT); | ||
2131 | int ret; | ||
2132 | |||
2133 | SMC_SELECT_BANK(3); | ||
2134 | spin_lock_irq(&smc->lock); | ||
2135 | if (smc->cfg & CFG_MII_SELECT) | ||
2136 | ret = mii_ethtool_gset(&smc->mii_if, ecmd); | ||
2137 | else | ||
2138 | ret = smc_netdev_get_ecmd(dev, ecmd); | ||
2139 | spin_unlock_irq(&smc->lock); | ||
2140 | SMC_SELECT_BANK(saved_bank); | ||
2141 | return ret; | ||
2142 | } | ||
2143 | |||
2144 | static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | ||
2145 | { | ||
2146 | struct smc_private *smc = netdev_priv(dev); | ||
2147 | kio_addr_t ioaddr = dev->base_addr; | ||
2148 | u16 saved_bank = inw(ioaddr + BANK_SELECT); | ||
2149 | int ret; | ||
2150 | |||
2151 | SMC_SELECT_BANK(3); | ||
2152 | spin_lock_irq(&smc->lock); | ||
2153 | if (smc->cfg & CFG_MII_SELECT) | ||
2154 | ret = mii_ethtool_sset(&smc->mii_if, ecmd); | ||
2155 | else | ||
2156 | ret = smc_netdev_set_ecmd(dev, ecmd); | ||
2157 | spin_unlock_irq(&smc->lock); | ||
2158 | SMC_SELECT_BANK(saved_bank); | ||
2159 | return ret; | ||
2160 | } | ||
2161 | |||
2162 | static u32 smc_get_link(struct net_device *dev) | ||
2163 | { | ||
2164 | struct smc_private *smc = netdev_priv(dev); | ||
2165 | kio_addr_t ioaddr = dev->base_addr; | ||
2166 | u16 saved_bank = inw(ioaddr + BANK_SELECT); | ||
2167 | u32 ret; | ||
2168 | |||
2169 | SMC_SELECT_BANK(3); | ||
2170 | spin_lock_irq(&smc->lock); | ||
2171 | ret = smc_link_ok(dev); | ||
2172 | spin_unlock_irq(&smc->lock); | ||
2173 | SMC_SELECT_BANK(saved_bank); | ||
2174 | return ret; | ||
2175 | } | ||
2176 | |||
2177 | #ifdef PCMCIA_DEBUG | ||
2178 | static u32 smc_get_msglevel(struct net_device *dev) | ||
2179 | { | ||
2180 | return pc_debug; | ||
2181 | } | ||
2182 | |||
2183 | static void smc_set_msglevel(struct net_device *dev, u32 val) | ||
2184 | { | ||
2185 | pc_debug = val; | ||
2186 | } | ||
2187 | #endif | ||
2188 | |||
2189 | static int smc_nway_reset(struct net_device *dev) | ||
2190 | { | ||
2191 | struct smc_private *smc = netdev_priv(dev); | ||
2192 | if (smc->cfg & CFG_MII_SELECT) { | ||
2193 | kio_addr_t ioaddr = dev->base_addr; | ||
2194 | u16 saved_bank = inw(ioaddr + BANK_SELECT); | ||
2195 | int res; | ||
2196 | |||
2197 | SMC_SELECT_BANK(3); | ||
2198 | res = mii_nway_restart(&smc->mii_if); | ||
2199 | SMC_SELECT_BANK(saved_bank); | ||
2200 | |||
2201 | return res; | ||
2202 | } else | ||
2203 | return -EOPNOTSUPP; | ||
2204 | } | ||
2205 | |||
2206 | static struct ethtool_ops ethtool_ops = { | ||
2207 | .begin = check_if_running, | ||
2208 | .get_drvinfo = smc_get_drvinfo, | ||
2209 | .get_settings = smc_get_settings, | ||
2210 | .set_settings = smc_set_settings, | ||
2211 | .get_link = smc_get_link, | ||
2212 | #ifdef PCMCIA_DEBUG | ||
2213 | .get_msglevel = smc_get_msglevel, | ||
2214 | .set_msglevel = smc_set_msglevel, | ||
2215 | #endif | ||
2216 | .nway_reset = smc_nway_reset, | ||
2217 | }; | ||
2218 | |||
2219 | static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) | ||
2220 | { | ||
2221 | struct smc_private *smc = netdev_priv(dev); | ||
2222 | struct mii_ioctl_data *mii = if_mii(rq); | ||
2223 | int rc = 0; | ||
2224 | u16 saved_bank; | ||
2225 | kio_addr_t ioaddr = dev->base_addr; | ||
2226 | |||
2227 | if (!netif_running(dev)) | ||
2228 | return -EINVAL; | ||
2229 | |||
2230 | spin_lock_irq(&smc->lock); | ||
2231 | saved_bank = inw(ioaddr + BANK_SELECT); | ||
2232 | SMC_SELECT_BANK(3); | ||
2233 | rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL); | ||
2234 | SMC_SELECT_BANK(saved_bank); | ||
2235 | spin_unlock_irq(&smc->lock); | ||
2236 | return rc; | ||
2237 | } | ||
2238 | |||
2239 | static struct pcmcia_driver smc91c92_cs_driver = { | ||
2240 | .owner = THIS_MODULE, | ||
2241 | .drv = { | ||
2242 | .name = "smc91c92_cs", | ||
2243 | }, | ||
2244 | .attach = smc91c92_attach, | ||
2245 | .detach = smc91c92_detach, | ||
2246 | }; | ||
2247 | |||
2248 | static int __init init_smc91c92_cs(void) | ||
2249 | { | ||
2250 | return pcmcia_register_driver(&smc91c92_cs_driver); | ||
2251 | } | ||
2252 | |||
2253 | static void __exit exit_smc91c92_cs(void) | ||
2254 | { | ||
2255 | pcmcia_unregister_driver(&smc91c92_cs_driver); | ||
2256 | BUG_ON(dev_list != NULL); | ||
2257 | } | ||
2258 | |||
2259 | module_init(init_smc91c92_cs); | ||
2260 | module_exit(exit_smc91c92_cs); | ||
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c new file mode 100644 index 000000000000..58177d67ea12 --- /dev/null +++ b/drivers/net/pcmcia/xirc2ps_cs.c | |||
@@ -0,0 +1,2031 @@ | |||
1 | /* [xirc2ps_cs.c wk 03.11.99] (1.40 1999/11/18 00:06:03) | ||
2 | * Xircom CreditCard Ethernet Adapter IIps driver | ||
3 | * Xircom Realport 10/100 (RE-100) driver | ||
4 | * | ||
5 | * This driver supports various Xircom CreditCard Ethernet adapters | ||
6 | * including the CE2, CE IIps, RE-10, CEM28, CEM33, CE33, CEM56, | ||
7 | * CE3-100, CE3B, RE-100, REM10BT, and REM56G-100. | ||
8 | * | ||
9 | * 2000-09-24 <psheer@icon.co.za> The Xircom CE3B-100 may not | ||
10 | * autodetect the media properly. In this case use the | ||
11 | * if_port=1 (for 10BaseT) or if_port=4 (for 100BaseT) options | ||
12 | * to force the media type. | ||
13 | * | ||
14 | * Written originally by Werner Koch based on David Hinds' skeleton of the | ||
15 | * PCMCIA driver. | ||
16 | * | ||
17 | * Copyright (c) 1997,1998 Werner Koch (dd9jn) | ||
18 | * | ||
19 | * This driver is free software; you can redistribute it and/or modify | ||
20 | * it under the terms of the GNU General Public License as published by | ||
21 | * the Free Software Foundation; either version 2 of the License, or | ||
22 | * (at your option) any later version. | ||
23 | * | ||
24 | * It is distributed in the hope that it will be useful, | ||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | * GNU General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License | ||
30 | * along with this program; if not, write to the Free Software | ||
31 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
32 | * | ||
33 | * | ||
34 | * ALTERNATIVELY, this driver may be distributed under the terms of | ||
35 | * the following license, in which case the provisions of this license | ||
36 | * are required INSTEAD OF the GNU General Public License. (This clause | ||
37 | * is necessary due to a potential bad interaction between the GPL and | ||
38 | * the restrictions contained in a BSD-style copyright.) | ||
39 | * | ||
40 | * Redistribution and use in source and binary forms, with or without | ||
41 | * modification, are permitted provided that the following conditions | ||
42 | * are met: | ||
43 | * 1. Redistributions of source code must retain the above copyright | ||
44 | * notice, and the entire permission notice in its entirety, | ||
45 | * including the disclaimer of warranties. | ||
46 | * 2. Redistributions in binary form must reproduce the above copyright | ||
47 | * notice, this list of conditions and the following disclaimer in the | ||
48 | * documentation and/or other materials provided with the distribution. | ||
49 | * 3. The name of the author may not be used to endorse or promote | ||
50 | * products derived from this software without specific prior | ||
51 | * written permission. | ||
52 | * | ||
53 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
54 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
55 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
56 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | ||
57 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
58 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
59 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
61 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
62 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
63 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
64 | */ | ||
65 | |||
66 | #include <linux/module.h> | ||
67 | #include <linux/kernel.h> | ||
68 | #include <linux/init.h> | ||
69 | #include <linux/ptrace.h> | ||
70 | #include <linux/slab.h> | ||
71 | #include <linux/string.h> | ||
72 | #include <linux/timer.h> | ||
73 | #include <linux/interrupt.h> | ||
74 | #include <linux/in.h> | ||
75 | #include <linux/delay.h> | ||
76 | #include <linux/ethtool.h> | ||
77 | #include <linux/netdevice.h> | ||
78 | #include <linux/etherdevice.h> | ||
79 | #include <linux/skbuff.h> | ||
80 | #include <linux/if_arp.h> | ||
81 | #include <linux/ioport.h> | ||
82 | #include <linux/bitops.h> | ||
83 | |||
84 | #include <pcmcia/version.h> | ||
85 | #include <pcmcia/cs_types.h> | ||
86 | #include <pcmcia/cs.h> | ||
87 | #include <pcmcia/cistpl.h> | ||
88 | #include <pcmcia/cisreg.h> | ||
89 | #include <pcmcia/ciscode.h> | ||
90 | |||
91 | #include <asm/io.h> | ||
92 | #include <asm/system.h> | ||
93 | #include <asm/uaccess.h> | ||
94 | |||
95 | #ifndef MANFID_COMPAQ | ||
96 | #define MANFID_COMPAQ 0x0138 | ||
97 | #define MANFID_COMPAQ2 0x0183 /* is this correct? */ | ||
98 | #endif | ||
99 | |||
100 | #include <pcmcia/ds.h> | ||
101 | |||
102 | /* Time in jiffies before concluding Tx hung */ | ||
103 | #define TX_TIMEOUT ((400*HZ)/1000) | ||
104 | |||
105 | /**************** | ||
106 | * Some constants used to access the hardware | ||
107 | */ | ||
108 | |||
109 | /* Register offsets and value constans */ | ||
110 | #define XIRCREG_CR 0 /* Command register (wr) */ | ||
111 | enum xirc_cr { | ||
112 | TransmitPacket = 0x01, | ||
113 | SoftReset = 0x02, | ||
114 | EnableIntr = 0x04, | ||
115 | ForceIntr = 0x08, | ||
116 | ClearTxFIFO = 0x10, | ||
117 | ClearRxOvrun = 0x20, | ||
118 | RestartTx = 0x40 | ||
119 | }; | ||
120 | #define XIRCREG_ESR 0 /* Ethernet status register (rd) */ | ||
121 | enum xirc_esr { | ||
122 | FullPktRcvd = 0x01, /* full packet in receive buffer */ | ||
123 | PktRejected = 0x04, /* a packet has been rejected */ | ||
124 | TxPktPend = 0x08, /* TX Packet Pending */ | ||
125 | IncorPolarity = 0x10, | ||
126 | MediaSelect = 0x20 /* set if TP, clear if AUI */ | ||
127 | }; | ||
128 | #define XIRCREG_PR 1 /* Page Register select */ | ||
129 | #define XIRCREG_EDP 4 /* Ethernet Data Port Register */ | ||
130 | #define XIRCREG_ISR 6 /* Ethernet Interrupt Status Register */ | ||
131 | enum xirc_isr { | ||
132 | TxBufOvr = 0x01, /* TX Buffer Overflow */ | ||
133 | PktTxed = 0x02, /* Packet Transmitted */ | ||
134 | MACIntr = 0x04, /* MAC Interrupt occurred */ | ||
135 | TxResGrant = 0x08, /* Tx Reservation Granted */ | ||
136 | RxFullPkt = 0x20, /* Rx Full Packet */ | ||
137 | RxPktRej = 0x40, /* Rx Packet Rejected */ | ||
138 | ForcedIntr= 0x80 /* Forced Interrupt */ | ||
139 | }; | ||
140 | #define XIRCREG1_IMR0 12 /* Ethernet Interrupt Mask Register (on page 1)*/ | ||
141 | #define XIRCREG1_IMR1 13 | ||
142 | #define XIRCREG0_TSO 8 /* Transmit Space Open Register (on page 0)*/ | ||
143 | #define XIRCREG0_TRS 10 /* Transmit reservation Size Register (page 0)*/ | ||
144 | #define XIRCREG0_DO 12 /* Data Offset Register (page 0) (wr) */ | ||
145 | #define XIRCREG0_RSR 12 /* Receive Status Register (page 0) (rd) */ | ||
146 | enum xirc_rsr { | ||
147 | PhyPkt = 0x01, /* set:physical packet, clear: multicast packet */ | ||
148 | BrdcstPkt = 0x02, /* set if it is a broadcast packet */ | ||
149 | PktTooLong = 0x04, /* set if packet length > 1518 */ | ||
150 | AlignErr = 0x10, /* incorrect CRC and last octet not complete */ | ||
151 | CRCErr = 0x20, /* incorrect CRC and last octet is complete */ | ||
152 | PktRxOk = 0x80 /* received ok */ | ||
153 | }; | ||
154 | #define XIRCREG0_PTR 13 /* packets transmitted register (rd) */ | ||
155 | #define XIRCREG0_RBC 14 /* receive byte count regsister (rd) */ | ||
156 | #define XIRCREG1_ECR 14 /* ethernet configurationn register */ | ||
157 | enum xirc_ecr { | ||
158 | FullDuplex = 0x04, /* enable full duplex mode */ | ||
159 | LongTPMode = 0x08, /* adjust for longer lengths of TP cable */ | ||
160 | DisablePolCor = 0x10,/* disable auto polarity correction */ | ||
161 | DisableLinkPulse = 0x20, /* disable link pulse generation */ | ||
162 | DisableAutoTx = 0x40, /* disable auto-transmit */ | ||
163 | }; | ||
164 | #define XIRCREG2_RBS 8 /* receive buffer start register */ | ||
165 | #define XIRCREG2_LED 10 /* LED Configuration register */ | ||
166 | /* values for the leds: Bits 2-0 for led 1 | ||
167 | * 0 disabled Bits 5-3 for led 2 | ||
168 | * 1 collision | ||
169 | * 2 noncollision | ||
170 | * 3 link_detected | ||
171 | * 4 incor_polarity | ||
172 | * 5 jabber | ||
173 | * 6 auto_assertion | ||
174 | * 7 rx_tx_activity | ||
175 | */ | ||
176 | #define XIRCREG2_MSR 12 /* Mohawk specific register */ | ||
177 | |||
178 | #define XIRCREG4_GPR0 8 /* General Purpose Register 0 */ | ||
179 | #define XIRCREG4_GPR1 9 /* General Purpose Register 1 */ | ||
180 | #define XIRCREG2_GPR2 13 /* General Purpose Register 2 (page2!)*/ | ||
181 | #define XIRCREG4_BOV 10 /* Bonding Version Register */ | ||
182 | #define XIRCREG4_LMA 12 /* Local Memory Address Register */ | ||
183 | #define XIRCREG4_LMD 14 /* Local Memory Data Port */ | ||
184 | /* MAC register can only by accessed with 8 bit operations */ | ||
185 | #define XIRCREG40_CMD0 8 /* Command Register (wr) */ | ||
186 | enum xirc_cmd { /* Commands */ | ||
187 | Transmit = 0x01, | ||
188 | EnableRecv = 0x04, | ||
189 | DisableRecv = 0x08, | ||
190 | Abort = 0x10, | ||
191 | Online = 0x20, | ||
192 | IntrAck = 0x40, | ||
193 | Offline = 0x80 | ||
194 | }; | ||
195 | #define XIRCREG5_RHSA0 10 /* Rx Host Start Address */ | ||
196 | #define XIRCREG40_RXST0 9 /* Receive Status Register */ | ||
197 | #define XIRCREG40_TXST0 11 /* Transmit Status Register 0 */ | ||
198 | #define XIRCREG40_TXST1 12 /* Transmit Status Register 10 */ | ||
199 | #define XIRCREG40_RMASK0 13 /* Receive Mask Register */ | ||
200 | #define XIRCREG40_TMASK0 14 /* Transmit Mask Register 0 */ | ||
201 | #define XIRCREG40_TMASK1 15 /* Transmit Mask Register 0 */ | ||
202 | #define XIRCREG42_SWC0 8 /* Software Configuration 0 */ | ||
203 | #define XIRCREG42_SWC1 9 /* Software Configuration 1 */ | ||
204 | #define XIRCREG42_BOC 10 /* Back-Off Configuration */ | ||
205 | #define XIRCREG44_TDR0 8 /* Time Domain Reflectometry 0 */ | ||
206 | #define XIRCREG44_TDR1 9 /* Time Domain Reflectometry 1 */ | ||
207 | #define XIRCREG44_RXBC_LO 10 /* Rx Byte Count 0 (rd) */ | ||
208 | #define XIRCREG44_RXBC_HI 11 /* Rx Byte Count 1 (rd) */ | ||
209 | #define XIRCREG45_REV 15 /* Revision Register (rd) */ | ||
210 | #define XIRCREG50_IA 8 /* Individual Address (8-13) */ | ||
211 | |||
212 | static char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; | ||
213 | |||
214 | /**************** | ||
215 | * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If | ||
216 | * you do not define PCMCIA_DEBUG at all, all the debug code will be | ||
217 | * left out. If you compile with PCMCIA_DEBUG=0, the debug code will | ||
218 | * be present but disabled -- but it can then be enabled for specific | ||
219 | * modules at load time with a 'pc_debug=#' option to insmod. | ||
220 | */ | ||
221 | #ifdef PCMCIA_DEBUG | ||
222 | static int pc_debug = PCMCIA_DEBUG; | ||
223 | module_param(pc_debug, int, 0); | ||
224 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KDBG_XIRC args) | ||
225 | #else | ||
226 | #define DEBUG(n, args...) | ||
227 | #endif | ||
228 | |||
229 | #define KDBG_XIRC KERN_DEBUG "xirc2ps_cs: " | ||
230 | #define KERR_XIRC KERN_ERR "xirc2ps_cs: " | ||
231 | #define KWRN_XIRC KERN_WARNING "xirc2ps_cs: " | ||
232 | #define KNOT_XIRC KERN_NOTICE "xirc2ps_cs: " | ||
233 | #define KINF_XIRC KERN_INFO "xirc2ps_cs: " | ||
234 | |||
235 | /* card types */ | ||
236 | #define XIR_UNKNOWN 0 /* unknown: not supported */ | ||
237 | #define XIR_CE 1 /* (prodid 1) different hardware: not supported */ | ||
238 | #define XIR_CE2 2 /* (prodid 2) */ | ||
239 | #define XIR_CE3 3 /* (prodid 3) */ | ||
240 | #define XIR_CEM 4 /* (prodid 1) different hardware: not supported */ | ||
241 | #define XIR_CEM2 5 /* (prodid 2) */ | ||
242 | #define XIR_CEM3 6 /* (prodid 3) */ | ||
243 | #define XIR_CEM33 7 /* (prodid 4) */ | ||
244 | #define XIR_CEM56M 8 /* (prodid 5) */ | ||
245 | #define XIR_CEM56 9 /* (prodid 6) */ | ||
246 | #define XIR_CM28 10 /* (prodid 3) modem only: not supported here */ | ||
247 | #define XIR_CM33 11 /* (prodid 4) modem only: not supported here */ | ||
248 | #define XIR_CM56 12 /* (prodid 5) modem only: not supported here */ | ||
249 | #define XIR_CG 13 /* (prodid 1) GSM modem only: not supported */ | ||
250 | #define XIR_CBE 14 /* (prodid 1) cardbus ethernet: not supported */ | ||
251 | /*====================================================================*/ | ||
252 | |||
253 | /* Module parameters */ | ||
254 | |||
255 | MODULE_DESCRIPTION("Xircom PCMCIA ethernet driver"); | ||
256 | MODULE_LICENSE("Dual MPL/GPL"); | ||
257 | |||
258 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) | ||
259 | |||
260 | INT_MODULE_PARM(if_port, 0); | ||
261 | INT_MODULE_PARM(full_duplex, 0); | ||
262 | INT_MODULE_PARM(do_sound, 1); | ||
263 | INT_MODULE_PARM(lockup_hack, 0); /* anti lockup hack */ | ||
264 | |||
265 | /*====================================================================*/ | ||
266 | |||
267 | /* We do not process more than these number of bytes during one | ||
268 | * interrupt. (Of course we receive complete packets, so this is not | ||
269 | * an exact value). | ||
270 | * Something between 2000..22000; first value gives best interrupt latency, | ||
271 | * the second enables the usage of the complete on-chip buffer. We use the | ||
272 | * high value as the initial value. | ||
273 | */ | ||
274 | static unsigned maxrx_bytes = 22000; | ||
275 | |||
276 | /* MII management prototypes */ | ||
277 | static void mii_idle(kio_addr_t ioaddr); | ||
278 | static void mii_putbit(kio_addr_t ioaddr, unsigned data); | ||
279 | static int mii_getbit(kio_addr_t ioaddr); | ||
280 | static void mii_wbits(kio_addr_t ioaddr, unsigned data, int len); | ||
281 | static unsigned mii_rd(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg); | ||
282 | static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, | ||
283 | unsigned data, int len); | ||
284 | |||
285 | /* | ||
286 | * The event() function is this driver's Card Services event handler. | ||
287 | * It will be called by Card Services when an appropriate card status | ||
288 | * event is received. The config() and release() entry points are | ||
289 | * used to configure or release a socket, in response to card insertion | ||
290 | * and ejection events. They are invoked from the event handler. | ||
291 | */ | ||
292 | |||
293 | static int has_ce2_string(dev_link_t * link); | ||
294 | static void xirc2ps_config(dev_link_t * link); | ||
295 | static void xirc2ps_release(dev_link_t * link); | ||
296 | static int xirc2ps_event(event_t event, int priority, | ||
297 | event_callback_args_t * args); | ||
298 | |||
299 | /**************** | ||
300 | * The attach() and detach() entry points are used to create and destroy | ||
301 | * "instances" of the driver, where each instance represents everything | ||
302 | * needed to manage one actual PCMCIA card. | ||
303 | */ | ||
304 | |||
305 | static dev_link_t *xirc2ps_attach(void); | ||
306 | static void xirc2ps_detach(dev_link_t *); | ||
307 | |||
308 | /**************** | ||
309 | * You'll also need to prototype all the functions that will actually | ||
310 | * be used to talk to your device. See 'pcmem_cs' for a good example | ||
311 | * of a fully self-sufficient driver; the other drivers rely more or | ||
312 | * less on other parts of the kernel. | ||
313 | */ | ||
314 | |||
315 | static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs); | ||
316 | |||
317 | /* | ||
318 | * The dev_info variable is the "key" that is used to match up this | ||
319 | * device driver with appropriate cards, through the card configuration | ||
320 | * database. | ||
321 | */ | ||
322 | |||
323 | static dev_info_t dev_info = "xirc2ps_cs"; | ||
324 | |||
325 | /**************** | ||
326 | * A linked list of "instances" of the device. Each actual | ||
327 | * PCMCIA card corresponds to one device instance, and is described | ||
328 | * by one dev_link_t structure (defined in ds.h). | ||
329 | * | ||
330 | * You may not want to use a linked list for this -- for example, the | ||
331 | * memory card driver uses an array of dev_link_t pointers, where minor | ||
332 | * device numbers are used to derive the corresponding array index. | ||
333 | */ | ||
334 | |||
335 | static dev_link_t *dev_list; | ||
336 | |||
337 | /**************** | ||
338 | * A dev_link_t structure has fields for most things that are needed | ||
339 | * to keep track of a socket, but there will usually be some device | ||
340 | * specific information that also needs to be kept track of. The | ||
341 | * 'priv' pointer in a dev_link_t structure can be used to point to | ||
342 | * a device-specific private data structure, like this. | ||
343 | * | ||
344 | * A driver needs to provide a dev_node_t structure for each device | ||
345 | * on a card. In some cases, there is only one device per card (for | ||
346 | * example, ethernet cards, modems). In other cases, there may be | ||
347 | * many actual or logical devices (SCSI adapters, memory cards with | ||
348 | * multiple partitions). The dev_node_t structures need to be kept | ||
349 | * in a linked list starting at the 'dev' field of a dev_link_t | ||
350 | * structure. We allocate them in the card's private data structure, | ||
351 | * because they generally can't be allocated dynamically. | ||
352 | */ | ||
353 | |||
354 | typedef struct local_info_t { | ||
355 | dev_link_t link; | ||
356 | dev_node_t node; | ||
357 | struct net_device_stats stats; | ||
358 | int card_type; | ||
359 | int probe_port; | ||
360 | int silicon; /* silicon revision. 0=old CE2, 1=Scipper, 4=Mohawk */ | ||
361 | int mohawk; /* a CE3 type card */ | ||
362 | int dingo; /* a CEM56 type card */ | ||
363 | int new_mii; /* has full 10baseT/100baseT MII */ | ||
364 | int modem; /* is a multi function card (i.e with a modem) */ | ||
365 | void __iomem *dingo_ccr; /* only used for CEM56 cards */ | ||
366 | unsigned last_ptr_value; /* last packets transmitted value */ | ||
367 | const char *manf_str; | ||
368 | } local_info_t; | ||
369 | |||
370 | /**************** | ||
371 | * Some more prototypes | ||
372 | */ | ||
373 | static int do_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
374 | static void do_tx_timeout(struct net_device *dev); | ||
375 | static struct net_device_stats *do_get_stats(struct net_device *dev); | ||
376 | static void set_addresses(struct net_device *dev); | ||
377 | static void set_multicast_list(struct net_device *dev); | ||
378 | static int set_card_type(dev_link_t *link, const void *s); | ||
379 | static int do_config(struct net_device *dev, struct ifmap *map); | ||
380 | static int do_open(struct net_device *dev); | ||
381 | static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
382 | static struct ethtool_ops netdev_ethtool_ops; | ||
383 | static void hardreset(struct net_device *dev); | ||
384 | static void do_reset(struct net_device *dev, int full); | ||
385 | static int init_mii(struct net_device *dev); | ||
386 | static void do_powerdown(struct net_device *dev); | ||
387 | static int do_stop(struct net_device *dev); | ||
388 | |||
389 | /*=============== Helper functions =========================*/ | ||
390 | static int | ||
391 | first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
392 | { | ||
393 | int err; | ||
394 | |||
395 | if ((err = pcmcia_get_first_tuple(handle, tuple)) == 0 && | ||
396 | (err = pcmcia_get_tuple_data(handle, tuple)) == 0) | ||
397 | err = pcmcia_parse_tuple(handle, tuple, parse); | ||
398 | return err; | ||
399 | } | ||
400 | |||
401 | static int | ||
402 | next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
403 | { | ||
404 | int err; | ||
405 | |||
406 | if ((err = pcmcia_get_next_tuple(handle, tuple)) == 0 && | ||
407 | (err = pcmcia_get_tuple_data(handle, tuple)) == 0) | ||
408 | err = pcmcia_parse_tuple(handle, tuple, parse); | ||
409 | return err; | ||
410 | } | ||
411 | |||
412 | #define SelectPage(pgnr) outb((pgnr), ioaddr + XIRCREG_PR) | ||
413 | #define GetByte(reg) ((unsigned)inb(ioaddr + (reg))) | ||
414 | #define GetWord(reg) ((unsigned)inw(ioaddr + (reg))) | ||
415 | #define PutByte(reg,value) outb((value), ioaddr+(reg)) | ||
416 | #define PutWord(reg,value) outw((value), ioaddr+(reg)) | ||
417 | |||
418 | /*====== Functions used for debugging =================================*/ | ||
419 | #if defined(PCMCIA_DEBUG) && 0 /* reading regs may change system status */ | ||
420 | static void | ||
421 | PrintRegisters(struct net_device *dev) | ||
422 | { | ||
423 | kio_addr_t ioaddr = dev->base_addr; | ||
424 | |||
425 | if (pc_debug > 1) { | ||
426 | int i, page; | ||
427 | |||
428 | printk(KDBG_XIRC "Register common: "); | ||
429 | for (i = 0; i < 8; i++) | ||
430 | printk(" %2.2x", GetByte(i)); | ||
431 | printk("\n"); | ||
432 | for (page = 0; page <= 8; page++) { | ||
433 | printk(KDBG_XIRC "Register page %2x: ", page); | ||
434 | SelectPage(page); | ||
435 | for (i = 8; i < 16; i++) | ||
436 | printk(" %2.2x", GetByte(i)); | ||
437 | printk("\n"); | ||
438 | } | ||
439 | for (page=0x40 ; page <= 0x5f; page++) { | ||
440 | if (page == 0x43 || (page >= 0x46 && page <= 0x4f) | ||
441 | || (page >= 0x51 && page <=0x5e)) | ||
442 | continue; | ||
443 | printk(KDBG_XIRC "Register page %2x: ", page); | ||
444 | SelectPage(page); | ||
445 | for (i = 8; i < 16; i++) | ||
446 | printk(" %2.2x", GetByte(i)); | ||
447 | printk("\n"); | ||
448 | } | ||
449 | } | ||
450 | } | ||
451 | #endif /* PCMCIA_DEBUG */ | ||
452 | |||
453 | /*============== MII Management functions ===============*/ | ||
454 | |||
455 | /**************** | ||
456 | * Turn around for read | ||
457 | */ | ||
458 | static void | ||
459 | mii_idle(kio_addr_t ioaddr) | ||
460 | { | ||
461 | PutByte(XIRCREG2_GPR2, 0x04|0); /* drive MDCK low */ | ||
462 | udelay(1); | ||
463 | PutByte(XIRCREG2_GPR2, 0x04|1); /* and drive MDCK high */ | ||
464 | udelay(1); | ||
465 | } | ||
466 | |||
467 | /**************** | ||
468 | * Write a bit to MDI/O | ||
469 | */ | ||
470 | static void | ||
471 | mii_putbit(kio_addr_t ioaddr, unsigned data) | ||
472 | { | ||
473 | #if 1 | ||
474 | if (data) { | ||
475 | PutByte(XIRCREG2_GPR2, 0x0c|2|0); /* set MDIO */ | ||
476 | udelay(1); | ||
477 | PutByte(XIRCREG2_GPR2, 0x0c|2|1); /* and drive MDCK high */ | ||
478 | udelay(1); | ||
479 | } else { | ||
480 | PutByte(XIRCREG2_GPR2, 0x0c|0|0); /* clear MDIO */ | ||
481 | udelay(1); | ||
482 | PutByte(XIRCREG2_GPR2, 0x0c|0|1); /* and drive MDCK high */ | ||
483 | udelay(1); | ||
484 | } | ||
485 | #else | ||
486 | if (data) { | ||
487 | PutWord(XIRCREG2_GPR2-1, 0x0e0e); | ||
488 | udelay(1); | ||
489 | PutWord(XIRCREG2_GPR2-1, 0x0f0f); | ||
490 | udelay(1); | ||
491 | } else { | ||
492 | PutWord(XIRCREG2_GPR2-1, 0x0c0c); | ||
493 | udelay(1); | ||
494 | PutWord(XIRCREG2_GPR2-1, 0x0d0d); | ||
495 | udelay(1); | ||
496 | } | ||
497 | #endif | ||
498 | } | ||
499 | |||
500 | /**************** | ||
501 | * Get a bit from MDI/O | ||
502 | */ | ||
503 | static int | ||
504 | mii_getbit(kio_addr_t ioaddr) | ||
505 | { | ||
506 | unsigned d; | ||
507 | |||
508 | PutByte(XIRCREG2_GPR2, 4|0); /* drive MDCK low */ | ||
509 | udelay(1); | ||
510 | d = GetByte(XIRCREG2_GPR2); /* read MDIO */ | ||
511 | PutByte(XIRCREG2_GPR2, 4|1); /* drive MDCK high again */ | ||
512 | udelay(1); | ||
513 | return d & 0x20; /* read MDIO */ | ||
514 | } | ||
515 | |||
516 | static void | ||
517 | mii_wbits(kio_addr_t ioaddr, unsigned data, int len) | ||
518 | { | ||
519 | unsigned m = 1 << (len-1); | ||
520 | for (; m; m >>= 1) | ||
521 | mii_putbit(ioaddr, data & m); | ||
522 | } | ||
523 | |||
524 | static unsigned | ||
525 | mii_rd(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg) | ||
526 | { | ||
527 | int i; | ||
528 | unsigned data=0, m; | ||
529 | |||
530 | SelectPage(2); | ||
531 | for (i=0; i < 32; i++) /* 32 bit preamble */ | ||
532 | mii_putbit(ioaddr, 1); | ||
533 | mii_wbits(ioaddr, 0x06, 4); /* Start and opcode for read */ | ||
534 | mii_wbits(ioaddr, phyaddr, 5); /* PHY address to be accessed */ | ||
535 | mii_wbits(ioaddr, phyreg, 5); /* PHY register to read */ | ||
536 | mii_idle(ioaddr); /* turn around */ | ||
537 | mii_getbit(ioaddr); | ||
538 | |||
539 | for (m = 1<<15; m; m >>= 1) | ||
540 | if (mii_getbit(ioaddr)) | ||
541 | data |= m; | ||
542 | mii_idle(ioaddr); | ||
543 | return data; | ||
544 | } | ||
545 | |||
546 | static void | ||
547 | mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) | ||
548 | { | ||
549 | int i; | ||
550 | |||
551 | SelectPage(2); | ||
552 | for (i=0; i < 32; i++) /* 32 bit preamble */ | ||
553 | mii_putbit(ioaddr, 1); | ||
554 | mii_wbits(ioaddr, 0x05, 4); /* Start and opcode for write */ | ||
555 | mii_wbits(ioaddr, phyaddr, 5); /* PHY address to be accessed */ | ||
556 | mii_wbits(ioaddr, phyreg, 5); /* PHY Register to write */ | ||
557 | mii_putbit(ioaddr, 1); /* turn around */ | ||
558 | mii_putbit(ioaddr, 0); | ||
559 | mii_wbits(ioaddr, data, len); /* And write the data */ | ||
560 | mii_idle(ioaddr); | ||
561 | } | ||
562 | |||
563 | /*============= Main bulk of functions =========================*/ | ||
564 | |||
565 | /**************** | ||
566 | * xirc2ps_attach() creates an "instance" of the driver, allocating | ||
567 | * local data structures for one device. The device is registered | ||
568 | * with Card Services. | ||
569 | * | ||
570 | * The dev_link structure is initialized, but we don't actually | ||
571 | * configure the card at this point -- we wait until we receive a | ||
572 | * card insertion event. | ||
573 | */ | ||
574 | |||
575 | static dev_link_t * | ||
576 | xirc2ps_attach(void) | ||
577 | { | ||
578 | client_reg_t client_reg; | ||
579 | dev_link_t *link; | ||
580 | struct net_device *dev; | ||
581 | local_info_t *local; | ||
582 | int err; | ||
583 | |||
584 | DEBUG(0, "attach()\n"); | ||
585 | |||
586 | /* Allocate the device structure */ | ||
587 | dev = alloc_etherdev(sizeof(local_info_t)); | ||
588 | if (!dev) | ||
589 | return NULL; | ||
590 | local = netdev_priv(dev); | ||
591 | link = &local->link; | ||
592 | link->priv = dev; | ||
593 | |||
594 | /* General socket configuration */ | ||
595 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
596 | link->conf.Vcc = 50; | ||
597 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
598 | link->conf.ConfigIndex = 1; | ||
599 | link->conf.Present = PRESENT_OPTION; | ||
600 | link->irq.Handler = xirc2ps_interrupt; | ||
601 | link->irq.Instance = dev; | ||
602 | |||
603 | /* Fill in card specific entries */ | ||
604 | SET_MODULE_OWNER(dev); | ||
605 | dev->hard_start_xmit = &do_start_xmit; | ||
606 | dev->set_config = &do_config; | ||
607 | dev->get_stats = &do_get_stats; | ||
608 | dev->do_ioctl = &do_ioctl; | ||
609 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | ||
610 | dev->set_multicast_list = &set_multicast_list; | ||
611 | dev->open = &do_open; | ||
612 | dev->stop = &do_stop; | ||
613 | #ifdef HAVE_TX_TIMEOUT | ||
614 | dev->tx_timeout = do_tx_timeout; | ||
615 | dev->watchdog_timeo = TX_TIMEOUT; | ||
616 | #endif | ||
617 | |||
618 | /* Register with Card Services */ | ||
619 | link->next = dev_list; | ||
620 | dev_list = link; | ||
621 | client_reg.dev_info = &dev_info; | ||
622 | client_reg.EventMask = | ||
623 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
624 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
625 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
626 | client_reg.event_handler = &xirc2ps_event; | ||
627 | client_reg.Version = 0x0210; | ||
628 | client_reg.event_callback_args.client_data = link; | ||
629 | if ((err = pcmcia_register_client(&link->handle, &client_reg))) { | ||
630 | cs_error(link->handle, RegisterClient, err); | ||
631 | xirc2ps_detach(link); | ||
632 | return NULL; | ||
633 | } | ||
634 | |||
635 | return link; | ||
636 | } /* xirc2ps_attach */ | ||
637 | |||
638 | /**************** | ||
639 | * This deletes a driver "instance". The device is de-registered | ||
640 | * with Card Services. If it has been released, all local data | ||
641 | * structures are freed. Otherwise, the structures will be freed | ||
642 | * when the device is released. | ||
643 | */ | ||
644 | |||
645 | static void | ||
646 | xirc2ps_detach(dev_link_t * link) | ||
647 | { | ||
648 | struct net_device *dev = link->priv; | ||
649 | dev_link_t **linkp; | ||
650 | |||
651 | DEBUG(0, "detach(0x%p)\n", link); | ||
652 | |||
653 | /* Locate device structure */ | ||
654 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
655 | if (*linkp == link) | ||
656 | break; | ||
657 | if (!*linkp) { | ||
658 | DEBUG(0, "detach(0x%p): dev_link lost\n", link); | ||
659 | return; | ||
660 | } | ||
661 | |||
662 | if (link->dev) | ||
663 | unregister_netdev(dev); | ||
664 | |||
665 | /* | ||
666 | * If the device is currently configured and active, we won't | ||
667 | * actually delete it yet. Instead, it is marked so that when | ||
668 | * the release() function is called, that will trigger a proper | ||
669 | * detach(). | ||
670 | */ | ||
671 | if (link->state & DEV_CONFIG) | ||
672 | xirc2ps_release(link); | ||
673 | |||
674 | /* Break the link with Card Services */ | ||
675 | if (link->handle) | ||
676 | pcmcia_deregister_client(link->handle); | ||
677 | |||
678 | /* Unlink device structure, free it */ | ||
679 | *linkp = link->next; | ||
680 | free_netdev(dev); | ||
681 | } /* xirc2ps_detach */ | ||
682 | |||
683 | /**************** | ||
684 | * Detect the type of the card. s is the buffer with the data of tuple 0x20 | ||
685 | * Returns: 0 := not supported | ||
686 | * mediaid=11 and prodid=47 | ||
687 | * Media-Id bits: | ||
688 | * Ethernet 0x01 | ||
689 | * Tokenring 0x02 | ||
690 | * Arcnet 0x04 | ||
691 | * Wireless 0x08 | ||
692 | * Modem 0x10 | ||
693 | * GSM only 0x20 | ||
694 | * Prod-Id bits: | ||
695 | * Pocket 0x10 | ||
696 | * External 0x20 | ||
697 | * Creditcard 0x40 | ||
698 | * Cardbus 0x80 | ||
699 | * | ||
700 | */ | ||
701 | static int | ||
702 | set_card_type(dev_link_t *link, const void *s) | ||
703 | { | ||
704 | struct net_device *dev = link->priv; | ||
705 | local_info_t *local = netdev_priv(dev); | ||
706 | #ifdef PCMCIA_DEBUG | ||
707 | unsigned cisrev = ((const unsigned char *)s)[2]; | ||
708 | #endif | ||
709 | unsigned mediaid= ((const unsigned char *)s)[3]; | ||
710 | unsigned prodid = ((const unsigned char *)s)[4]; | ||
711 | |||
712 | DEBUG(0, "cisrev=%02x mediaid=%02x prodid=%02x\n", | ||
713 | cisrev, mediaid, prodid); | ||
714 | |||
715 | local->mohawk = 0; | ||
716 | local->dingo = 0; | ||
717 | local->modem = 0; | ||
718 | local->card_type = XIR_UNKNOWN; | ||
719 | if (!(prodid & 0x40)) { | ||
720 | printk(KNOT_XIRC "Ooops: Not a creditcard\n"); | ||
721 | return 0; | ||
722 | } | ||
723 | if (!(mediaid & 0x01)) { | ||
724 | printk(KNOT_XIRC "Not an Ethernet card\n"); | ||
725 | return 0; | ||
726 | } | ||
727 | if (mediaid & 0x10) { | ||
728 | local->modem = 1; | ||
729 | switch(prodid & 15) { | ||
730 | case 1: local->card_type = XIR_CEM ; break; | ||
731 | case 2: local->card_type = XIR_CEM2 ; break; | ||
732 | case 3: local->card_type = XIR_CEM3 ; break; | ||
733 | case 4: local->card_type = XIR_CEM33 ; break; | ||
734 | case 5: local->card_type = XIR_CEM56M; | ||
735 | local->mohawk = 1; | ||
736 | break; | ||
737 | case 6: | ||
738 | case 7: /* 7 is the RealPort 10/56 */ | ||
739 | local->card_type = XIR_CEM56 ; | ||
740 | local->mohawk = 1; | ||
741 | local->dingo = 1; | ||
742 | break; | ||
743 | } | ||
744 | } else { | ||
745 | switch(prodid & 15) { | ||
746 | case 1: local->card_type = has_ce2_string(link)? XIR_CE2 : XIR_CE ; | ||
747 | break; | ||
748 | case 2: local->card_type = XIR_CE2; break; | ||
749 | case 3: local->card_type = XIR_CE3; | ||
750 | local->mohawk = 1; | ||
751 | break; | ||
752 | } | ||
753 | } | ||
754 | if (local->card_type == XIR_CE || local->card_type == XIR_CEM) { | ||
755 | printk(KNOT_XIRC "Sorry, this is an old CE card\n"); | ||
756 | return 0; | ||
757 | } | ||
758 | if (local->card_type == XIR_UNKNOWN) | ||
759 | printk(KNOT_XIRC "unknown card (mediaid=%02x prodid=%02x)\n", | ||
760 | mediaid, prodid); | ||
761 | |||
762 | return 1; | ||
763 | } | ||
764 | |||
765 | /**************** | ||
766 | * There are some CE2 cards out which claim to be a CE card. | ||
767 | * This function looks for a "CE2" in the 3rd version field. | ||
768 | * Returns: true if this is a CE2 | ||
769 | */ | ||
770 | static int | ||
771 | has_ce2_string(dev_link_t * link) | ||
772 | { | ||
773 | client_handle_t handle = link->handle; | ||
774 | tuple_t tuple; | ||
775 | cisparse_t parse; | ||
776 | u_char buf[256]; | ||
777 | |||
778 | tuple.Attributes = 0; | ||
779 | tuple.TupleData = buf; | ||
780 | tuple.TupleDataMax = 254; | ||
781 | tuple.TupleOffset = 0; | ||
782 | tuple.DesiredTuple = CISTPL_VERS_1; | ||
783 | if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) { | ||
784 | if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2")) | ||
785 | return 1; | ||
786 | } | ||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | /**************** | ||
791 | * xirc2ps_config() is scheduled to run after a CARD_INSERTION event | ||
792 | * is received, to configure the PCMCIA socket, and to make the | ||
793 | * ethernet device available to the system. | ||
794 | */ | ||
795 | static void | ||
796 | xirc2ps_config(dev_link_t * link) | ||
797 | { | ||
798 | client_handle_t handle = link->handle; | ||
799 | struct net_device *dev = link->priv; | ||
800 | local_info_t *local = netdev_priv(dev); | ||
801 | tuple_t tuple; | ||
802 | cisparse_t parse; | ||
803 | kio_addr_t ioaddr; | ||
804 | int err, i; | ||
805 | u_char buf[64]; | ||
806 | cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data; | ||
807 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | ||
808 | |||
809 | local->dingo_ccr = NULL; | ||
810 | |||
811 | DEBUG(0, "config(0x%p)\n", link); | ||
812 | |||
813 | /* | ||
814 | * This reads the card's CONFIG tuple to find its configuration | ||
815 | * registers. | ||
816 | */ | ||
817 | tuple.Attributes = 0; | ||
818 | tuple.TupleData = buf; | ||
819 | tuple.TupleDataMax = 64; | ||
820 | tuple.TupleOffset = 0; | ||
821 | |||
822 | /* Is this a valid card */ | ||
823 | tuple.DesiredTuple = CISTPL_MANFID; | ||
824 | if ((err=first_tuple(handle, &tuple, &parse))) { | ||
825 | printk(KNOT_XIRC "manfid not found in CIS\n"); | ||
826 | goto failure; | ||
827 | } | ||
828 | |||
829 | switch(parse.manfid.manf) { | ||
830 | case MANFID_XIRCOM: | ||
831 | local->manf_str = "Xircom"; | ||
832 | break; | ||
833 | case MANFID_ACCTON: | ||
834 | local->manf_str = "Accton"; | ||
835 | break; | ||
836 | case MANFID_COMPAQ: | ||
837 | case MANFID_COMPAQ2: | ||
838 | local->manf_str = "Compaq"; | ||
839 | break; | ||
840 | case MANFID_INTEL: | ||
841 | local->manf_str = "Intel"; | ||
842 | break; | ||
843 | case MANFID_TOSHIBA: | ||
844 | local->manf_str = "Toshiba"; | ||
845 | break; | ||
846 | default: | ||
847 | printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n", | ||
848 | (unsigned)parse.manfid.manf); | ||
849 | goto failure; | ||
850 | } | ||
851 | DEBUG(0, "found %s card\n", local->manf_str); | ||
852 | |||
853 | if (!set_card_type(link, buf)) { | ||
854 | printk(KNOT_XIRC "this card is not supported\n"); | ||
855 | goto failure; | ||
856 | } | ||
857 | |||
858 | /* get configuration stuff */ | ||
859 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
860 | if ((err=first_tuple(handle, &tuple, &parse))) | ||
861 | goto cis_error; | ||
862 | link->conf.ConfigBase = parse.config.base; | ||
863 | link->conf.Present = parse.config.rmask[0]; | ||
864 | |||
865 | /* get the ethernet address from the CIS */ | ||
866 | tuple.DesiredTuple = CISTPL_FUNCE; | ||
867 | for (err = first_tuple(handle, &tuple, &parse); !err; | ||
868 | err = next_tuple(handle, &tuple, &parse)) { | ||
869 | /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: | ||
870 | * the first one with a length of zero the second correct - | ||
871 | * so I skip all entries with length 0 */ | ||
872 | if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID | ||
873 | && ((cistpl_lan_node_id_t *)parse.funce.data)->nb) | ||
874 | break; | ||
875 | } | ||
876 | if (err) { /* not found: try to get the node-id from tuple 0x89 */ | ||
877 | tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */ | ||
878 | if ((err = pcmcia_get_first_tuple(handle, &tuple)) == 0 && | ||
879 | (err = pcmcia_get_tuple_data(handle, &tuple)) == 0) { | ||
880 | if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) | ||
881 | memcpy(&parse, buf, 8); | ||
882 | else | ||
883 | err = -1; | ||
884 | } | ||
885 | } | ||
886 | if (err) { /* another try (James Lehmer's CE2 version 4.1)*/ | ||
887 | tuple.DesiredTuple = CISTPL_FUNCE; | ||
888 | for (err = first_tuple(handle, &tuple, &parse); !err; | ||
889 | err = next_tuple(handle, &tuple, &parse)) { | ||
890 | if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 | ||
891 | && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { | ||
892 | buf[1] = 4; | ||
893 | memcpy(&parse, buf+1, 8); | ||
894 | break; | ||
895 | } | ||
896 | } | ||
897 | } | ||
898 | if (err) { | ||
899 | printk(KNOT_XIRC "node-id not found in CIS\n"); | ||
900 | goto failure; | ||
901 | } | ||
902 | node_id = (cistpl_lan_node_id_t *)parse.funce.data; | ||
903 | if (node_id->nb != 6) { | ||
904 | printk(KNOT_XIRC "malformed node-id in CIS\n"); | ||
905 | goto failure; | ||
906 | } | ||
907 | for (i=0; i < 6; i++) | ||
908 | dev->dev_addr[i] = node_id->id[i]; | ||
909 | |||
910 | /* Configure card */ | ||
911 | link->state |= DEV_CONFIG; | ||
912 | |||
913 | link->io.IOAddrLines =10; | ||
914 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
915 | link->irq.Attributes = IRQ_HANDLE_PRESENT; | ||
916 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
917 | if (local->modem) { | ||
918 | int pass; | ||
919 | |||
920 | if (do_sound) { | ||
921 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
922 | link->conf.Status |= CCSR_AUDIO_ENA; | ||
923 | } | ||
924 | link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED ; | ||
925 | link->io.NumPorts2 = 8; | ||
926 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; | ||
927 | if (local->dingo) { | ||
928 | /* Take the Modem IO port from the CIS and scan for a free | ||
929 | * Ethernet port */ | ||
930 | link->io.NumPorts1 = 16; /* no Mako stuff anymore */ | ||
931 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
932 | for (err = first_tuple(handle, &tuple, &parse); !err; | ||
933 | err = next_tuple(handle, &tuple, &parse)) { | ||
934 | if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { | ||
935 | for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { | ||
936 | link->conf.ConfigIndex = cf->index ; | ||
937 | link->io.BasePort2 = cf->io.win[0].base; | ||
938 | link->io.BasePort1 = ioaddr; | ||
939 | if (!(err=pcmcia_request_io(link->handle, &link->io))) | ||
940 | goto port_found; | ||
941 | } | ||
942 | } | ||
943 | } | ||
944 | } else { | ||
945 | link->io.NumPorts1 = 18; | ||
946 | /* We do 2 passes here: The first one uses the regular mapping and | ||
947 | * the second tries again, thereby considering that the 32 ports are | ||
948 | * mirrored every 32 bytes. Actually we use a mirrored port for | ||
949 | * the Mako if (on the first pass) the COR bit 5 is set. | ||
950 | */ | ||
951 | for (pass=0; pass < 2; pass++) { | ||
952 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
953 | for (err = first_tuple(handle, &tuple, &parse); !err; | ||
954 | err = next_tuple(handle, &tuple, &parse)){ | ||
955 | if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){ | ||
956 | link->conf.ConfigIndex = cf->index ; | ||
957 | link->io.BasePort2 = cf->io.win[0].base; | ||
958 | link->io.BasePort1 = link->io.BasePort2 | ||
959 | + (pass ? (cf->index & 0x20 ? -24:8) | ||
960 | : (cf->index & 0x20 ? 8:-24)); | ||
961 | if (!(err=pcmcia_request_io(link->handle, &link->io))) | ||
962 | goto port_found; | ||
963 | } | ||
964 | } | ||
965 | } | ||
966 | /* if special option: | ||
967 | * try to configure as Ethernet only. | ||
968 | * .... */ | ||
969 | } | ||
970 | printk(KNOT_XIRC "no ports available\n"); | ||
971 | } else { | ||
972 | link->irq.Attributes |= IRQ_TYPE_EXCLUSIVE; | ||
973 | link->io.NumPorts1 = 16; | ||
974 | for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { | ||
975 | link->io.BasePort1 = ioaddr; | ||
976 | if (!(err=pcmcia_request_io(link->handle, &link->io))) | ||
977 | goto port_found; | ||
978 | } | ||
979 | link->io.BasePort1 = 0; /* let CS decide */ | ||
980 | if ((err=pcmcia_request_io(link->handle, &link->io))) { | ||
981 | cs_error(link->handle, RequestIO, err); | ||
982 | goto config_error; | ||
983 | } | ||
984 | } | ||
985 | port_found: | ||
986 | if (err) | ||
987 | goto config_error; | ||
988 | |||
989 | /**************** | ||
990 | * Now allocate an interrupt line. Note that this does not | ||
991 | * actually assign a handler to the interrupt. | ||
992 | */ | ||
993 | if ((err=pcmcia_request_irq(link->handle, &link->irq))) { | ||
994 | cs_error(link->handle, RequestIRQ, err); | ||
995 | goto config_error; | ||
996 | } | ||
997 | |||
998 | /**************** | ||
999 | * This actually configures the PCMCIA socket -- setting up | ||
1000 | * the I/O windows and the interrupt mapping. | ||
1001 | */ | ||
1002 | if ((err=pcmcia_request_configuration(link->handle, &link->conf))) { | ||
1003 | cs_error(link->handle, RequestConfiguration, err); | ||
1004 | goto config_error; | ||
1005 | } | ||
1006 | |||
1007 | if (local->dingo) { | ||
1008 | conf_reg_t reg; | ||
1009 | win_req_t req; | ||
1010 | memreq_t mem; | ||
1011 | |||
1012 | /* Reset the modem's BAR to the correct value | ||
1013 | * This is necessary because in the RequestConfiguration call, | ||
1014 | * the base address of the ethernet port (BasePort1) is written | ||
1015 | * to the BAR registers of the modem. | ||
1016 | */ | ||
1017 | reg.Action = CS_WRITE; | ||
1018 | reg.Offset = CISREG_IOBASE_0; | ||
1019 | reg.Value = link->io.BasePort2 & 0xff; | ||
1020 | if ((err = pcmcia_access_configuration_register(link->handle, ®))) { | ||
1021 | cs_error(link->handle, AccessConfigurationRegister, err); | ||
1022 | goto config_error; | ||
1023 | } | ||
1024 | reg.Action = CS_WRITE; | ||
1025 | reg.Offset = CISREG_IOBASE_1; | ||
1026 | reg.Value = (link->io.BasePort2 >> 8) & 0xff; | ||
1027 | if ((err = pcmcia_access_configuration_register(link->handle, ®))) { | ||
1028 | cs_error(link->handle, AccessConfigurationRegister, err); | ||
1029 | goto config_error; | ||
1030 | } | ||
1031 | |||
1032 | /* There is no config entry for the Ethernet part which | ||
1033 | * is at 0x0800. So we allocate a window into the attribute | ||
1034 | * memory and write direct to the CIS registers | ||
1035 | */ | ||
1036 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | ||
1037 | req.Base = req.Size = 0; | ||
1038 | req.AccessSpeed = 0; | ||
1039 | if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) { | ||
1040 | cs_error(link->handle, RequestWindow, err); | ||
1041 | goto config_error; | ||
1042 | } | ||
1043 | local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800; | ||
1044 | mem.CardOffset = 0x0; | ||
1045 | mem.Page = 0; | ||
1046 | if ((err = pcmcia_map_mem_page(link->win, &mem))) { | ||
1047 | cs_error(link->handle, MapMemPage, err); | ||
1048 | goto config_error; | ||
1049 | } | ||
1050 | |||
1051 | /* Setup the CCRs; there are no infos in the CIS about the Ethernet | ||
1052 | * part. | ||
1053 | */ | ||
1054 | writeb(0x47, local->dingo_ccr + CISREG_COR); | ||
1055 | ioaddr = link->io.BasePort1; | ||
1056 | writeb(ioaddr & 0xff , local->dingo_ccr + CISREG_IOBASE_0); | ||
1057 | writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1); | ||
1058 | |||
1059 | #if 0 | ||
1060 | { | ||
1061 | u_char tmp; | ||
1062 | printk(KERN_INFO "ECOR:"); | ||
1063 | for (i=0; i < 7; i++) { | ||
1064 | tmp = readb(local->dingo_ccr + i*2); | ||
1065 | printk(" %02x", tmp); | ||
1066 | } | ||
1067 | printk("\n"); | ||
1068 | printk(KERN_INFO "DCOR:"); | ||
1069 | for (i=0; i < 4; i++) { | ||
1070 | tmp = readb(local->dingo_ccr + 0x20 + i*2); | ||
1071 | printk(" %02x", tmp); | ||
1072 | } | ||
1073 | printk("\n"); | ||
1074 | printk(KERN_INFO "SCOR:"); | ||
1075 | for (i=0; i < 10; i++) { | ||
1076 | tmp = readb(local->dingo_ccr + 0x40 + i*2); | ||
1077 | printk(" %02x", tmp); | ||
1078 | } | ||
1079 | printk("\n"); | ||
1080 | } | ||
1081 | #endif | ||
1082 | |||
1083 | writeb(0x01, local->dingo_ccr + 0x20); | ||
1084 | writeb(0x0c, local->dingo_ccr + 0x22); | ||
1085 | writeb(0x00, local->dingo_ccr + 0x24); | ||
1086 | writeb(0x00, local->dingo_ccr + 0x26); | ||
1087 | writeb(0x00, local->dingo_ccr + 0x28); | ||
1088 | } | ||
1089 | |||
1090 | /* The if_port symbol can be set when the module is loaded */ | ||
1091 | local->probe_port=0; | ||
1092 | if (!if_port) { | ||
1093 | local->probe_port = dev->if_port = 1; | ||
1094 | } else if ((if_port >= 1 && if_port <= 2) || | ||
1095 | (local->mohawk && if_port==4)) | ||
1096 | dev->if_port = if_port; | ||
1097 | else | ||
1098 | printk(KNOT_XIRC "invalid if_port requested\n"); | ||
1099 | |||
1100 | /* we can now register the device with the net subsystem */ | ||
1101 | dev->irq = link->irq.AssignedIRQ; | ||
1102 | dev->base_addr = link->io.BasePort1; | ||
1103 | |||
1104 | if (local->dingo) | ||
1105 | do_reset(dev, 1); /* a kludge to make the cem56 work */ | ||
1106 | |||
1107 | link->dev = &local->node; | ||
1108 | link->state &= ~DEV_CONFIG_PENDING; | ||
1109 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
1110 | |||
1111 | if ((err=register_netdev(dev))) { | ||
1112 | printk(KNOT_XIRC "register_netdev() failed\n"); | ||
1113 | link->dev = NULL; | ||
1114 | goto config_error; | ||
1115 | } | ||
1116 | |||
1117 | strcpy(local->node.dev_name, dev->name); | ||
1118 | |||
1119 | /* give some infos about the hardware */ | ||
1120 | printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr", | ||
1121 | dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq); | ||
1122 | for (i = 0; i < 6; i++) | ||
1123 | printk("%c%02X", i?':':' ', dev->dev_addr[i]); | ||
1124 | printk("\n"); | ||
1125 | |||
1126 | return; | ||
1127 | |||
1128 | config_error: | ||
1129 | link->state &= ~DEV_CONFIG_PENDING; | ||
1130 | xirc2ps_release(link); | ||
1131 | return; | ||
1132 | |||
1133 | cis_error: | ||
1134 | printk(KNOT_XIRC "unable to parse CIS\n"); | ||
1135 | failure: | ||
1136 | link->state &= ~DEV_CONFIG_PENDING; | ||
1137 | } /* xirc2ps_config */ | ||
1138 | |||
1139 | /**************** | ||
1140 | * After a card is removed, xirc2ps_release() will unregister the net | ||
1141 | * device, and release the PCMCIA configuration. If the device is | ||
1142 | * still open, this will be postponed until it is closed. | ||
1143 | */ | ||
1144 | static void | ||
1145 | xirc2ps_release(dev_link_t *link) | ||
1146 | { | ||
1147 | |||
1148 | DEBUG(0, "release(0x%p)\n", link); | ||
1149 | |||
1150 | if (link->win) { | ||
1151 | struct net_device *dev = link->priv; | ||
1152 | local_info_t *local = netdev_priv(dev); | ||
1153 | if (local->dingo) | ||
1154 | iounmap(local->dingo_ccr - 0x0800); | ||
1155 | pcmcia_release_window(link->win); | ||
1156 | } | ||
1157 | pcmcia_release_configuration(link->handle); | ||
1158 | pcmcia_release_io(link->handle, &link->io); | ||
1159 | pcmcia_release_irq(link->handle, &link->irq); | ||
1160 | link->state &= ~DEV_CONFIG; | ||
1161 | |||
1162 | } /* xirc2ps_release */ | ||
1163 | |||
1164 | /*====================================================================*/ | ||
1165 | |||
1166 | /**************** | ||
1167 | * The card status event handler. Mostly, this schedules other | ||
1168 | * stuff to run after an event is received. A CARD_REMOVAL event | ||
1169 | * also sets some flags to discourage the net drivers from trying | ||
1170 | * to talk to the card any more. | ||
1171 | * | ||
1172 | * When a CARD_REMOVAL event is received, we immediately set a flag | ||
1173 | * to block future accesses to this device. All the functions that | ||
1174 | * actually access the device should check this flag to make sure | ||
1175 | * the card is still present. | ||
1176 | */ | ||
1177 | |||
1178 | static int | ||
1179 | xirc2ps_event(event_t event, int priority, | ||
1180 | event_callback_args_t * args) | ||
1181 | { | ||
1182 | dev_link_t *link = args->client_data; | ||
1183 | struct net_device *dev = link->priv; | ||
1184 | |||
1185 | DEBUG(0, "event(%d)\n", (int)event); | ||
1186 | |||
1187 | switch (event) { | ||
1188 | case CS_EVENT_REGISTRATION_COMPLETE: | ||
1189 | DEBUG(0, "registration complete\n"); | ||
1190 | break; | ||
1191 | case CS_EVENT_CARD_REMOVAL: | ||
1192 | link->state &= ~DEV_PRESENT; | ||
1193 | if (link->state & DEV_CONFIG) | ||
1194 | netif_device_detach(dev); | ||
1195 | break; | ||
1196 | case CS_EVENT_CARD_INSERTION: | ||
1197 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
1198 | xirc2ps_config(link); | ||
1199 | break; | ||
1200 | case CS_EVENT_PM_SUSPEND: | ||
1201 | link->state |= DEV_SUSPEND; | ||
1202 | /* Fall through... */ | ||
1203 | case CS_EVENT_RESET_PHYSICAL: | ||
1204 | if (link->state & DEV_CONFIG) { | ||
1205 | if (link->open) { | ||
1206 | netif_device_detach(dev); | ||
1207 | do_powerdown(dev); | ||
1208 | } | ||
1209 | pcmcia_release_configuration(link->handle); | ||
1210 | } | ||
1211 | break; | ||
1212 | case CS_EVENT_PM_RESUME: | ||
1213 | link->state &= ~DEV_SUSPEND; | ||
1214 | /* Fall through... */ | ||
1215 | case CS_EVENT_CARD_RESET: | ||
1216 | if (link->state & DEV_CONFIG) { | ||
1217 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1218 | if (link->open) { | ||
1219 | do_reset(dev,1); | ||
1220 | netif_device_attach(dev); | ||
1221 | } | ||
1222 | } | ||
1223 | break; | ||
1224 | } | ||
1225 | return 0; | ||
1226 | } /* xirc2ps_event */ | ||
1227 | |||
1228 | /*====================================================================*/ | ||
1229 | |||
1230 | /**************** | ||
1231 | * This is the Interrupt service route. | ||
1232 | */ | ||
1233 | static irqreturn_t | ||
1234 | xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
1235 | { | ||
1236 | struct net_device *dev = (struct net_device *)dev_id; | ||
1237 | local_info_t *lp = netdev_priv(dev); | ||
1238 | kio_addr_t ioaddr; | ||
1239 | u_char saved_page; | ||
1240 | unsigned bytes_rcvd; | ||
1241 | unsigned int_status, eth_status, rx_status, tx_status; | ||
1242 | unsigned rsr, pktlen; | ||
1243 | ulong start_ticks = jiffies; /* fixme: jiffies rollover every 497 days | ||
1244 | * is this something to worry about? | ||
1245 | * -- on a laptop? | ||
1246 | */ | ||
1247 | |||
1248 | if (!netif_device_present(dev)) | ||
1249 | return IRQ_HANDLED; | ||
1250 | |||
1251 | ioaddr = dev->base_addr; | ||
1252 | if (lp->mohawk) { /* must disable the interrupt */ | ||
1253 | PutByte(XIRCREG_CR, 0); | ||
1254 | } | ||
1255 | |||
1256 | DEBUG(6, "%s: interrupt %d at %#x.\n", dev->name, irq, ioaddr); | ||
1257 | |||
1258 | saved_page = GetByte(XIRCREG_PR); | ||
1259 | /* Read the ISR to see whats the cause for the interrupt. | ||
1260 | * This also clears the interrupt flags on CE2 cards | ||
1261 | */ | ||
1262 | int_status = GetByte(XIRCREG_ISR); | ||
1263 | bytes_rcvd = 0; | ||
1264 | loop_entry: | ||
1265 | if (int_status == 0xff) { /* card may be ejected */ | ||
1266 | DEBUG(3, "%s: interrupt %d for dead card\n", dev->name, irq); | ||
1267 | goto leave; | ||
1268 | } | ||
1269 | eth_status = GetByte(XIRCREG_ESR); | ||
1270 | |||
1271 | SelectPage(0x40); | ||
1272 | rx_status = GetByte(XIRCREG40_RXST0); | ||
1273 | PutByte(XIRCREG40_RXST0, (~rx_status & 0xff)); | ||
1274 | tx_status = GetByte(XIRCREG40_TXST0); | ||
1275 | tx_status |= GetByte(XIRCREG40_TXST1) << 8; | ||
1276 | PutByte(XIRCREG40_TXST0, 0); | ||
1277 | PutByte(XIRCREG40_TXST1, 0); | ||
1278 | |||
1279 | DEBUG(3, "%s: ISR=%#2.2x ESR=%#2.2x RSR=%#2.2x TSR=%#4.4x\n", | ||
1280 | dev->name, int_status, eth_status, rx_status, tx_status); | ||
1281 | |||
1282 | /***** receive section ******/ | ||
1283 | SelectPage(0); | ||
1284 | while (eth_status & FullPktRcvd) { | ||
1285 | rsr = GetByte(XIRCREG0_RSR); | ||
1286 | if (bytes_rcvd > maxrx_bytes && (rsr & PktRxOk)) { | ||
1287 | /* too many bytes received during this int, drop the rest of the | ||
1288 | * packets */ | ||
1289 | lp->stats.rx_dropped++; | ||
1290 | DEBUG(2, "%s: RX drop, too much done\n", dev->name); | ||
1291 | } else if (rsr & PktRxOk) { | ||
1292 | struct sk_buff *skb; | ||
1293 | |||
1294 | pktlen = GetWord(XIRCREG0_RBC); | ||
1295 | bytes_rcvd += pktlen; | ||
1296 | |||
1297 | DEBUG(5, "rsr=%#02x packet_length=%u\n", rsr, pktlen); | ||
1298 | |||
1299 | skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */ | ||
1300 | if (!skb) { | ||
1301 | printk(KNOT_XIRC "low memory, packet dropped (size=%u)\n", | ||
1302 | pktlen); | ||
1303 | lp->stats.rx_dropped++; | ||
1304 | } else { /* okay get the packet */ | ||
1305 | skb_reserve(skb, 2); | ||
1306 | if (lp->silicon == 0 ) { /* work around a hardware bug */ | ||
1307 | unsigned rhsa; /* receive start address */ | ||
1308 | |||
1309 | SelectPage(5); | ||
1310 | rhsa = GetWord(XIRCREG5_RHSA0); | ||
1311 | SelectPage(0); | ||
1312 | rhsa += 3; /* skip control infos */ | ||
1313 | if (rhsa >= 0x8000) | ||
1314 | rhsa = 0; | ||
1315 | if (rhsa + pktlen > 0x8000) { | ||
1316 | unsigned i; | ||
1317 | u_char *buf = skb_put(skb, pktlen); | ||
1318 | for (i=0; i < pktlen ; i++, rhsa++) { | ||
1319 | buf[i] = GetByte(XIRCREG_EDP); | ||
1320 | if (rhsa == 0x8000) { | ||
1321 | rhsa = 0; | ||
1322 | i--; | ||
1323 | } | ||
1324 | } | ||
1325 | } else { | ||
1326 | insw(ioaddr+XIRCREG_EDP, | ||
1327 | skb_put(skb, pktlen), (pktlen+1)>>1); | ||
1328 | } | ||
1329 | } | ||
1330 | #if 0 | ||
1331 | else if (lp->mohawk) { | ||
1332 | /* To use this 32 bit access we should use | ||
1333 | * a manual optimized loop | ||
1334 | * Also the words are swapped, we can get more | ||
1335 | * performance by using 32 bit access and swapping | ||
1336 | * the words in a register. Will need this for cardbus | ||
1337 | * | ||
1338 | * Note: don't forget to change the ALLOC_SKB to .. +3 | ||
1339 | */ | ||
1340 | unsigned i; | ||
1341 | u_long *p = skb_put(skb, pktlen); | ||
1342 | register u_long a; | ||
1343 | kio_addr_t edpreg = ioaddr+XIRCREG_EDP-2; | ||
1344 | for (i=0; i < len ; i += 4, p++) { | ||
1345 | a = inl(edpreg); | ||
1346 | __asm__("rorl $16,%0\n\t" | ||
1347 | :"=q" (a) | ||
1348 | : "0" (a)); | ||
1349 | *p = a; | ||
1350 | } | ||
1351 | } | ||
1352 | #endif | ||
1353 | else { | ||
1354 | insw(ioaddr+XIRCREG_EDP, skb_put(skb, pktlen), | ||
1355 | (pktlen+1)>>1); | ||
1356 | } | ||
1357 | skb->protocol = eth_type_trans(skb, dev); | ||
1358 | skb->dev = dev; | ||
1359 | netif_rx(skb); | ||
1360 | dev->last_rx = jiffies; | ||
1361 | lp->stats.rx_packets++; | ||
1362 | lp->stats.rx_bytes += pktlen; | ||
1363 | if (!(rsr & PhyPkt)) | ||
1364 | lp->stats.multicast++; | ||
1365 | } | ||
1366 | } else { /* bad packet */ | ||
1367 | DEBUG(5, "rsr=%#02x\n", rsr); | ||
1368 | } | ||
1369 | if (rsr & PktTooLong) { | ||
1370 | lp->stats.rx_frame_errors++; | ||
1371 | DEBUG(3, "%s: Packet too long\n", dev->name); | ||
1372 | } | ||
1373 | if (rsr & CRCErr) { | ||
1374 | lp->stats.rx_crc_errors++; | ||
1375 | DEBUG(3, "%s: CRC error\n", dev->name); | ||
1376 | } | ||
1377 | if (rsr & AlignErr) { | ||
1378 | lp->stats.rx_fifo_errors++; /* okay ? */ | ||
1379 | DEBUG(3, "%s: Alignment error\n", dev->name); | ||
1380 | } | ||
1381 | |||
1382 | /* clear the received/dropped/error packet */ | ||
1383 | PutWord(XIRCREG0_DO, 0x8000); /* issue cmd: skip_rx_packet */ | ||
1384 | |||
1385 | /* get the new ethernet status */ | ||
1386 | eth_status = GetByte(XIRCREG_ESR); | ||
1387 | } | ||
1388 | if (rx_status & 0x10) { /* Receive overrun */ | ||
1389 | lp->stats.rx_over_errors++; | ||
1390 | PutByte(XIRCREG_CR, ClearRxOvrun); | ||
1391 | DEBUG(3, "receive overrun cleared\n"); | ||
1392 | } | ||
1393 | |||
1394 | /***** transmit section ******/ | ||
1395 | if (int_status & PktTxed) { | ||
1396 | unsigned n, nn; | ||
1397 | |||
1398 | n = lp->last_ptr_value; | ||
1399 | nn = GetByte(XIRCREG0_PTR); | ||
1400 | lp->last_ptr_value = nn; | ||
1401 | if (nn < n) /* rollover */ | ||
1402 | lp->stats.tx_packets += 256 - n; | ||
1403 | else if (n == nn) { /* happens sometimes - don't know why */ | ||
1404 | DEBUG(0, "PTR not changed?\n"); | ||
1405 | } else | ||
1406 | lp->stats.tx_packets += lp->last_ptr_value - n; | ||
1407 | netif_wake_queue(dev); | ||
1408 | } | ||
1409 | if (tx_status & 0x0002) { /* Execessive collissions */ | ||
1410 | DEBUG(0, "tx restarted due to execssive collissions\n"); | ||
1411 | PutByte(XIRCREG_CR, RestartTx); /* restart transmitter process */ | ||
1412 | } | ||
1413 | if (tx_status & 0x0040) | ||
1414 | lp->stats.tx_aborted_errors++; | ||
1415 | |||
1416 | /* recalculate our work chunk so that we limit the duration of this | ||
1417 | * ISR to about 1/10 of a second. | ||
1418 | * Calculate only if we received a reasonable amount of bytes. | ||
1419 | */ | ||
1420 | if (bytes_rcvd > 1000) { | ||
1421 | u_long duration = jiffies - start_ticks; | ||
1422 | |||
1423 | if (duration >= HZ/10) { /* if more than about 1/10 second */ | ||
1424 | maxrx_bytes = (bytes_rcvd * (HZ/10)) / duration; | ||
1425 | if (maxrx_bytes < 2000) | ||
1426 | maxrx_bytes = 2000; | ||
1427 | else if (maxrx_bytes > 22000) | ||
1428 | maxrx_bytes = 22000; | ||
1429 | DEBUG(1, "set maxrx=%u (rcvd=%u ticks=%lu)\n", | ||
1430 | maxrx_bytes, bytes_rcvd, duration); | ||
1431 | } else if (!duration && maxrx_bytes < 22000) { | ||
1432 | /* now much faster */ | ||
1433 | maxrx_bytes += 2000; | ||
1434 | if (maxrx_bytes > 22000) | ||
1435 | maxrx_bytes = 22000; | ||
1436 | DEBUG(1, "set maxrx=%u\n", maxrx_bytes); | ||
1437 | } | ||
1438 | } | ||
1439 | |||
1440 | leave: | ||
1441 | if (lockup_hack) { | ||
1442 | if (int_status != 0xff && (int_status = GetByte(XIRCREG_ISR)) != 0) | ||
1443 | goto loop_entry; | ||
1444 | } | ||
1445 | SelectPage(saved_page); | ||
1446 | PutByte(XIRCREG_CR, EnableIntr); /* re-enable interrupts */ | ||
1447 | /* Instead of dropping packets during a receive, we could | ||
1448 | * force an interrupt with this command: | ||
1449 | * PutByte(XIRCREG_CR, EnableIntr|ForceIntr); | ||
1450 | */ | ||
1451 | return IRQ_HANDLED; | ||
1452 | } /* xirc2ps_interrupt */ | ||
1453 | |||
1454 | /*====================================================================*/ | ||
1455 | |||
1456 | static void | ||
1457 | do_tx_timeout(struct net_device *dev) | ||
1458 | { | ||
1459 | local_info_t *lp = netdev_priv(dev); | ||
1460 | printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); | ||
1461 | lp->stats.tx_errors++; | ||
1462 | /* reset the card */ | ||
1463 | do_reset(dev,1); | ||
1464 | dev->trans_start = jiffies; | ||
1465 | netif_wake_queue(dev); | ||
1466 | } | ||
1467 | |||
1468 | static int | ||
1469 | do_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
1470 | { | ||
1471 | local_info_t *lp = netdev_priv(dev); | ||
1472 | kio_addr_t ioaddr = dev->base_addr; | ||
1473 | int okay; | ||
1474 | unsigned freespace; | ||
1475 | unsigned pktlen = skb? skb->len : 0; | ||
1476 | |||
1477 | DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n", | ||
1478 | skb, dev, pktlen); | ||
1479 | |||
1480 | |||
1481 | /* adjust the packet length to min. required | ||
1482 | * and hope that the buffer is large enough | ||
1483 | * to provide some random data. | ||
1484 | * fixme: For Mohawk we can change this by sending | ||
1485 | * a larger packetlen than we actually have; the chip will | ||
1486 | * pad this in his buffer with random bytes | ||
1487 | */ | ||
1488 | if (pktlen < ETH_ZLEN) | ||
1489 | { | ||
1490 | skb = skb_padto(skb, ETH_ZLEN); | ||
1491 | if (skb == NULL) | ||
1492 | return 0; | ||
1493 | pktlen = ETH_ZLEN; | ||
1494 | } | ||
1495 | |||
1496 | netif_stop_queue(dev); | ||
1497 | SelectPage(0); | ||
1498 | PutWord(XIRCREG0_TRS, (u_short)pktlen+2); | ||
1499 | freespace = GetWord(XIRCREG0_TSO); | ||
1500 | okay = freespace & 0x8000; | ||
1501 | freespace &= 0x7fff; | ||
1502 | /* TRS doesn't work - (indeed it is eliminated with sil-rev 1) */ | ||
1503 | okay = pktlen +2 < freespace; | ||
1504 | DEBUG(2 + (okay ? 2 : 0), "%s: avail. tx space=%u%s\n", | ||
1505 | dev->name, freespace, okay ? " (okay)":" (not enough)"); | ||
1506 | if (!okay) { /* not enough space */ | ||
1507 | return 1; /* upper layer may decide to requeue this packet */ | ||
1508 | } | ||
1509 | /* send the packet */ | ||
1510 | PutWord(XIRCREG_EDP, (u_short)pktlen); | ||
1511 | outsw(ioaddr+XIRCREG_EDP, skb->data, pktlen>>1); | ||
1512 | if (pktlen & 1) | ||
1513 | PutByte(XIRCREG_EDP, skb->data[pktlen-1]); | ||
1514 | |||
1515 | if (lp->mohawk) | ||
1516 | PutByte(XIRCREG_CR, TransmitPacket|EnableIntr); | ||
1517 | |||
1518 | dev_kfree_skb (skb); | ||
1519 | dev->trans_start = jiffies; | ||
1520 | lp->stats.tx_bytes += pktlen; | ||
1521 | netif_start_queue(dev); | ||
1522 | return 0; | ||
1523 | } | ||
1524 | |||
1525 | static struct net_device_stats * | ||
1526 | do_get_stats(struct net_device *dev) | ||
1527 | { | ||
1528 | local_info_t *lp = netdev_priv(dev); | ||
1529 | |||
1530 | /* lp->stats.rx_missed_errors = GetByte(?) */ | ||
1531 | return &lp->stats; | ||
1532 | } | ||
1533 | |||
1534 | /**************** | ||
1535 | * Set all addresses: This first one is the individual address, | ||
1536 | * the next 9 addresses are taken from the multicast list and | ||
1537 | * the rest is filled with the individual address. | ||
1538 | */ | ||
1539 | static void | ||
1540 | set_addresses(struct net_device *dev) | ||
1541 | { | ||
1542 | kio_addr_t ioaddr = dev->base_addr; | ||
1543 | local_info_t *lp = netdev_priv(dev); | ||
1544 | struct dev_mc_list *dmi = dev->mc_list; | ||
1545 | char *addr; | ||
1546 | int i,j,k,n; | ||
1547 | |||
1548 | SelectPage(k=0x50); | ||
1549 | for (i=0,j=8,n=0; ; i++, j++) { | ||
1550 | if (i > 5) { | ||
1551 | if (++n > 9) | ||
1552 | break; | ||
1553 | i = 0; | ||
1554 | } | ||
1555 | if (j > 15) { | ||
1556 | j = 8; | ||
1557 | k++; | ||
1558 | SelectPage(k); | ||
1559 | } | ||
1560 | |||
1561 | if (n && n <= dev->mc_count && dmi) { | ||
1562 | addr = dmi->dmi_addr; | ||
1563 | dmi = dmi->next; | ||
1564 | } else | ||
1565 | addr = dev->dev_addr; | ||
1566 | |||
1567 | if (lp->mohawk) | ||
1568 | PutByte(j, addr[5-i]); | ||
1569 | else | ||
1570 | PutByte(j, addr[i]); | ||
1571 | } | ||
1572 | SelectPage(0); | ||
1573 | } | ||
1574 | |||
1575 | /**************** | ||
1576 | * Set or clear the multicast filter for this adaptor. | ||
1577 | * We can filter up to 9 addresses, if more are requested we set | ||
1578 | * multicast promiscuous mode. | ||
1579 | */ | ||
1580 | |||
1581 | static void | ||
1582 | set_multicast_list(struct net_device *dev) | ||
1583 | { | ||
1584 | kio_addr_t ioaddr = dev->base_addr; | ||
1585 | |||
1586 | SelectPage(0x42); | ||
1587 | if (dev->flags & IFF_PROMISC) { /* snoop */ | ||
1588 | PutByte(XIRCREG42_SWC1, 0x06); /* set MPE and PME */ | ||
1589 | } else if (dev->mc_count > 9 || (dev->flags & IFF_ALLMULTI)) { | ||
1590 | PutByte(XIRCREG42_SWC1, 0x06); /* set MPE */ | ||
1591 | } else if (dev->mc_count) { | ||
1592 | /* the chip can filter 9 addresses perfectly */ | ||
1593 | PutByte(XIRCREG42_SWC1, 0x00); | ||
1594 | SelectPage(0x40); | ||
1595 | PutByte(XIRCREG40_CMD0, Offline); | ||
1596 | set_addresses(dev); | ||
1597 | SelectPage(0x40); | ||
1598 | PutByte(XIRCREG40_CMD0, EnableRecv | Online); | ||
1599 | } else { /* standard usage */ | ||
1600 | PutByte(XIRCREG42_SWC1, 0x00); | ||
1601 | } | ||
1602 | SelectPage(0); | ||
1603 | } | ||
1604 | |||
1605 | static int | ||
1606 | do_config(struct net_device *dev, struct ifmap *map) | ||
1607 | { | ||
1608 | local_info_t *local = netdev_priv(dev); | ||
1609 | |||
1610 | DEBUG(0, "do_config(%p)\n", dev); | ||
1611 | if (map->port != 255 && map->port != dev->if_port) { | ||
1612 | if (map->port > 4) | ||
1613 | return -EINVAL; | ||
1614 | if (!map->port) { | ||
1615 | local->probe_port = 1; | ||
1616 | dev->if_port = 1; | ||
1617 | } else { | ||
1618 | local->probe_port = 0; | ||
1619 | dev->if_port = map->port; | ||
1620 | } | ||
1621 | printk(KERN_INFO "%s: switching to %s port\n", | ||
1622 | dev->name, if_names[dev->if_port]); | ||
1623 | do_reset(dev,1); /* not the fine way :-) */ | ||
1624 | } | ||
1625 | return 0; | ||
1626 | } | ||
1627 | |||
1628 | /**************** | ||
1629 | * Open the driver | ||
1630 | */ | ||
1631 | static int | ||
1632 | do_open(struct net_device *dev) | ||
1633 | { | ||
1634 | local_info_t *lp = netdev_priv(dev); | ||
1635 | dev_link_t *link = &lp->link; | ||
1636 | |||
1637 | DEBUG(0, "do_open(%p)\n", dev); | ||
1638 | |||
1639 | /* Check that the PCMCIA card is still here. */ | ||
1640 | /* Physical device present signature. */ | ||
1641 | if (!DEV_OK(link)) | ||
1642 | return -ENODEV; | ||
1643 | |||
1644 | /* okay */ | ||
1645 | link->open++; | ||
1646 | |||
1647 | netif_start_queue(dev); | ||
1648 | do_reset(dev,1); | ||
1649 | |||
1650 | return 0; | ||
1651 | } | ||
1652 | |||
1653 | static void netdev_get_drvinfo(struct net_device *dev, | ||
1654 | struct ethtool_drvinfo *info) | ||
1655 | { | ||
1656 | strcpy(info->driver, "xirc2ps_cs"); | ||
1657 | sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr); | ||
1658 | } | ||
1659 | |||
1660 | static struct ethtool_ops netdev_ethtool_ops = { | ||
1661 | .get_drvinfo = netdev_get_drvinfo, | ||
1662 | }; | ||
1663 | |||
1664 | static int | ||
1665 | do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||
1666 | { | ||
1667 | local_info_t *local = netdev_priv(dev); | ||
1668 | kio_addr_t ioaddr = dev->base_addr; | ||
1669 | u16 *data = (u16 *)&rq->ifr_ifru; | ||
1670 | |||
1671 | DEBUG(1, "%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n", | ||
1672 | dev->name, rq->ifr_ifrn.ifrn_name, cmd, | ||
1673 | data[0], data[1], data[2], data[3]); | ||
1674 | |||
1675 | if (!local->mohawk) | ||
1676 | return -EOPNOTSUPP; | ||
1677 | |||
1678 | switch(cmd) { | ||
1679 | case SIOCGMIIPHY: /* Get the address of the PHY in use. */ | ||
1680 | data[0] = 0; /* we have only this address */ | ||
1681 | /* fall trough */ | ||
1682 | case SIOCGMIIREG: /* Read the specified MII register. */ | ||
1683 | data[3] = mii_rd(ioaddr, data[0] & 0x1f, data[1] & 0x1f); | ||
1684 | break; | ||
1685 | case SIOCSMIIREG: /* Write the specified MII register */ | ||
1686 | if (!capable(CAP_NET_ADMIN)) | ||
1687 | return -EPERM; | ||
1688 | mii_wr(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2], 16); | ||
1689 | break; | ||
1690 | default: | ||
1691 | return -EOPNOTSUPP; | ||
1692 | } | ||
1693 | return 0; | ||
1694 | } | ||
1695 | |||
1696 | static void | ||
1697 | hardreset(struct net_device *dev) | ||
1698 | { | ||
1699 | local_info_t *local = netdev_priv(dev); | ||
1700 | kio_addr_t ioaddr = dev->base_addr; | ||
1701 | |||
1702 | SelectPage(4); | ||
1703 | udelay(1); | ||
1704 | PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ | ||
1705 | msleep(40); /* wait 40 msec */ | ||
1706 | if (local->mohawk) | ||
1707 | PutByte(XIRCREG4_GPR1, 1); /* set bit 0: power up */ | ||
1708 | else | ||
1709 | PutByte(XIRCREG4_GPR1, 1 | 4); /* set bit 0: power up, bit 2: AIC */ | ||
1710 | msleep(20); /* wait 20 msec */ | ||
1711 | } | ||
1712 | |||
1713 | static void | ||
1714 | do_reset(struct net_device *dev, int full) | ||
1715 | { | ||
1716 | local_info_t *local = netdev_priv(dev); | ||
1717 | kio_addr_t ioaddr = dev->base_addr; | ||
1718 | unsigned value; | ||
1719 | |||
1720 | DEBUG(0, "%s: do_reset(%p,%d)\n", dev? dev->name:"eth?", dev, full); | ||
1721 | |||
1722 | hardreset(dev); | ||
1723 | PutByte(XIRCREG_CR, SoftReset); /* set */ | ||
1724 | msleep(20); /* wait 20 msec */ | ||
1725 | PutByte(XIRCREG_CR, 0); /* clear */ | ||
1726 | msleep(40); /* wait 40 msec */ | ||
1727 | if (local->mohawk) { | ||
1728 | SelectPage(4); | ||
1729 | /* set pin GP1 and GP2 to output (0x0c) | ||
1730 | * set GP1 to low to power up the ML6692 (0x00) | ||
1731 | * set GP2 to high to power up the 10Mhz chip (0x02) | ||
1732 | */ | ||
1733 | PutByte(XIRCREG4_GPR0, 0x0e); | ||
1734 | } | ||
1735 | |||
1736 | /* give the circuits some time to power up */ | ||
1737 | msleep(500); /* about 500ms */ | ||
1738 | |||
1739 | local->last_ptr_value = 0; | ||
1740 | local->silicon = local->mohawk ? (GetByte(XIRCREG4_BOV) & 0x70) >> 4 | ||
1741 | : (GetByte(XIRCREG4_BOV) & 0x30) >> 4; | ||
1742 | |||
1743 | if (local->probe_port) { | ||
1744 | if (!local->mohawk) { | ||
1745 | SelectPage(4); | ||
1746 | PutByte(XIRCREG4_GPR0, 4); | ||
1747 | local->probe_port = 0; | ||
1748 | } | ||
1749 | } else if (dev->if_port == 2) { /* enable 10Base2 */ | ||
1750 | SelectPage(0x42); | ||
1751 | PutByte(XIRCREG42_SWC1, 0xC0); | ||
1752 | } else { /* enable 10BaseT */ | ||
1753 | SelectPage(0x42); | ||
1754 | PutByte(XIRCREG42_SWC1, 0x80); | ||
1755 | } | ||
1756 | msleep(40); /* wait 40 msec to let it complete */ | ||
1757 | |||
1758 | #ifdef PCMCIA_DEBUG | ||
1759 | if (pc_debug) { | ||
1760 | SelectPage(0); | ||
1761 | value = GetByte(XIRCREG_ESR); /* read the ESR */ | ||
1762 | printk(KERN_DEBUG "%s: ESR is: %#02x\n", dev->name, value); | ||
1763 | } | ||
1764 | #endif | ||
1765 | |||
1766 | /* setup the ECR */ | ||
1767 | SelectPage(1); | ||
1768 | PutByte(XIRCREG1_IMR0, 0xff); /* allow all ints */ | ||
1769 | PutByte(XIRCREG1_IMR1, 1 ); /* and Set TxUnderrunDetect */ | ||
1770 | value = GetByte(XIRCREG1_ECR); | ||
1771 | #if 0 | ||
1772 | if (local->mohawk) | ||
1773 | value |= DisableLinkPulse; | ||
1774 | PutByte(XIRCREG1_ECR, value); | ||
1775 | #endif | ||
1776 | DEBUG(0, "%s: ECR is: %#02x\n", dev->name, value); | ||
1777 | |||
1778 | SelectPage(0x42); | ||
1779 | PutByte(XIRCREG42_SWC0, 0x20); /* disable source insertion */ | ||
1780 | |||
1781 | if (local->silicon != 1) { | ||
1782 | /* set the local memory dividing line. | ||
1783 | * The comments in the sample code say that this is only | ||
1784 | * settable with the scipper version 2 which is revision 0. | ||
1785 | * Always for CE3 cards | ||
1786 | */ | ||
1787 | SelectPage(2); | ||
1788 | PutWord(XIRCREG2_RBS, 0x2000); | ||
1789 | } | ||
1790 | |||
1791 | if (full) | ||
1792 | set_addresses(dev); | ||
1793 | |||
1794 | /* Hardware workaround: | ||
1795 | * The receive byte pointer after reset is off by 1 so we need | ||
1796 | * to move the offset pointer back to 0. | ||
1797 | */ | ||
1798 | SelectPage(0); | ||
1799 | PutWord(XIRCREG0_DO, 0x2000); /* change offset command, off=0 */ | ||
1800 | |||
1801 | /* setup MAC IMRs and clear status registers */ | ||
1802 | SelectPage(0x40); /* Bit 7 ... bit 0 */ | ||
1803 | PutByte(XIRCREG40_RMASK0, 0xff); /* ROK, RAB, rsv, RO, CRC, AE, PTL, MP */ | ||
1804 | PutByte(XIRCREG40_TMASK0, 0xff); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */ | ||
1805 | PutByte(XIRCREG40_TMASK1, 0xb0); /* rsv, rsv, PTD, EXT, rsv,rsv,rsv, rsv*/ | ||
1806 | PutByte(XIRCREG40_RXST0, 0x00); /* ROK, RAB, REN, RO, CRC, AE, PTL, MP */ | ||
1807 | PutByte(XIRCREG40_TXST0, 0x00); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */ | ||
1808 | PutByte(XIRCREG40_TXST1, 0x00); /* TEN, rsv, PTD, EXT, retry_counter:4 */ | ||
1809 | |||
1810 | if (full && local->mohawk && init_mii(dev)) { | ||
1811 | if (dev->if_port == 4 || local->dingo || local->new_mii) { | ||
1812 | printk(KERN_INFO "%s: MII selected\n", dev->name); | ||
1813 | SelectPage(2); | ||
1814 | PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08); | ||
1815 | msleep(20); | ||
1816 | } else { | ||
1817 | printk(KERN_INFO "%s: MII detected; using 10mbs\n", | ||
1818 | dev->name); | ||
1819 | SelectPage(0x42); | ||
1820 | if (dev->if_port == 2) /* enable 10Base2 */ | ||
1821 | PutByte(XIRCREG42_SWC1, 0xC0); | ||
1822 | else /* enable 10BaseT */ | ||
1823 | PutByte(XIRCREG42_SWC1, 0x80); | ||
1824 | msleep(40); /* wait 40 msec to let it complete */ | ||
1825 | } | ||
1826 | if (full_duplex) | ||
1827 | PutByte(XIRCREG1_ECR, GetByte(XIRCREG1_ECR | FullDuplex)); | ||
1828 | } else { /* No MII */ | ||
1829 | SelectPage(0); | ||
1830 | value = GetByte(XIRCREG_ESR); /* read the ESR */ | ||
1831 | dev->if_port = (value & MediaSelect) ? 1 : 2; | ||
1832 | } | ||
1833 | |||
1834 | /* configure the LEDs */ | ||
1835 | SelectPage(2); | ||
1836 | if (dev->if_port == 1 || dev->if_port == 4) /* TP: Link and Activity */ | ||
1837 | PutByte(XIRCREG2_LED, 0x3b); | ||
1838 | else /* Coax: Not-Collision and Activity */ | ||
1839 | PutByte(XIRCREG2_LED, 0x3a); | ||
1840 | |||
1841 | if (local->dingo) | ||
1842 | PutByte(0x0b, 0x04); /* 100 Mbit LED */ | ||
1843 | |||
1844 | /* enable receiver and put the mac online */ | ||
1845 | if (full) { | ||
1846 | SelectPage(0x40); | ||
1847 | PutByte(XIRCREG40_CMD0, EnableRecv | Online); | ||
1848 | } | ||
1849 | |||
1850 | /* setup Ethernet IMR and enable interrupts */ | ||
1851 | SelectPage(1); | ||
1852 | PutByte(XIRCREG1_IMR0, 0xff); | ||
1853 | udelay(1); | ||
1854 | SelectPage(0); | ||
1855 | PutByte(XIRCREG_CR, EnableIntr); | ||
1856 | if (local->modem && !local->dingo) { /* do some magic */ | ||
1857 | if (!(GetByte(0x10) & 0x01)) | ||
1858 | PutByte(0x10, 0x11); /* unmask master-int bit */ | ||
1859 | } | ||
1860 | |||
1861 | if (full) | ||
1862 | printk(KERN_INFO "%s: media %s, silicon revision %d\n", | ||
1863 | dev->name, if_names[dev->if_port], local->silicon); | ||
1864 | /* We should switch back to page 0 to avoid a bug in revision 0 | ||
1865 | * where regs with offset below 8 can't be read after an access | ||
1866 | * to the MAC registers */ | ||
1867 | SelectPage(0); | ||
1868 | } | ||
1869 | |||
1870 | /**************** | ||
1871 | * Initialize the Media-Independent-Interface | ||
1872 | * Returns: True if we have a good MII | ||
1873 | */ | ||
1874 | static int | ||
1875 | init_mii(struct net_device *dev) | ||
1876 | { | ||
1877 | local_info_t *local = netdev_priv(dev); | ||
1878 | kio_addr_t ioaddr = dev->base_addr; | ||
1879 | unsigned control, status, linkpartner; | ||
1880 | int i; | ||
1881 | |||
1882 | if (if_port == 4 || if_port == 1) { /* force 100BaseT or 10BaseT */ | ||
1883 | dev->if_port = if_port; | ||
1884 | local->probe_port = 0; | ||
1885 | return 1; | ||
1886 | } | ||
1887 | |||
1888 | status = mii_rd(ioaddr, 0, 1); | ||
1889 | if ((status & 0xff00) != 0x7800) | ||
1890 | return 0; /* No MII */ | ||
1891 | |||
1892 | local->new_mii = (mii_rd(ioaddr, 0, 2) != 0xffff); | ||
1893 | |||
1894 | if (local->probe_port) | ||
1895 | control = 0x1000; /* auto neg */ | ||
1896 | else if (dev->if_port == 4) | ||
1897 | control = 0x2000; /* no auto neg, 100mbs mode */ | ||
1898 | else | ||
1899 | control = 0x0000; /* no auto neg, 10mbs mode */ | ||
1900 | mii_wr(ioaddr, 0, 0, control, 16); | ||
1901 | udelay(100); | ||
1902 | control = mii_rd(ioaddr, 0, 0); | ||
1903 | |||
1904 | if (control & 0x0400) { | ||
1905 | printk(KERN_NOTICE "%s can't take PHY out of isolation mode\n", | ||
1906 | dev->name); | ||
1907 | local->probe_port = 0; | ||
1908 | return 0; | ||
1909 | } | ||
1910 | |||
1911 | if (local->probe_port) { | ||
1912 | /* according to the DP83840A specs the auto negotiation process | ||
1913 | * may take up to 3.5 sec, so we use this also for our ML6692 | ||
1914 | * Fixme: Better to use a timer here! | ||
1915 | */ | ||
1916 | for (i=0; i < 35; i++) { | ||
1917 | msleep(100); /* wait 100 msec */ | ||
1918 | status = mii_rd(ioaddr, 0, 1); | ||
1919 | if ((status & 0x0020) && (status & 0x0004)) | ||
1920 | break; | ||
1921 | } | ||
1922 | |||
1923 | if (!(status & 0x0020)) { | ||
1924 | printk(KERN_INFO "%s: autonegotiation failed;" | ||
1925 | " using 10mbs\n", dev->name); | ||
1926 | if (!local->new_mii) { | ||
1927 | control = 0x0000; | ||
1928 | mii_wr(ioaddr, 0, 0, control, 16); | ||
1929 | udelay(100); | ||
1930 | SelectPage(0); | ||
1931 | dev->if_port = (GetByte(XIRCREG_ESR) & MediaSelect) ? 1 : 2; | ||
1932 | } | ||
1933 | } else { | ||
1934 | linkpartner = mii_rd(ioaddr, 0, 5); | ||
1935 | printk(KERN_INFO "%s: MII link partner: %04x\n", | ||
1936 | dev->name, linkpartner); | ||
1937 | if (linkpartner & 0x0080) { | ||
1938 | dev->if_port = 4; | ||
1939 | } else | ||
1940 | dev->if_port = 1; | ||
1941 | } | ||
1942 | } | ||
1943 | |||
1944 | return 1; | ||
1945 | } | ||
1946 | |||
1947 | static void | ||
1948 | do_powerdown(struct net_device *dev) | ||
1949 | { | ||
1950 | |||
1951 | kio_addr_t ioaddr = dev->base_addr; | ||
1952 | |||
1953 | DEBUG(0, "do_powerdown(%p)\n", dev); | ||
1954 | |||
1955 | SelectPage(4); | ||
1956 | PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ | ||
1957 | SelectPage(0); | ||
1958 | } | ||
1959 | |||
1960 | static int | ||
1961 | do_stop(struct net_device *dev) | ||
1962 | { | ||
1963 | kio_addr_t ioaddr = dev->base_addr; | ||
1964 | local_info_t *lp = netdev_priv(dev); | ||
1965 | dev_link_t *link = &lp->link; | ||
1966 | |||
1967 | DEBUG(0, "do_stop(%p)\n", dev); | ||
1968 | |||
1969 | if (!link) | ||
1970 | return -ENODEV; | ||
1971 | |||
1972 | netif_stop_queue(dev); | ||
1973 | |||
1974 | SelectPage(0); | ||
1975 | PutByte(XIRCREG_CR, 0); /* disable interrupts */ | ||
1976 | SelectPage(0x01); | ||
1977 | PutByte(XIRCREG1_IMR0, 0x00); /* forbid all ints */ | ||
1978 | SelectPage(4); | ||
1979 | PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ | ||
1980 | SelectPage(0); | ||
1981 | |||
1982 | link->open--; | ||
1983 | return 0; | ||
1984 | } | ||
1985 | |||
1986 | static struct pcmcia_driver xirc2ps_cs_driver = { | ||
1987 | .owner = THIS_MODULE, | ||
1988 | .drv = { | ||
1989 | .name = "xirc2ps_cs", | ||
1990 | }, | ||
1991 | .attach = xirc2ps_attach, | ||
1992 | .detach = xirc2ps_detach, | ||
1993 | }; | ||
1994 | |||
1995 | static int __init | ||
1996 | init_xirc2ps_cs(void) | ||
1997 | { | ||
1998 | return pcmcia_register_driver(&xirc2ps_cs_driver); | ||
1999 | } | ||
2000 | |||
2001 | static void __exit | ||
2002 | exit_xirc2ps_cs(void) | ||
2003 | { | ||
2004 | pcmcia_unregister_driver(&xirc2ps_cs_driver); | ||
2005 | BUG_ON(dev_list != NULL); | ||
2006 | } | ||
2007 | |||
2008 | module_init(init_xirc2ps_cs); | ||
2009 | module_exit(exit_xirc2ps_cs); | ||
2010 | |||
2011 | #ifndef MODULE | ||
2012 | static int __init setup_xirc2ps_cs(char *str) | ||
2013 | { | ||
2014 | /* if_port, full_duplex, do_sound, lockup_hack | ||
2015 | */ | ||
2016 | int ints[10] = { -1 }; | ||
2017 | |||
2018 | str = get_options(str, 9, ints); | ||
2019 | |||
2020 | #define MAYBE_SET(X,Y) if (ints[0] >= Y && ints[Y] != -1) { X = ints[Y]; } | ||
2021 | MAYBE_SET(if_port, 3); | ||
2022 | MAYBE_SET(full_duplex, 4); | ||
2023 | MAYBE_SET(do_sound, 5); | ||
2024 | MAYBE_SET(lockup_hack, 6); | ||
2025 | #undef MAYBE_SET | ||
2026 | |||
2027 | return 0; | ||
2028 | } | ||
2029 | |||
2030 | __setup("xirc2ps_cs=", setup_xirc2ps_cs); | ||
2031 | #endif | ||