diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-07-15 06:18:21 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-08-12 03:21:43 -0400 |
commit | 9e13fbf7af3cb044f365e8df9c0e9277715cfc7c (patch) | |
tree | 9093489bce7301d1d58bdfa7d7142ba9fb83e49a /drivers/net/ethernet/seeq | |
parent | 8862bf1ed60de49550109b7023a0a33eb7db8b3c (diff) |
seeq: Move the SEEQ drivers
Move the drivers that use SEEQ chipset into drivers/net/ethernet/seeq
and make the necessary Kconfig and Makefile changes.
CC: Russell King <linux@arm.linux.org.uk>
CC: Hamish Coleman <hamish@zot.apana.org.au>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/seeq')
-rw-r--r-- | drivers/net/ethernet/seeq/Kconfig | 45 | ||||
-rw-r--r-- | drivers/net/ethernet/seeq/Makefile | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/seeq/ether3.c | 918 | ||||
-rw-r--r-- | drivers/net/ethernet/seeq/ether3.h | 176 | ||||
-rw-r--r-- | drivers/net/ethernet/seeq/seeq8005.c | 752 | ||||
-rw-r--r-- | drivers/net/ethernet/seeq/seeq8005.h | 156 | ||||
-rw-r--r-- | drivers/net/ethernet/seeq/sgiseeq.c | 858 | ||||
-rw-r--r-- | drivers/net/ethernet/seeq/sgiseeq.h | 103 |
8 files changed, 3015 insertions, 0 deletions
diff --git a/drivers/net/ethernet/seeq/Kconfig b/drivers/net/ethernet/seeq/Kconfig new file mode 100644 index 000000000000..02667915b34a --- /dev/null +++ b/drivers/net/ethernet/seeq/Kconfig | |||
@@ -0,0 +1,45 @@ | |||
1 | # | ||
2 | # SEEQ device configuration | ||
3 | # | ||
4 | |||
5 | config NET_VENDOR_SEEQ | ||
6 | bool "SEEQ devices" | ||
7 | depends on (ARM && ARCH_ACORN) || SGI_HAS_SEEQ || EXPERIMENTAL | ||
8 | ---help--- | ||
9 | If you have a network (Ethernet) card belonging to this class, say Y | ||
10 | and read the Ethernet-HOWTO, available from | ||
11 | <http://www.tldp.org/docs.html#howto>. | ||
12 | |||
13 | Note that the answer to this question doesn't directly affect the | ||
14 | kernel: saying N will just cause the configurator to skip all | ||
15 | the questions about SEEQ devices. If you say Y, you will be asked for | ||
16 | your specific card in the following questions. | ||
17 | |||
18 | if NET_VENDOR_SEEQ | ||
19 | |||
20 | config ARM_ETHER3 | ||
21 | tristate "Acorn/ANT Ether3 support" | ||
22 | depends on ARM && ARCH_ACORN | ||
23 | ---help--- | ||
24 | If you have an Acorn system with one of these network cards, you | ||
25 | should say Y to this option if you wish to use it with Linux. | ||
26 | |||
27 | config SEEQ8005 | ||
28 | tristate "SEEQ8005 support (EXPERIMENTAL)" | ||
29 | depends on EXPERIMENTAL | ||
30 | ---help--- | ||
31 | This is a driver for the SEEQ 8005 network (Ethernet) card. If this | ||
32 | is for you, read the Ethernet-HOWTO, available from | ||
33 | <http://www.tldp.org/docs.html#howto>. | ||
34 | |||
35 | To compile this driver as a module, choose M here. The module | ||
36 | will be called seeq8005. | ||
37 | |||
38 | config SGISEEQ | ||
39 | tristate "SGI Seeq ethernet controller support" | ||
40 | depends on SGI_HAS_SEEQ | ||
41 | ---help--- | ||
42 | Say Y here if you have an Seeq based Ethernet network card. This is | ||
43 | used in many Silicon Graphics machines. | ||
44 | |||
45 | endif # NET_VENDOR_SEEQ | ||
diff --git a/drivers/net/ethernet/seeq/Makefile b/drivers/net/ethernet/seeq/Makefile new file mode 100644 index 000000000000..3e258a580c05 --- /dev/null +++ b/drivers/net/ethernet/seeq/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for the SEEQ network device drivers | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_ARM_ETHER3) += ether3.o | ||
6 | obj-$(CONFIG_SEEQ8005) += seeq8005.o | ||
7 | obj-$(CONFIG_SGISEEQ) += sgiseeq.o | ||
diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c new file mode 100644 index 000000000000..44a8746f4014 --- /dev/null +++ b/drivers/net/ethernet/seeq/ether3.c | |||
@@ -0,0 +1,918 @@ | |||
1 | /* | ||
2 | * linux/drivers/acorn/net/ether3.c | ||
3 | * | ||
4 | * Copyright (C) 1995-2000 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * SEEQ nq8005 ethernet driver for Acorn/ANT Ether3 card | ||
11 | * for Acorn machines | ||
12 | * | ||
13 | * By Russell King, with some suggestions from borris@ant.co.uk | ||
14 | * | ||
15 | * Changelog: | ||
16 | * 1.04 RMK 29/02/1996 Won't pass packets that are from our ethernet | ||
17 | * address up to the higher levels - they're | ||
18 | * silently ignored. I/F can now be put into | ||
19 | * multicast mode. Receiver routine optimised. | ||
20 | * 1.05 RMK 30/02/1996 Now claims interrupt at open when part of | ||
21 | * the kernel rather than when a module. | ||
22 | * 1.06 RMK 02/03/1996 Various code cleanups | ||
23 | * 1.07 RMK 13/10/1996 Optimised interrupt routine and transmit | ||
24 | * routines. | ||
25 | * 1.08 RMK 14/10/1996 Fixed problem with too many packets, | ||
26 | * prevented the kernel message about dropped | ||
27 | * packets appearing too many times a second. | ||
28 | * Now does not disable all IRQs, only the IRQ | ||
29 | * used by this card. | ||
30 | * 1.09 RMK 10/11/1996 Only enables TX irq when buffer space is low, | ||
31 | * but we still service the TX queue if we get a | ||
32 | * RX interrupt. | ||
33 | * 1.10 RMK 15/07/1997 Fixed autoprobing of NQ8004. | ||
34 | * 1.11 RMK 16/11/1997 Fixed autoprobing of NQ8005A. | ||
35 | * 1.12 RMK 31/12/1997 Removed reference to dev_tint for Linux 2.1. | ||
36 | * RMK 27/06/1998 Changed asm/delay.h to linux/delay.h. | ||
37 | * 1.13 RMK 29/06/1998 Fixed problem with transmission of packets. | ||
38 | * Chip seems to have a bug in, whereby if the | ||
39 | * packet starts two bytes from the end of the | ||
40 | * buffer, it corrupts the receiver chain, and | ||
41 | * never updates the transmit status correctly. | ||
42 | * 1.14 RMK 07/01/1998 Added initial code for ETHERB addressing. | ||
43 | * 1.15 RMK 30/04/1999 More fixes to the transmit routine for buggy | ||
44 | * hardware. | ||
45 | * 1.16 RMK 10/02/2000 Updated for 2.3.43 | ||
46 | * 1.17 RMK 13/05/2000 Updated for 2.3.99-pre8 | ||
47 | */ | ||
48 | |||
49 | #include <linux/module.h> | ||
50 | #include <linux/kernel.h> | ||
51 | #include <linux/types.h> | ||
52 | #include <linux/fcntl.h> | ||
53 | #include <linux/interrupt.h> | ||
54 | #include <linux/ioport.h> | ||
55 | #include <linux/in.h> | ||
56 | #include <linux/slab.h> | ||
57 | #include <linux/string.h> | ||
58 | #include <linux/errno.h> | ||
59 | #include <linux/netdevice.h> | ||
60 | #include <linux/etherdevice.h> | ||
61 | #include <linux/skbuff.h> | ||
62 | #include <linux/device.h> | ||
63 | #include <linux/init.h> | ||
64 | #include <linux/delay.h> | ||
65 | #include <linux/bitops.h> | ||
66 | |||
67 | #include <asm/system.h> | ||
68 | #include <asm/ecard.h> | ||
69 | #include <asm/io.h> | ||
70 | |||
71 | static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; | ||
72 | |||
73 | #include "ether3.h" | ||
74 | |||
75 | static unsigned int net_debug = NET_DEBUG; | ||
76 | |||
77 | static void ether3_setmulticastlist(struct net_device *dev); | ||
78 | static int ether3_rx(struct net_device *dev, unsigned int maxcnt); | ||
79 | static void ether3_tx(struct net_device *dev); | ||
80 | static int ether3_open (struct net_device *dev); | ||
81 | static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev); | ||
82 | static irqreturn_t ether3_interrupt (int irq, void *dev_id); | ||
83 | static int ether3_close (struct net_device *dev); | ||
84 | static void ether3_setmulticastlist (struct net_device *dev); | ||
85 | static void ether3_timeout(struct net_device *dev); | ||
86 | |||
87 | #define BUS_16 2 | ||
88 | #define BUS_8 1 | ||
89 | #define BUS_UNKNOWN 0 | ||
90 | |||
91 | /* --------------------------------------------------------------------------- */ | ||
92 | |||
93 | typedef enum { | ||
94 | buffer_write, | ||
95 | buffer_read | ||
96 | } buffer_rw_t; | ||
97 | |||
98 | /* | ||
99 | * ether3 read/write. Slow things down a bit... | ||
100 | * The SEEQ8005 doesn't like us writing to its registers | ||
101 | * too quickly. | ||
102 | */ | ||
103 | static inline void ether3_outb(int v, const void __iomem *r) | ||
104 | { | ||
105 | writeb(v, r); | ||
106 | udelay(1); | ||
107 | } | ||
108 | |||
109 | static inline void ether3_outw(int v, const void __iomem *r) | ||
110 | { | ||
111 | writew(v, r); | ||
112 | udelay(1); | ||
113 | } | ||
114 | #define ether3_inb(r) ({ unsigned int __v = readb((r)); udelay(1); __v; }) | ||
115 | #define ether3_inw(r) ({ unsigned int __v = readw((r)); udelay(1); __v; }) | ||
116 | |||
117 | static int | ||
118 | ether3_setbuffer(struct net_device *dev, buffer_rw_t read, int start) | ||
119 | { | ||
120 | int timeout = 1000; | ||
121 | |||
122 | ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); | ||
123 | ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND); | ||
124 | |||
125 | while ((ether3_inw(REG_STATUS) & STAT_FIFOEMPTY) == 0) { | ||
126 | if (!timeout--) { | ||
127 | printk("%s: setbuffer broken\n", dev->name); | ||
128 | priv(dev)->broken = 1; | ||
129 | return 1; | ||
130 | } | ||
131 | udelay(1); | ||
132 | } | ||
133 | |||
134 | if (read == buffer_read) { | ||
135 | ether3_outw(start, REG_DMAADDR); | ||
136 | ether3_outw(priv(dev)->regs.command | CMD_FIFOREAD, REG_COMMAND); | ||
137 | } else { | ||
138 | ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND); | ||
139 | ether3_outw(start, REG_DMAADDR); | ||
140 | } | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * write data to the buffer memory | ||
146 | */ | ||
147 | #define ether3_writebuffer(dev,data,length) \ | ||
148 | writesw(REG_BUFWIN, (data), (length) >> 1) | ||
149 | |||
150 | #define ether3_writeword(dev,data) \ | ||
151 | writew((data), REG_BUFWIN) | ||
152 | |||
153 | #define ether3_writelong(dev,data) { \ | ||
154 | void __iomem *reg_bufwin = REG_BUFWIN; \ | ||
155 | writew((data), reg_bufwin); \ | ||
156 | writew((data) >> 16, reg_bufwin); \ | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * read data from the buffer memory | ||
161 | */ | ||
162 | #define ether3_readbuffer(dev,data,length) \ | ||
163 | readsw(REG_BUFWIN, (data), (length) >> 1) | ||
164 | |||
165 | #define ether3_readword(dev) \ | ||
166 | readw(REG_BUFWIN) | ||
167 | |||
168 | #define ether3_readlong(dev) \ | ||
169 | readw(REG_BUFWIN) | (readw(REG_BUFWIN) << 16) | ||
170 | |||
171 | /* | ||
172 | * Switch LED off... | ||
173 | */ | ||
174 | static void ether3_ledoff(unsigned long data) | ||
175 | { | ||
176 | struct net_device *dev = (struct net_device *)data; | ||
177 | ether3_outw(priv(dev)->regs.config2 |= CFG2_CTRLO, REG_CONFIG2); | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | * switch LED on... | ||
182 | */ | ||
183 | static inline void ether3_ledon(struct net_device *dev) | ||
184 | { | ||
185 | del_timer(&priv(dev)->timer); | ||
186 | priv(dev)->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */ | ||
187 | priv(dev)->timer.data = (unsigned long)dev; | ||
188 | priv(dev)->timer.function = ether3_ledoff; | ||
189 | add_timer(&priv(dev)->timer); | ||
190 | if (priv(dev)->regs.config2 & CFG2_CTRLO) | ||
191 | ether3_outw(priv(dev)->regs.config2 &= ~CFG2_CTRLO, REG_CONFIG2); | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * Read the ethernet address string from the on board rom. | ||
196 | * This is an ascii string!!! | ||
197 | */ | ||
198 | static int __devinit | ||
199 | ether3_addr(char *addr, struct expansion_card *ec) | ||
200 | { | ||
201 | struct in_chunk_dir cd; | ||
202 | char *s; | ||
203 | |||
204 | if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) { | ||
205 | int i; | ||
206 | for (i = 0; i<6; i++) { | ||
207 | addr[i] = simple_strtoul(s + 1, &s, 0x10); | ||
208 | if (*s != (i==5?')' : ':' )) | ||
209 | break; | ||
210 | } | ||
211 | if (i == 6) | ||
212 | return 0; | ||
213 | } | ||
214 | /* I wonder if we should even let the user continue in this case | ||
215 | * - no, it would be better to disable the device | ||
216 | */ | ||
217 | printk(KERN_ERR "ether3: Couldn't read a valid MAC address from card.\n"); | ||
218 | return -ENODEV; | ||
219 | } | ||
220 | |||
221 | /* --------------------------------------------------------------------------- */ | ||
222 | |||
223 | static int __devinit | ||
224 | ether3_ramtest(struct net_device *dev, unsigned char byte) | ||
225 | { | ||
226 | unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL); | ||
227 | int i,ret = 0; | ||
228 | int max_errors = 4; | ||
229 | int bad = -1; | ||
230 | |||
231 | if (!buffer) | ||
232 | return 1; | ||
233 | |||
234 | memset(buffer, byte, RX_END); | ||
235 | ether3_setbuffer(dev, buffer_write, 0); | ||
236 | ether3_writebuffer(dev, buffer, TX_END); | ||
237 | ether3_setbuffer(dev, buffer_write, RX_START); | ||
238 | ether3_writebuffer(dev, buffer + RX_START, RX_LEN); | ||
239 | memset(buffer, byte ^ 0xff, RX_END); | ||
240 | ether3_setbuffer(dev, buffer_read, 0); | ||
241 | ether3_readbuffer(dev, buffer, TX_END); | ||
242 | ether3_setbuffer(dev, buffer_read, RX_START); | ||
243 | ether3_readbuffer(dev, buffer + RX_START, RX_LEN); | ||
244 | |||
245 | for (i = 0; i < RX_END; i++) { | ||
246 | if (buffer[i] != byte) { | ||
247 | if (max_errors > 0 && bad != buffer[i]) { | ||
248 | printk("%s: RAM failed with (%02X instead of %02X) at 0x%04X", | ||
249 | dev->name, buffer[i], byte, i); | ||
250 | ret = 2; | ||
251 | max_errors--; | ||
252 | bad = i; | ||
253 | } | ||
254 | } else { | ||
255 | if (bad != -1) { | ||
256 | if (bad != i - 1) | ||
257 | printk(" - 0x%04X\n", i - 1); | ||
258 | printk("\n"); | ||
259 | bad = -1; | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | if (bad != -1) | ||
264 | printk(" - 0xffff\n"); | ||
265 | kfree(buffer); | ||
266 | |||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | /* ------------------------------------------------------------------------------- */ | ||
271 | |||
272 | static int __devinit ether3_init_2(struct net_device *dev) | ||
273 | { | ||
274 | int i; | ||
275 | |||
276 | priv(dev)->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8; | ||
277 | priv(dev)->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC; | ||
278 | priv(dev)->regs.command = 0; | ||
279 | |||
280 | /* | ||
281 | * Set up our hardware address | ||
282 | */ | ||
283 | ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1); | ||
284 | for (i = 0; i < 6; i++) | ||
285 | ether3_outb(dev->dev_addr[i], REG_BUFWIN); | ||
286 | |||
287 | if (dev->flags & IFF_PROMISC) | ||
288 | priv(dev)->regs.config1 |= CFG1_RECVPROMISC; | ||
289 | else if (dev->flags & IFF_MULTICAST) | ||
290 | priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI; | ||
291 | else | ||
292 | priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD; | ||
293 | |||
294 | /* | ||
295 | * There is a problem with the NQ8005 in that it occasionally loses the | ||
296 | * last two bytes. To get round this problem, we receive the CRC as | ||
297 | * well. That way, if we do lose the last two, then it doesn't matter. | ||
298 | */ | ||
299 | ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1); | ||
300 | ether3_outw((TX_END>>8) - 1, REG_BUFWIN); | ||
301 | ether3_outw(priv(dev)->rx_head, REG_RECVPTR); | ||
302 | ether3_outw(0, REG_TRANSMITPTR); | ||
303 | ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND); | ||
304 | ether3_outw(priv(dev)->regs.config2, REG_CONFIG2); | ||
305 | ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); | ||
306 | ether3_outw(priv(dev)->regs.command, REG_COMMAND); | ||
307 | |||
308 | i = ether3_ramtest(dev, 0x5A); | ||
309 | if(i) | ||
310 | return i; | ||
311 | i = ether3_ramtest(dev, 0x1E); | ||
312 | if(i) | ||
313 | return i; | ||
314 | |||
315 | ether3_setbuffer(dev, buffer_write, 0); | ||
316 | ether3_writelong(dev, 0); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static void | ||
321 | ether3_init_for_open(struct net_device *dev) | ||
322 | { | ||
323 | int i; | ||
324 | |||
325 | /* Reset the chip */ | ||
326 | ether3_outw(CFG2_RESET, REG_CONFIG2); | ||
327 | udelay(4); | ||
328 | |||
329 | priv(dev)->regs.command = 0; | ||
330 | ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND); | ||
331 | while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON)) | ||
332 | barrier(); | ||
333 | |||
334 | ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1); | ||
335 | for (i = 0; i < 6; i++) | ||
336 | ether3_outb(dev->dev_addr[i], REG_BUFWIN); | ||
337 | |||
338 | priv(dev)->tx_head = 0; | ||
339 | priv(dev)->tx_tail = 0; | ||
340 | priv(dev)->regs.config2 |= CFG2_CTRLO; | ||
341 | priv(dev)->rx_head = RX_START; | ||
342 | |||
343 | ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1); | ||
344 | ether3_outw((TX_END>>8) - 1, REG_BUFWIN); | ||
345 | ether3_outw(priv(dev)->rx_head, REG_RECVPTR); | ||
346 | ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND); | ||
347 | ether3_outw(0, REG_TRANSMITPTR); | ||
348 | ether3_outw(priv(dev)->regs.config2, REG_CONFIG2); | ||
349 | ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); | ||
350 | |||
351 | ether3_setbuffer(dev, buffer_write, 0); | ||
352 | ether3_writelong(dev, 0); | ||
353 | |||
354 | priv(dev)->regs.command = CMD_ENINTRX | CMD_ENINTTX; | ||
355 | ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND); | ||
356 | } | ||
357 | |||
358 | static inline int | ||
359 | ether3_probe_bus_8(struct net_device *dev, int val) | ||
360 | { | ||
361 | int write_low, write_high, read_low, read_high; | ||
362 | |||
363 | write_low = val & 255; | ||
364 | write_high = val >> 8; | ||
365 | |||
366 | printk(KERN_DEBUG "ether3_probe: write8 [%02X:%02X]", write_high, write_low); | ||
367 | |||
368 | ether3_outb(write_low, REG_RECVPTR); | ||
369 | ether3_outb(write_high, REG_RECVPTR + 4); | ||
370 | |||
371 | read_low = ether3_inb(REG_RECVPTR); | ||
372 | read_high = ether3_inb(REG_RECVPTR + 4); | ||
373 | |||
374 | printk(", read8 [%02X:%02X]\n", read_high, read_low); | ||
375 | |||
376 | return read_low == write_low && read_high == write_high; | ||
377 | } | ||
378 | |||
379 | static inline int | ||
380 | ether3_probe_bus_16(struct net_device *dev, int val) | ||
381 | { | ||
382 | int read_val; | ||
383 | |||
384 | ether3_outw(val, REG_RECVPTR); | ||
385 | read_val = ether3_inw(REG_RECVPTR); | ||
386 | |||
387 | printk(KERN_DEBUG "ether3_probe: write16 [%04X], read16 [%04X]\n", val, read_val); | ||
388 | |||
389 | return read_val == val; | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * Open/initialize the board. This is called (in the current kernel) | ||
394 | * sometime after booting when the 'ifconfig' program is run. | ||
395 | * | ||
396 | * This routine should set everything up anew at each open, even | ||
397 | * registers that "should" only need to be set once at boot, so that | ||
398 | * there is non-reboot way to recover if something goes wrong. | ||
399 | */ | ||
400 | static int | ||
401 | ether3_open(struct net_device *dev) | ||
402 | { | ||
403 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
404 | printk(KERN_WARNING "%s: invalid ethernet MAC address\n", | ||
405 | dev->name); | ||
406 | return -EINVAL; | ||
407 | } | ||
408 | |||
409 | if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev)) | ||
410 | return -EAGAIN; | ||
411 | |||
412 | ether3_init_for_open(dev); | ||
413 | |||
414 | netif_start_queue(dev); | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * The inverse routine to ether3_open(). | ||
421 | */ | ||
422 | static int | ||
423 | ether3_close(struct net_device *dev) | ||
424 | { | ||
425 | netif_stop_queue(dev); | ||
426 | |||
427 | disable_irq(dev->irq); | ||
428 | |||
429 | ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND); | ||
430 | priv(dev)->regs.command = 0; | ||
431 | while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON)) | ||
432 | barrier(); | ||
433 | ether3_outb(0x80, REG_CONFIG2 + 4); | ||
434 | ether3_outw(0, REG_COMMAND); | ||
435 | |||
436 | free_irq(dev->irq, dev); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | /* | ||
442 | * Set or clear promiscuous/multicast mode filter for this adaptor. | ||
443 | * | ||
444 | * We don't attempt any packet filtering. The card may have a SEEQ 8004 | ||
445 | * in which does not have the other ethernet address registers present... | ||
446 | */ | ||
447 | static void ether3_setmulticastlist(struct net_device *dev) | ||
448 | { | ||
449 | priv(dev)->regs.config1 &= ~CFG1_RECVPROMISC; | ||
450 | |||
451 | if (dev->flags & IFF_PROMISC) { | ||
452 | /* promiscuous mode */ | ||
453 | priv(dev)->regs.config1 |= CFG1_RECVPROMISC; | ||
454 | } else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) { | ||
455 | priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI; | ||
456 | } else | ||
457 | priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD; | ||
458 | |||
459 | ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); | ||
460 | } | ||
461 | |||
462 | static void ether3_timeout(struct net_device *dev) | ||
463 | { | ||
464 | unsigned long flags; | ||
465 | |||
466 | del_timer(&priv(dev)->timer); | ||
467 | |||
468 | local_irq_save(flags); | ||
469 | printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name); | ||
470 | printk(KERN_ERR "%s: state: { status=%04X cfg1=%04X cfg2=%04X }\n", dev->name, | ||
471 | ether3_inw(REG_STATUS), ether3_inw(REG_CONFIG1), ether3_inw(REG_CONFIG2)); | ||
472 | printk(KERN_ERR "%s: { rpr=%04X rea=%04X tpr=%04X }\n", dev->name, | ||
473 | ether3_inw(REG_RECVPTR), ether3_inw(REG_RECVEND), ether3_inw(REG_TRANSMITPTR)); | ||
474 | printk(KERN_ERR "%s: tx head=%X tx tail=%X\n", dev->name, | ||
475 | priv(dev)->tx_head, priv(dev)->tx_tail); | ||
476 | ether3_setbuffer(dev, buffer_read, priv(dev)->tx_tail); | ||
477 | printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev)); | ||
478 | local_irq_restore(flags); | ||
479 | |||
480 | priv(dev)->regs.config2 |= CFG2_CTRLO; | ||
481 | dev->stats.tx_errors += 1; | ||
482 | ether3_outw(priv(dev)->regs.config2, REG_CONFIG2); | ||
483 | priv(dev)->tx_head = priv(dev)->tx_tail = 0; | ||
484 | |||
485 | netif_wake_queue(dev); | ||
486 | } | ||
487 | |||
488 | /* | ||
489 | * Transmit a packet | ||
490 | */ | ||
491 | static int | ||
492 | ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) | ||
493 | { | ||
494 | unsigned long flags; | ||
495 | unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; | ||
496 | unsigned int ptr, next_ptr; | ||
497 | |||
498 | if (priv(dev)->broken) { | ||
499 | dev_kfree_skb(skb); | ||
500 | dev->stats.tx_dropped++; | ||
501 | netif_start_queue(dev); | ||
502 | return NETDEV_TX_OK; | ||
503 | } | ||
504 | |||
505 | length = (length + 1) & ~1; | ||
506 | if (length != skb->len) { | ||
507 | if (skb_padto(skb, length)) | ||
508 | goto out; | ||
509 | } | ||
510 | |||
511 | next_ptr = (priv(dev)->tx_head + 1) & 15; | ||
512 | |||
513 | local_irq_save(flags); | ||
514 | |||
515 | if (priv(dev)->tx_tail == next_ptr) { | ||
516 | local_irq_restore(flags); | ||
517 | return NETDEV_TX_BUSY; /* unable to queue */ | ||
518 | } | ||
519 | |||
520 | ptr = 0x600 * priv(dev)->tx_head; | ||
521 | priv(dev)->tx_head = next_ptr; | ||
522 | next_ptr *= 0x600; | ||
523 | |||
524 | #define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS) | ||
525 | |||
526 | ether3_setbuffer(dev, buffer_write, next_ptr); | ||
527 | ether3_writelong(dev, 0); | ||
528 | ether3_setbuffer(dev, buffer_write, ptr); | ||
529 | ether3_writelong(dev, 0); | ||
530 | ether3_writebuffer(dev, skb->data, length); | ||
531 | ether3_writeword(dev, htons(next_ptr)); | ||
532 | ether3_writeword(dev, TXHDR_CHAINCONTINUE >> 16); | ||
533 | ether3_setbuffer(dev, buffer_write, ptr); | ||
534 | ether3_writeword(dev, htons((ptr + length + 4))); | ||
535 | ether3_writeword(dev, TXHDR_FLAGS >> 16); | ||
536 | ether3_ledon(dev); | ||
537 | |||
538 | if (!(ether3_inw(REG_STATUS) & STAT_TXON)) { | ||
539 | ether3_outw(ptr, REG_TRANSMITPTR); | ||
540 | ether3_outw(priv(dev)->regs.command | CMD_TXON, REG_COMMAND); | ||
541 | } | ||
542 | |||
543 | next_ptr = (priv(dev)->tx_head + 1) & 15; | ||
544 | local_irq_restore(flags); | ||
545 | |||
546 | dev_kfree_skb(skb); | ||
547 | |||
548 | if (priv(dev)->tx_tail == next_ptr) | ||
549 | netif_stop_queue(dev); | ||
550 | |||
551 | out: | ||
552 | return NETDEV_TX_OK; | ||
553 | } | ||
554 | |||
555 | static irqreturn_t | ||
556 | ether3_interrupt(int irq, void *dev_id) | ||
557 | { | ||
558 | struct net_device *dev = (struct net_device *)dev_id; | ||
559 | unsigned int status, handled = IRQ_NONE; | ||
560 | |||
561 | #if NET_DEBUG > 1 | ||
562 | if(net_debug & DEBUG_INT) | ||
563 | printk("eth3irq: %d ", irq); | ||
564 | #endif | ||
565 | |||
566 | status = ether3_inw(REG_STATUS); | ||
567 | |||
568 | if (status & STAT_INTRX) { | ||
569 | ether3_outw(CMD_ACKINTRX | priv(dev)->regs.command, REG_COMMAND); | ||
570 | ether3_rx(dev, 12); | ||
571 | handled = IRQ_HANDLED; | ||
572 | } | ||
573 | |||
574 | if (status & STAT_INTTX) { | ||
575 | ether3_outw(CMD_ACKINTTX | priv(dev)->regs.command, REG_COMMAND); | ||
576 | ether3_tx(dev); | ||
577 | handled = IRQ_HANDLED; | ||
578 | } | ||
579 | |||
580 | #if NET_DEBUG > 1 | ||
581 | if(net_debug & DEBUG_INT) | ||
582 | printk("done\n"); | ||
583 | #endif | ||
584 | return handled; | ||
585 | } | ||
586 | |||
587 | /* | ||
588 | * If we have a good packet(s), get it/them out of the buffers. | ||
589 | */ | ||
590 | static int ether3_rx(struct net_device *dev, unsigned int maxcnt) | ||
591 | { | ||
592 | unsigned int next_ptr = priv(dev)->rx_head, received = 0; | ||
593 | |||
594 | ether3_ledon(dev); | ||
595 | |||
596 | do { | ||
597 | unsigned int this_ptr, status; | ||
598 | unsigned char addrs[16]; | ||
599 | |||
600 | /* | ||
601 | * read the first 16 bytes from the buffer. | ||
602 | * This contains the status bytes etc and ethernet addresses, | ||
603 | * and we also check the source ethernet address to see if | ||
604 | * it originated from us. | ||
605 | */ | ||
606 | { | ||
607 | unsigned int temp_ptr; | ||
608 | ether3_setbuffer(dev, buffer_read, next_ptr); | ||
609 | temp_ptr = ether3_readword(dev); | ||
610 | status = ether3_readword(dev); | ||
611 | if ((status & (RXSTAT_DONE | RXHDR_CHAINCONTINUE | RXHDR_RECEIVE)) != | ||
612 | (RXSTAT_DONE | RXHDR_CHAINCONTINUE) || !temp_ptr) | ||
613 | break; | ||
614 | |||
615 | this_ptr = next_ptr + 4; | ||
616 | next_ptr = ntohs(temp_ptr); | ||
617 | } | ||
618 | ether3_setbuffer(dev, buffer_read, this_ptr); | ||
619 | ether3_readbuffer(dev, addrs+2, 12); | ||
620 | |||
621 | if (next_ptr < RX_START || next_ptr >= RX_END) { | ||
622 | int i; | ||
623 | printk("%s: bad next pointer @%04X: ", dev->name, priv(dev)->rx_head); | ||
624 | printk("%02X %02X %02X %02X ", next_ptr >> 8, next_ptr & 255, status & 255, status >> 8); | ||
625 | for (i = 2; i < 14; i++) | ||
626 | printk("%02X ", addrs[i]); | ||
627 | printk("\n"); | ||
628 | next_ptr = priv(dev)->rx_head; | ||
629 | break; | ||
630 | } | ||
631 | /* | ||
632 | * ignore our own packets... | ||
633 | */ | ||
634 | if (!(*(unsigned long *)&dev->dev_addr[0] ^ *(unsigned long *)&addrs[2+6]) && | ||
635 | !(*(unsigned short *)&dev->dev_addr[4] ^ *(unsigned short *)&addrs[2+10])) { | ||
636 | maxcnt ++; /* compensate for loopedback packet */ | ||
637 | ether3_outw(next_ptr >> 8, REG_RECVEND); | ||
638 | } else | ||
639 | if (!(status & (RXSTAT_OVERSIZE|RXSTAT_CRCERROR|RXSTAT_DRIBBLEERROR|RXSTAT_SHORTPACKET))) { | ||
640 | unsigned int length = next_ptr - this_ptr; | ||
641 | struct sk_buff *skb; | ||
642 | |||
643 | if (next_ptr <= this_ptr) | ||
644 | length += RX_END - RX_START; | ||
645 | |||
646 | skb = dev_alloc_skb(length + 2); | ||
647 | if (skb) { | ||
648 | unsigned char *buf; | ||
649 | |||
650 | skb_reserve(skb, 2); | ||
651 | buf = skb_put(skb, length); | ||
652 | ether3_readbuffer(dev, buf + 12, length - 12); | ||
653 | ether3_outw(next_ptr >> 8, REG_RECVEND); | ||
654 | *(unsigned short *)(buf + 0) = *(unsigned short *)(addrs + 2); | ||
655 | *(unsigned long *)(buf + 2) = *(unsigned long *)(addrs + 4); | ||
656 | *(unsigned long *)(buf + 6) = *(unsigned long *)(addrs + 8); | ||
657 | *(unsigned short *)(buf + 10) = *(unsigned short *)(addrs + 12); | ||
658 | skb->protocol = eth_type_trans(skb, dev); | ||
659 | netif_rx(skb); | ||
660 | received ++; | ||
661 | } else | ||
662 | goto dropping; | ||
663 | } else { | ||
664 | struct net_device_stats *stats = &dev->stats; | ||
665 | ether3_outw(next_ptr >> 8, REG_RECVEND); | ||
666 | if (status & RXSTAT_OVERSIZE) stats->rx_over_errors ++; | ||
667 | if (status & RXSTAT_CRCERROR) stats->rx_crc_errors ++; | ||
668 | if (status & RXSTAT_DRIBBLEERROR) stats->rx_fifo_errors ++; | ||
669 | if (status & RXSTAT_SHORTPACKET) stats->rx_length_errors ++; | ||
670 | stats->rx_errors++; | ||
671 | } | ||
672 | } | ||
673 | while (-- maxcnt); | ||
674 | |||
675 | done: | ||
676 | dev->stats.rx_packets += received; | ||
677 | priv(dev)->rx_head = next_ptr; | ||
678 | /* | ||
679 | * If rx went off line, then that means that the buffer may be full. We | ||
680 | * have dropped at least one packet. | ||
681 | */ | ||
682 | if (!(ether3_inw(REG_STATUS) & STAT_RXON)) { | ||
683 | dev->stats.rx_dropped++; | ||
684 | ether3_outw(next_ptr, REG_RECVPTR); | ||
685 | ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND); | ||
686 | } | ||
687 | |||
688 | return maxcnt; | ||
689 | |||
690 | dropping:{ | ||
691 | static unsigned long last_warned; | ||
692 | |||
693 | ether3_outw(next_ptr >> 8, REG_RECVEND); | ||
694 | /* | ||
695 | * Don't print this message too many times... | ||
696 | */ | ||
697 | if (time_after(jiffies, last_warned + 10 * HZ)) { | ||
698 | last_warned = jiffies; | ||
699 | printk("%s: memory squeeze, dropping packet.\n", dev->name); | ||
700 | } | ||
701 | dev->stats.rx_dropped++; | ||
702 | goto done; | ||
703 | } | ||
704 | } | ||
705 | |||
706 | /* | ||
707 | * Update stats for the transmitted packet(s) | ||
708 | */ | ||
709 | static void ether3_tx(struct net_device *dev) | ||
710 | { | ||
711 | unsigned int tx_tail = priv(dev)->tx_tail; | ||
712 | int max_work = 14; | ||
713 | |||
714 | do { | ||
715 | unsigned long status; | ||
716 | |||
717 | /* | ||
718 | * Read the packet header | ||
719 | */ | ||
720 | ether3_setbuffer(dev, buffer_read, tx_tail * 0x600); | ||
721 | status = ether3_readlong(dev); | ||
722 | |||
723 | /* | ||
724 | * Check to see if this packet has been transmitted | ||
725 | */ | ||
726 | if ((status & (TXSTAT_DONE | TXHDR_TRANSMIT)) != | ||
727 | (TXSTAT_DONE | TXHDR_TRANSMIT)) | ||
728 | break; | ||
729 | |||
730 | /* | ||
731 | * Update errors | ||
732 | */ | ||
733 | if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS))) | ||
734 | dev->stats.tx_packets++; | ||
735 | else { | ||
736 | dev->stats.tx_errors++; | ||
737 | if (status & TXSTAT_16COLLISIONS) | ||
738 | dev->stats.collisions += 16; | ||
739 | if (status & TXSTAT_BABBLED) | ||
740 | dev->stats.tx_fifo_errors++; | ||
741 | } | ||
742 | |||
743 | tx_tail = (tx_tail + 1) & 15; | ||
744 | } while (--max_work); | ||
745 | |||
746 | if (priv(dev)->tx_tail != tx_tail) { | ||
747 | priv(dev)->tx_tail = tx_tail; | ||
748 | netif_wake_queue(dev); | ||
749 | } | ||
750 | } | ||
751 | |||
752 | static void __devinit ether3_banner(void) | ||
753 | { | ||
754 | static unsigned version_printed = 0; | ||
755 | |||
756 | if (net_debug && version_printed++ == 0) | ||
757 | printk(KERN_INFO "%s", version); | ||
758 | } | ||
759 | |||
760 | static const struct net_device_ops ether3_netdev_ops = { | ||
761 | .ndo_open = ether3_open, | ||
762 | .ndo_stop = ether3_close, | ||
763 | .ndo_start_xmit = ether3_sendpacket, | ||
764 | .ndo_set_multicast_list = ether3_setmulticastlist, | ||
765 | .ndo_tx_timeout = ether3_timeout, | ||
766 | .ndo_validate_addr = eth_validate_addr, | ||
767 | .ndo_change_mtu = eth_change_mtu, | ||
768 | .ndo_set_mac_address = eth_mac_addr, | ||
769 | }; | ||
770 | |||
771 | static int __devinit | ||
772 | ether3_probe(struct expansion_card *ec, const struct ecard_id *id) | ||
773 | { | ||
774 | const struct ether3_data *data = id->data; | ||
775 | struct net_device *dev; | ||
776 | int bus_type, ret; | ||
777 | |||
778 | ether3_banner(); | ||
779 | |||
780 | ret = ecard_request_resources(ec); | ||
781 | if (ret) | ||
782 | goto out; | ||
783 | |||
784 | dev = alloc_etherdev(sizeof(struct dev_priv)); | ||
785 | if (!dev) { | ||
786 | ret = -ENOMEM; | ||
787 | goto release; | ||
788 | } | ||
789 | |||
790 | SET_NETDEV_DEV(dev, &ec->dev); | ||
791 | |||
792 | priv(dev)->base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); | ||
793 | if (!priv(dev)->base) { | ||
794 | ret = -ENOMEM; | ||
795 | goto free; | ||
796 | } | ||
797 | |||
798 | ec->irqaddr = priv(dev)->base + data->base_offset; | ||
799 | ec->irqmask = 0xf0; | ||
800 | |||
801 | priv(dev)->seeq = priv(dev)->base + data->base_offset; | ||
802 | dev->irq = ec->irq; | ||
803 | |||
804 | ether3_addr(dev->dev_addr, ec); | ||
805 | |||
806 | init_timer(&priv(dev)->timer); | ||
807 | |||
808 | /* Reset card... | ||
809 | */ | ||
810 | ether3_outb(0x80, REG_CONFIG2 + 4); | ||
811 | bus_type = BUS_UNKNOWN; | ||
812 | udelay(4); | ||
813 | |||
814 | /* Test using Receive Pointer (16-bit register) to find out | ||
815 | * how the ether3 is connected to the bus... | ||
816 | */ | ||
817 | if (ether3_probe_bus_8(dev, 0x100) && | ||
818 | ether3_probe_bus_8(dev, 0x201)) | ||
819 | bus_type = BUS_8; | ||
820 | |||
821 | if (bus_type == BUS_UNKNOWN && | ||
822 | ether3_probe_bus_16(dev, 0x101) && | ||
823 | ether3_probe_bus_16(dev, 0x201)) | ||
824 | bus_type = BUS_16; | ||
825 | |||
826 | switch (bus_type) { | ||
827 | case BUS_UNKNOWN: | ||
828 | printk(KERN_ERR "%s: unable to identify bus width\n", dev->name); | ||
829 | ret = -ENODEV; | ||
830 | goto free; | ||
831 | |||
832 | case BUS_8: | ||
833 | printk(KERN_ERR "%s: %s found, but is an unsupported " | ||
834 | "8-bit card\n", dev->name, data->name); | ||
835 | ret = -ENODEV; | ||
836 | goto free; | ||
837 | |||
838 | default: | ||
839 | break; | ||
840 | } | ||
841 | |||
842 | if (ether3_init_2(dev)) { | ||
843 | ret = -ENODEV; | ||
844 | goto free; | ||
845 | } | ||
846 | |||
847 | dev->netdev_ops = ðer3_netdev_ops; | ||
848 | dev->watchdog_timeo = 5 * HZ / 100; | ||
849 | |||
850 | ret = register_netdev(dev); | ||
851 | if (ret) | ||
852 | goto free; | ||
853 | |||
854 | printk("%s: %s in slot %d, %pM\n", | ||
855 | dev->name, data->name, ec->slot_no, dev->dev_addr); | ||
856 | |||
857 | ecard_set_drvdata(ec, dev); | ||
858 | return 0; | ||
859 | |||
860 | free: | ||
861 | free_netdev(dev); | ||
862 | release: | ||
863 | ecard_release_resources(ec); | ||
864 | out: | ||
865 | return ret; | ||
866 | } | ||
867 | |||
868 | static void __devexit ether3_remove(struct expansion_card *ec) | ||
869 | { | ||
870 | struct net_device *dev = ecard_get_drvdata(ec); | ||
871 | |||
872 | ecard_set_drvdata(ec, NULL); | ||
873 | |||
874 | unregister_netdev(dev); | ||
875 | free_netdev(dev); | ||
876 | ecard_release_resources(ec); | ||
877 | } | ||
878 | |||
879 | static struct ether3_data ether3 = { | ||
880 | .name = "ether3", | ||
881 | .base_offset = 0, | ||
882 | }; | ||
883 | |||
884 | static struct ether3_data etherb = { | ||
885 | .name = "etherb", | ||
886 | .base_offset = 0x800, | ||
887 | }; | ||
888 | |||
889 | static const struct ecard_id ether3_ids[] = { | ||
890 | { MANU_ANT2, PROD_ANT_ETHER3, ðer3 }, | ||
891 | { MANU_ANT, PROD_ANT_ETHER3, ðer3 }, | ||
892 | { MANU_ANT, PROD_ANT_ETHERB, ðerb }, | ||
893 | { 0xffff, 0xffff } | ||
894 | }; | ||
895 | |||
896 | static struct ecard_driver ether3_driver = { | ||
897 | .probe = ether3_probe, | ||
898 | .remove = __devexit_p(ether3_remove), | ||
899 | .id_table = ether3_ids, | ||
900 | .drv = { | ||
901 | .name = "ether3", | ||
902 | }, | ||
903 | }; | ||
904 | |||
905 | static int __init ether3_init(void) | ||
906 | { | ||
907 | return ecard_register_driver(ðer3_driver); | ||
908 | } | ||
909 | |||
910 | static void __exit ether3_exit(void) | ||
911 | { | ||
912 | ecard_remove_driver(ðer3_driver); | ||
913 | } | ||
914 | |||
915 | module_init(ether3_init); | ||
916 | module_exit(ether3_exit); | ||
917 | |||
918 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/ethernet/seeq/ether3.h b/drivers/net/ethernet/seeq/ether3.h new file mode 100644 index 000000000000..2db63b08bdf3 --- /dev/null +++ b/drivers/net/ethernet/seeq/ether3.h | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * linux/drivers/acorn/net/ether3.h | ||
3 | * | ||
4 | * Copyright (C) 1995-2000 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * network driver for Acorn/ANT Ether3 cards | ||
11 | */ | ||
12 | |||
13 | #ifndef _LINUX_ether3_H | ||
14 | #define _LINUX_ether3_H | ||
15 | |||
16 | /* use 0 for production, 1 for verification, >2 for debug. debug flags: */ | ||
17 | #define DEBUG_TX 2 | ||
18 | #define DEBUG_RX 4 | ||
19 | #define DEBUG_INT 8 | ||
20 | #define DEBUG_IC 16 | ||
21 | #ifndef NET_DEBUG | ||
22 | #define NET_DEBUG 0 | ||
23 | #endif | ||
24 | |||
25 | #define priv(dev) ((struct dev_priv *)netdev_priv(dev)) | ||
26 | |||
27 | /* Command register definitions & bits */ | ||
28 | #define REG_COMMAND (priv(dev)->seeq + 0x0000) | ||
29 | #define CMD_ENINTDMA 0x0001 | ||
30 | #define CMD_ENINTRX 0x0002 | ||
31 | #define CMD_ENINTTX 0x0004 | ||
32 | #define CMD_ENINTBUFWIN 0x0008 | ||
33 | #define CMD_ACKINTDMA 0x0010 | ||
34 | #define CMD_ACKINTRX 0x0020 | ||
35 | #define CMD_ACKINTTX 0x0040 | ||
36 | #define CMD_ACKINTBUFWIN 0x0080 | ||
37 | #define CMD_DMAON 0x0100 | ||
38 | #define CMD_RXON 0x0200 | ||
39 | #define CMD_TXON 0x0400 | ||
40 | #define CMD_DMAOFF 0x0800 | ||
41 | #define CMD_RXOFF 0x1000 | ||
42 | #define CMD_TXOFF 0x2000 | ||
43 | #define CMD_FIFOREAD 0x4000 | ||
44 | #define CMD_FIFOWRITE 0x8000 | ||
45 | |||
46 | /* status register */ | ||
47 | #define REG_STATUS (priv(dev)->seeq + 0x0000) | ||
48 | #define STAT_ENINTSTAT 0x0001 | ||
49 | #define STAT_ENINTRX 0x0002 | ||
50 | #define STAT_ENINTTX 0x0004 | ||
51 | #define STAT_ENINTBUFWIN 0x0008 | ||
52 | #define STAT_INTDMA 0x0010 | ||
53 | #define STAT_INTRX 0x0020 | ||
54 | #define STAT_INTTX 0x0040 | ||
55 | #define STAT_INTBUFWIN 0x0080 | ||
56 | #define STAT_DMAON 0x0100 | ||
57 | #define STAT_RXON 0x0200 | ||
58 | #define STAT_TXON 0x0400 | ||
59 | #define STAT_FIFOFULL 0x2000 | ||
60 | #define STAT_FIFOEMPTY 0x4000 | ||
61 | #define STAT_FIFODIR 0x8000 | ||
62 | |||
63 | /* configuration register 1 */ | ||
64 | #define REG_CONFIG1 (priv(dev)->seeq + 0x0040) | ||
65 | #define CFG1_BUFSELSTAT0 0x0000 | ||
66 | #define CFG1_BUFSELSTAT1 0x0001 | ||
67 | #define CFG1_BUFSELSTAT2 0x0002 | ||
68 | #define CFG1_BUFSELSTAT3 0x0003 | ||
69 | #define CFG1_BUFSELSTAT4 0x0004 | ||
70 | #define CFG1_BUFSELSTAT5 0x0005 | ||
71 | #define CFG1_ADDRPROM 0x0006 | ||
72 | #define CFG1_TRANSEND 0x0007 | ||
73 | #define CFG1_LOCBUFMEM 0x0008 | ||
74 | #define CFG1_INTVECTOR 0x0009 | ||
75 | #define CFG1_RECVSPECONLY 0x0000 | ||
76 | #define CFG1_RECVSPECBROAD 0x4000 | ||
77 | #define CFG1_RECVSPECBRMULTI 0x8000 | ||
78 | #define CFG1_RECVPROMISC 0xC000 | ||
79 | |||
80 | /* The following aren't in 8004 */ | ||
81 | #define CFG1_DMABURSTCONT 0x0000 | ||
82 | #define CFG1_DMABURST800NS 0x0010 | ||
83 | #define CFG1_DMABURST1600NS 0x0020 | ||
84 | #define CFG1_DMABURST3200NS 0x0030 | ||
85 | #define CFG1_DMABURST1 0x0000 | ||
86 | #define CFG1_DMABURST4 0x0040 | ||
87 | #define CFG1_DMABURST8 0x0080 | ||
88 | #define CFG1_DMABURST16 0x00C0 | ||
89 | #define CFG1_RECVCOMPSTAT0 0x0100 | ||
90 | #define CFG1_RECVCOMPSTAT1 0x0200 | ||
91 | #define CFG1_RECVCOMPSTAT2 0x0400 | ||
92 | #define CFG1_RECVCOMPSTAT3 0x0800 | ||
93 | #define CFG1_RECVCOMPSTAT4 0x1000 | ||
94 | #define CFG1_RECVCOMPSTAT5 0x2000 | ||
95 | |||
96 | /* configuration register 2 */ | ||
97 | #define REG_CONFIG2 (priv(dev)->seeq + 0x0080) | ||
98 | #define CFG2_BYTESWAP 0x0001 | ||
99 | #define CFG2_ERRENCRC 0x0008 | ||
100 | #define CFG2_ERRENDRIBBLE 0x0010 | ||
101 | #define CFG2_ERRSHORTFRAME 0x0020 | ||
102 | #define CFG2_SLOTSELECT 0x0040 | ||
103 | #define CFG2_PREAMSELECT 0x0080 | ||
104 | #define CFG2_ADDRLENGTH 0x0100 | ||
105 | #define CFG2_RECVCRC 0x0200 | ||
106 | #define CFG2_XMITNOCRC 0x0400 | ||
107 | #define CFG2_LOOPBACK 0x0800 | ||
108 | #define CFG2_CTRLO 0x1000 | ||
109 | #define CFG2_RESET 0x8000 | ||
110 | |||
111 | #define REG_RECVEND (priv(dev)->seeq + 0x00c0) | ||
112 | |||
113 | #define REG_BUFWIN (priv(dev)->seeq + 0x0100) | ||
114 | |||
115 | #define REG_RECVPTR (priv(dev)->seeq + 0x0140) | ||
116 | |||
117 | #define REG_TRANSMITPTR (priv(dev)->seeq + 0x0180) | ||
118 | |||
119 | #define REG_DMAADDR (priv(dev)->seeq + 0x01c0) | ||
120 | |||
121 | /* | ||
122 | * Cards transmit/receive headers | ||
123 | */ | ||
124 | #define TX_NEXT (0xffff) | ||
125 | #define TXHDR_ENBABBLEINT (1 << 16) | ||
126 | #define TXHDR_ENCOLLISIONINT (1 << 17) | ||
127 | #define TXHDR_EN16COLLISION (1 << 18) | ||
128 | #define TXHDR_ENSUCCESS (1 << 19) | ||
129 | #define TXHDR_DATAFOLLOWS (1 << 21) | ||
130 | #define TXHDR_CHAINCONTINUE (1 << 22) | ||
131 | #define TXHDR_TRANSMIT (1 << 23) | ||
132 | #define TXSTAT_BABBLED (1 << 24) | ||
133 | #define TXSTAT_COLLISION (1 << 25) | ||
134 | #define TXSTAT_16COLLISIONS (1 << 26) | ||
135 | #define TXSTAT_DONE (1 << 31) | ||
136 | |||
137 | #define RX_NEXT (0xffff) | ||
138 | #define RXHDR_CHAINCONTINUE (1 << 6) | ||
139 | #define RXHDR_RECEIVE (1 << 7) | ||
140 | #define RXSTAT_OVERSIZE (1 << 8) | ||
141 | #define RXSTAT_CRCERROR (1 << 9) | ||
142 | #define RXSTAT_DRIBBLEERROR (1 << 10) | ||
143 | #define RXSTAT_SHORTPACKET (1 << 11) | ||
144 | #define RXSTAT_DONE (1 << 15) | ||
145 | |||
146 | |||
147 | #define TX_START 0x0000 | ||
148 | #define TX_END 0x6000 | ||
149 | #define RX_START 0x6000 | ||
150 | #define RX_LEN 0xA000 | ||
151 | #define RX_END 0x10000 | ||
152 | /* must be a power of 2 and greater than MAX_TX_BUFFERED */ | ||
153 | #define MAX_TXED 16 | ||
154 | #define MAX_TX_BUFFERED 10 | ||
155 | |||
156 | struct dev_priv { | ||
157 | void __iomem *base; | ||
158 | void __iomem *seeq; | ||
159 | struct { | ||
160 | unsigned int command; | ||
161 | unsigned int config1; | ||
162 | unsigned int config2; | ||
163 | } regs; | ||
164 | unsigned char tx_head; /* buffer nr to insert next packet */ | ||
165 | unsigned char tx_tail; /* buffer nr of transmitting packet */ | ||
166 | unsigned int rx_head; /* address to fetch next packet from */ | ||
167 | struct timer_list timer; | ||
168 | int broken; /* 0 = ok, 1 = something went wrong */ | ||
169 | }; | ||
170 | |||
171 | struct ether3_data { | ||
172 | const char name[8]; | ||
173 | unsigned long base_offset; | ||
174 | }; | ||
175 | |||
176 | #endif | ||
diff --git a/drivers/net/ethernet/seeq/seeq8005.c b/drivers/net/ethernet/seeq/seeq8005.c new file mode 100644 index 000000000000..d2fce98f557f --- /dev/null +++ b/drivers/net/ethernet/seeq/seeq8005.c | |||
@@ -0,0 +1,752 @@ | |||
1 | /* seeq8005.c: A network driver for linux. */ | ||
2 | /* | ||
3 | Based on skeleton.c, | ||
4 | Written 1993-94 by Donald Becker. | ||
5 | See the skeleton.c file for further copyright information. | ||
6 | |||
7 | This software may be used and distributed according to the terms | ||
8 | of the GNU General Public License, incorporated herein by reference. | ||
9 | |||
10 | The author may be reached as hamish@zot.apana.org.au | ||
11 | |||
12 | This file is a network device driver for the SEEQ 8005 chipset and | ||
13 | the Linux operating system. | ||
14 | |||
15 | */ | ||
16 | |||
17 | static const char version[] = | ||
18 | "seeq8005.c:v1.00 8/07/95 Hamish Coleman (hamish@zot.apana.org.au)\n"; | ||
19 | |||
20 | /* | ||
21 | Sources: | ||
22 | SEEQ 8005 databook | ||
23 | |||
24 | Version history: | ||
25 | 1.00 Public release. cosmetic changes (no warnings now) | ||
26 | 0.68 Turning per- packet,interrupt debug messages off - testing for release. | ||
27 | 0.67 timing problems/bad buffer reads seem to be fixed now | ||
28 | 0.63 *!@$ protocol=eth_type_trans -- now packets flow | ||
29 | 0.56 Send working | ||
30 | 0.48 Receive working | ||
31 | */ | ||
32 | |||
33 | #include <linux/module.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/types.h> | ||
36 | #include <linux/fcntl.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/ioport.h> | ||
39 | #include <linux/in.h> | ||
40 | #include <linux/string.h> | ||
41 | #include <linux/init.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <linux/errno.h> | ||
44 | #include <linux/netdevice.h> | ||
45 | #include <linux/etherdevice.h> | ||
46 | #include <linux/skbuff.h> | ||
47 | #include <linux/bitops.h> | ||
48 | #include <linux/jiffies.h> | ||
49 | |||
50 | #include <asm/system.h> | ||
51 | #include <asm/io.h> | ||
52 | #include <asm/dma.h> | ||
53 | |||
54 | #include "seeq8005.h" | ||
55 | |||
56 | /* First, a few definitions that the brave might change. */ | ||
57 | /* A zero-terminated list of I/O addresses to be probed. */ | ||
58 | static unsigned int seeq8005_portlist[] __initdata = | ||
59 | { 0x300, 0x320, 0x340, 0x360, 0}; | ||
60 | |||
61 | /* use 0 for production, 1 for verification, >2 for debug */ | ||
62 | #ifndef NET_DEBUG | ||
63 | #define NET_DEBUG 1 | ||
64 | #endif | ||
65 | static unsigned int net_debug = NET_DEBUG; | ||
66 | |||
67 | /* Information that need to be kept for each board. */ | ||
68 | struct net_local { | ||
69 | unsigned short receive_ptr; /* What address in packet memory do we expect a recv_pkt_header? */ | ||
70 | long open_time; /* Useless example local info. */ | ||
71 | }; | ||
72 | |||
73 | /* The station (ethernet) address prefix, used for IDing the board. */ | ||
74 | #define SA_ADDR0 0x00 | ||
75 | #define SA_ADDR1 0x80 | ||
76 | #define SA_ADDR2 0x4b | ||
77 | |||
78 | /* Index to functions, as function prototypes. */ | ||
79 | |||
80 | static int seeq8005_probe1(struct net_device *dev, int ioaddr); | ||
81 | static int seeq8005_open(struct net_device *dev); | ||
82 | static void seeq8005_timeout(struct net_device *dev); | ||
83 | static netdev_tx_t seeq8005_send_packet(struct sk_buff *skb, | ||
84 | struct net_device *dev); | ||
85 | static irqreturn_t seeq8005_interrupt(int irq, void *dev_id); | ||
86 | static void seeq8005_rx(struct net_device *dev); | ||
87 | static int seeq8005_close(struct net_device *dev); | ||
88 | static void set_multicast_list(struct net_device *dev); | ||
89 | |||
90 | /* Example routines you must write ;->. */ | ||
91 | #define tx_done(dev) (inw(SEEQ_STATUS) & SEEQSTAT_TX_ON) | ||
92 | static void hardware_send_packet(struct net_device *dev, char *buf, int length); | ||
93 | extern void seeq8005_init(struct net_device *dev, int startp); | ||
94 | static inline void wait_for_buffer(struct net_device *dev); | ||
95 | |||
96 | |||
97 | /* Check for a network adaptor of this type, and return '0' iff one exists. | ||
98 | If dev->base_addr == 0, probe all likely locations. | ||
99 | If dev->base_addr == 1, always return failure. | ||
100 | */ | ||
101 | |||
102 | static int io = 0x320; | ||
103 | static int irq = 10; | ||
104 | |||
105 | struct net_device * __init seeq8005_probe(int unit) | ||
106 | { | ||
107 | struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); | ||
108 | unsigned *port; | ||
109 | int err = 0; | ||
110 | |||
111 | if (!dev) | ||
112 | return ERR_PTR(-ENODEV); | ||
113 | |||
114 | if (unit >= 0) { | ||
115 | sprintf(dev->name, "eth%d", unit); | ||
116 | netdev_boot_setup_check(dev); | ||
117 | io = dev->base_addr; | ||
118 | irq = dev->irq; | ||
119 | } | ||
120 | |||
121 | if (io > 0x1ff) { /* Check a single specified location. */ | ||
122 | err = seeq8005_probe1(dev, io); | ||
123 | } else if (io != 0) { /* Don't probe at all. */ | ||
124 | err = -ENXIO; | ||
125 | } else { | ||
126 | for (port = seeq8005_portlist; *port; port++) { | ||
127 | if (seeq8005_probe1(dev, *port) == 0) | ||
128 | break; | ||
129 | } | ||
130 | if (!*port) | ||
131 | err = -ENODEV; | ||
132 | } | ||
133 | if (err) | ||
134 | goto out; | ||
135 | err = register_netdev(dev); | ||
136 | if (err) | ||
137 | goto out1; | ||
138 | return dev; | ||
139 | out1: | ||
140 | release_region(dev->base_addr, SEEQ8005_IO_EXTENT); | ||
141 | out: | ||
142 | free_netdev(dev); | ||
143 | return ERR_PTR(err); | ||
144 | } | ||
145 | |||
146 | static const struct net_device_ops seeq8005_netdev_ops = { | ||
147 | .ndo_open = seeq8005_open, | ||
148 | .ndo_stop = seeq8005_close, | ||
149 | .ndo_start_xmit = seeq8005_send_packet, | ||
150 | .ndo_tx_timeout = seeq8005_timeout, | ||
151 | .ndo_set_multicast_list = set_multicast_list, | ||
152 | .ndo_change_mtu = eth_change_mtu, | ||
153 | .ndo_set_mac_address = eth_mac_addr, | ||
154 | .ndo_validate_addr = eth_validate_addr, | ||
155 | }; | ||
156 | |||
157 | /* This is the real probe routine. Linux has a history of friendly device | ||
158 | probes on the ISA bus. A good device probes avoids doing writes, and | ||
159 | verifies that the correct device exists and functions. */ | ||
160 | |||
161 | static int __init seeq8005_probe1(struct net_device *dev, int ioaddr) | ||
162 | { | ||
163 | static unsigned version_printed; | ||
164 | int i,j; | ||
165 | unsigned char SA_prom[32]; | ||
166 | int old_cfg1; | ||
167 | int old_cfg2; | ||
168 | int old_stat; | ||
169 | int old_dmaar; | ||
170 | int old_rear; | ||
171 | int retval; | ||
172 | |||
173 | if (!request_region(ioaddr, SEEQ8005_IO_EXTENT, "seeq8005")) | ||
174 | return -ENODEV; | ||
175 | |||
176 | if (net_debug>1) | ||
177 | printk("seeq8005: probing at 0x%x\n",ioaddr); | ||
178 | |||
179 | old_stat = inw(SEEQ_STATUS); /* read status register */ | ||
180 | if (old_stat == 0xffff) { | ||
181 | retval = -ENODEV; | ||
182 | goto out; /* assume that 0xffff == no device */ | ||
183 | } | ||
184 | if ( (old_stat & 0x1800) != 0x1800 ) { /* assume that unused bits are 1, as my manual says */ | ||
185 | if (net_debug>1) { | ||
186 | printk("seeq8005: reserved stat bits != 0x1800\n"); | ||
187 | printk(" == 0x%04x\n",old_stat); | ||
188 | } | ||
189 | retval = -ENODEV; | ||
190 | goto out; | ||
191 | } | ||
192 | |||
193 | old_rear = inw(SEEQ_REA); | ||
194 | if (old_rear == 0xffff) { | ||
195 | outw(0,SEEQ_REA); | ||
196 | if (inw(SEEQ_REA) == 0xffff) { /* assume that 0xffff == no device */ | ||
197 | retval = -ENODEV; | ||
198 | goto out; | ||
199 | } | ||
200 | } else if ((old_rear & 0xff00) != 0xff00) { /* assume that unused bits are 1 */ | ||
201 | if (net_debug>1) { | ||
202 | printk("seeq8005: unused rear bits != 0xff00\n"); | ||
203 | printk(" == 0x%04x\n",old_rear); | ||
204 | } | ||
205 | retval = -ENODEV; | ||
206 | goto out; | ||
207 | } | ||
208 | |||
209 | old_cfg2 = inw(SEEQ_CFG2); /* read CFG2 register */ | ||
210 | old_cfg1 = inw(SEEQ_CFG1); | ||
211 | old_dmaar = inw(SEEQ_DMAAR); | ||
212 | |||
213 | if (net_debug>4) { | ||
214 | printk("seeq8005: stat = 0x%04x\n",old_stat); | ||
215 | printk("seeq8005: cfg1 = 0x%04x\n",old_cfg1); | ||
216 | printk("seeq8005: cfg2 = 0x%04x\n",old_cfg2); | ||
217 | printk("seeq8005: raer = 0x%04x\n",old_rear); | ||
218 | printk("seeq8005: dmaar= 0x%04x\n",old_dmaar); | ||
219 | } | ||
220 | |||
221 | outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); /* setup for reading PROM */ | ||
222 | outw( 0, SEEQ_DMAAR); /* set starting PROM address */ | ||
223 | outw( SEEQCFG1_BUFFER_PROM, SEEQ_CFG1); /* set buffer to look at PROM */ | ||
224 | |||
225 | |||
226 | j=0; | ||
227 | for(i=0; i <32; i++) { | ||
228 | j+= SA_prom[i] = inw(SEEQ_BUFFER) & 0xff; | ||
229 | } | ||
230 | |||
231 | #if 0 | ||
232 | /* untested because I only have the one card */ | ||
233 | if ( (j&0xff) != 0 ) { /* checksum appears to be 8bit = 0 */ | ||
234 | if (net_debug>1) { /* check this before deciding that we have a card */ | ||
235 | printk("seeq8005: prom sum error\n"); | ||
236 | } | ||
237 | outw( old_stat, SEEQ_STATUS); | ||
238 | outw( old_dmaar, SEEQ_DMAAR); | ||
239 | outw( old_cfg1, SEEQ_CFG1); | ||
240 | retval = -ENODEV; | ||
241 | goto out; | ||
242 | } | ||
243 | #endif | ||
244 | |||
245 | outw( SEEQCFG2_RESET, SEEQ_CFG2); /* reset the card */ | ||
246 | udelay(5); | ||
247 | outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD); | ||
248 | |||
249 | if (net_debug) { | ||
250 | printk("seeq8005: prom sum = 0x%08x\n",j); | ||
251 | for(j=0; j<32; j+=16) { | ||
252 | printk("seeq8005: prom %02x: ",j); | ||
253 | for(i=0;i<16;i++) { | ||
254 | printk("%02x ",SA_prom[j|i]); | ||
255 | } | ||
256 | printk(" "); | ||
257 | for(i=0;i<16;i++) { | ||
258 | if ((SA_prom[j|i]>31)&&(SA_prom[j|i]<127)) { | ||
259 | printk("%c", SA_prom[j|i]); | ||
260 | } else { | ||
261 | printk(" "); | ||
262 | } | ||
263 | } | ||
264 | printk("\n"); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | #if 0 | ||
269 | /* | ||
270 | * testing the packet buffer memory doesn't work yet | ||
271 | * but all other buffer accesses do | ||
272 | * - fixing is not a priority | ||
273 | */ | ||
274 | if (net_debug>1) { /* test packet buffer memory */ | ||
275 | printk("seeq8005: testing packet buffer ... "); | ||
276 | outw( SEEQCFG1_BUFFER_BUFFER, SEEQ_CFG1); | ||
277 | outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); | ||
278 | outw( 0 , SEEQ_DMAAR); | ||
279 | for(i=0;i<32768;i++) { | ||
280 | outw(0x5a5a, SEEQ_BUFFER); | ||
281 | } | ||
282 | j=jiffies+HZ; | ||
283 | while ( ((inw(SEEQ_STATUS) & SEEQSTAT_FIFO_EMPTY) != SEEQSTAT_FIFO_EMPTY) && time_before(jiffies, j) ) | ||
284 | mb(); | ||
285 | outw( 0 , SEEQ_DMAAR); | ||
286 | while ( ((inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, j+HZ)) | ||
287 | mb(); | ||
288 | if ( (inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT) | ||
289 | outw( SEEQCMD_WINDOW_INT_ACK | (inw(SEEQ_STATUS)& SEEQCMD_INT_MASK), SEEQ_CMD); | ||
290 | outw( SEEQCMD_FIFO_READ | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); | ||
291 | j=0; | ||
292 | for(i=0;i<32768;i++) { | ||
293 | if (inw(SEEQ_BUFFER) != 0x5a5a) | ||
294 | j++; | ||
295 | } | ||
296 | if (j) { | ||
297 | printk("%i\n",j); | ||
298 | } else { | ||
299 | printk("ok.\n"); | ||
300 | } | ||
301 | } | ||
302 | #endif | ||
303 | |||
304 | if (net_debug && version_printed++ == 0) | ||
305 | printk(version); | ||
306 | |||
307 | printk("%s: %s found at %#3x, ", dev->name, "seeq8005", ioaddr); | ||
308 | |||
309 | /* Fill in the 'dev' fields. */ | ||
310 | dev->base_addr = ioaddr; | ||
311 | dev->irq = irq; | ||
312 | |||
313 | /* Retrieve and print the ethernet address. */ | ||
314 | for (i = 0; i < 6; i++) | ||
315 | dev->dev_addr[i] = SA_prom[i+6]; | ||
316 | printk("%pM", dev->dev_addr); | ||
317 | |||
318 | if (dev->irq == 0xff) | ||
319 | ; /* Do nothing: a user-level program will set it. */ | ||
320 | else if (dev->irq < 2) { /* "Auto-IRQ" */ | ||
321 | unsigned long cookie = probe_irq_on(); | ||
322 | |||
323 | outw( SEEQCMD_RX_INT_EN | SEEQCMD_SET_RX_ON | SEEQCMD_SET_RX_OFF, SEEQ_CMD ); | ||
324 | |||
325 | dev->irq = probe_irq_off(cookie); | ||
326 | |||
327 | if (net_debug >= 2) | ||
328 | printk(" autoirq is %d\n", dev->irq); | ||
329 | } else if (dev->irq == 2) | ||
330 | /* Fixup for users that don't know that IRQ 2 is really IRQ 9, | ||
331 | * or don't know which one to set. | ||
332 | */ | ||
333 | dev->irq = 9; | ||
334 | |||
335 | #if 0 | ||
336 | { | ||
337 | int irqval = request_irq(dev->irq, seeq8005_interrupt, 0, "seeq8005", dev); | ||
338 | if (irqval) { | ||
339 | printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, | ||
340 | dev->irq, irqval); | ||
341 | retval = -EAGAIN; | ||
342 | goto out; | ||
343 | } | ||
344 | } | ||
345 | #endif | ||
346 | dev->netdev_ops = &seeq8005_netdev_ops; | ||
347 | dev->watchdog_timeo = HZ/20; | ||
348 | dev->flags &= ~IFF_MULTICAST; | ||
349 | |||
350 | return 0; | ||
351 | out: | ||
352 | release_region(ioaddr, SEEQ8005_IO_EXTENT); | ||
353 | return retval; | ||
354 | } | ||
355 | |||
356 | |||
357 | /* Open/initialize the board. This is called (in the current kernel) | ||
358 | sometime after booting when the 'ifconfig' program is run. | ||
359 | |||
360 | This routine should set everything up anew at each open, even | ||
361 | registers that "should" only need to be set once at boot, so that | ||
362 | there is non-reboot way to recover if something goes wrong. | ||
363 | */ | ||
364 | static int seeq8005_open(struct net_device *dev) | ||
365 | { | ||
366 | struct net_local *lp = netdev_priv(dev); | ||
367 | |||
368 | { | ||
369 | int irqval = request_irq(dev->irq, seeq8005_interrupt, 0, "seeq8005", dev); | ||
370 | if (irqval) { | ||
371 | printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, | ||
372 | dev->irq, irqval); | ||
373 | return -EAGAIN; | ||
374 | } | ||
375 | } | ||
376 | |||
377 | /* Reset the hardware here. Don't forget to set the station address. */ | ||
378 | seeq8005_init(dev, 1); | ||
379 | |||
380 | lp->open_time = jiffies; | ||
381 | |||
382 | netif_start_queue(dev); | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static void seeq8005_timeout(struct net_device *dev) | ||
387 | { | ||
388 | int ioaddr = dev->base_addr; | ||
389 | printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, | ||
390 | tx_done(dev) ? "IRQ conflict" : "network cable problem"); | ||
391 | /* Try to restart the adaptor. */ | ||
392 | seeq8005_init(dev, 1); | ||
393 | dev->trans_start = jiffies; /* prevent tx timeout */ | ||
394 | netif_wake_queue(dev); | ||
395 | } | ||
396 | |||
397 | static netdev_tx_t seeq8005_send_packet(struct sk_buff *skb, | ||
398 | struct net_device *dev) | ||
399 | { | ||
400 | short length = skb->len; | ||
401 | unsigned char *buf; | ||
402 | |||
403 | if (length < ETH_ZLEN) { | ||
404 | if (skb_padto(skb, ETH_ZLEN)) | ||
405 | return NETDEV_TX_OK; | ||
406 | length = ETH_ZLEN; | ||
407 | } | ||
408 | buf = skb->data; | ||
409 | |||
410 | /* Block a timer-based transmit from overlapping */ | ||
411 | netif_stop_queue(dev); | ||
412 | |||
413 | hardware_send_packet(dev, buf, length); | ||
414 | dev->stats.tx_bytes += length; | ||
415 | dev_kfree_skb (skb); | ||
416 | /* You might need to clean up and record Tx statistics here. */ | ||
417 | |||
418 | return NETDEV_TX_OK; | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * wait_for_buffer | ||
423 | * | ||
424 | * This routine waits for the SEEQ chip to assert that the FIFO is ready | ||
425 | * by checking for a window interrupt, and then clearing it. This has to | ||
426 | * occur in the interrupt handler! | ||
427 | */ | ||
428 | inline void wait_for_buffer(struct net_device * dev) | ||
429 | { | ||
430 | int ioaddr = dev->base_addr; | ||
431 | unsigned long tmp; | ||
432 | int status; | ||
433 | |||
434 | tmp = jiffies + HZ; | ||
435 | while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, tmp)) | ||
436 | cpu_relax(); | ||
437 | |||
438 | if ( (status & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT) | ||
439 | outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); | ||
440 | } | ||
441 | |||
442 | /* The typical workload of the driver: | ||
443 | Handle the network interface interrupts. */ | ||
444 | static irqreturn_t seeq8005_interrupt(int irq, void *dev_id) | ||
445 | { | ||
446 | struct net_device *dev = dev_id; | ||
447 | struct net_local *lp; | ||
448 | int ioaddr, status, boguscount = 0; | ||
449 | int handled = 0; | ||
450 | |||
451 | ioaddr = dev->base_addr; | ||
452 | lp = netdev_priv(dev); | ||
453 | |||
454 | status = inw(SEEQ_STATUS); | ||
455 | do { | ||
456 | if (net_debug >2) { | ||
457 | printk("%s: int, status=0x%04x\n",dev->name,status); | ||
458 | } | ||
459 | |||
460 | if (status & SEEQSTAT_WINDOW_INT) { | ||
461 | handled = 1; | ||
462 | outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); | ||
463 | if (net_debug) { | ||
464 | printk("%s: window int!\n",dev->name); | ||
465 | } | ||
466 | } | ||
467 | if (status & SEEQSTAT_TX_INT) { | ||
468 | handled = 1; | ||
469 | outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); | ||
470 | dev->stats.tx_packets++; | ||
471 | netif_wake_queue(dev); /* Inform upper layers. */ | ||
472 | } | ||
473 | if (status & SEEQSTAT_RX_INT) { | ||
474 | handled = 1; | ||
475 | /* Got a packet(s). */ | ||
476 | seeq8005_rx(dev); | ||
477 | } | ||
478 | status = inw(SEEQ_STATUS); | ||
479 | } while ( (++boguscount < 10) && (status & SEEQSTAT_ANY_INT)) ; | ||
480 | |||
481 | if(net_debug>2) { | ||
482 | printk("%s: eoi\n",dev->name); | ||
483 | } | ||
484 | return IRQ_RETVAL(handled); | ||
485 | } | ||
486 | |||
487 | /* We have a good packet(s), get it/them out of the buffers. */ | ||
488 | static void seeq8005_rx(struct net_device *dev) | ||
489 | { | ||
490 | struct net_local *lp = netdev_priv(dev); | ||
491 | int boguscount = 10; | ||
492 | int pkt_hdr; | ||
493 | int ioaddr = dev->base_addr; | ||
494 | |||
495 | do { | ||
496 | int next_packet; | ||
497 | int pkt_len; | ||
498 | int i; | ||
499 | int status; | ||
500 | |||
501 | status = inw(SEEQ_STATUS); | ||
502 | outw( lp->receive_ptr, SEEQ_DMAAR); | ||
503 | outw(SEEQCMD_FIFO_READ | SEEQCMD_RX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); | ||
504 | wait_for_buffer(dev); | ||
505 | next_packet = ntohs(inw(SEEQ_BUFFER)); | ||
506 | pkt_hdr = inw(SEEQ_BUFFER); | ||
507 | |||
508 | if (net_debug>2) { | ||
509 | printk("%s: 0x%04x recv next=0x%04x, hdr=0x%04x\n",dev->name,lp->receive_ptr,next_packet,pkt_hdr); | ||
510 | } | ||
511 | |||
512 | if ((next_packet == 0) || ((pkt_hdr & SEEQPKTH_CHAIN)==0)) { /* Read all the frames? */ | ||
513 | return; /* Done for now */ | ||
514 | } | ||
515 | |||
516 | if ((pkt_hdr & SEEQPKTS_DONE)==0) | ||
517 | break; | ||
518 | |||
519 | if (next_packet < lp->receive_ptr) { | ||
520 | pkt_len = (next_packet + 0x10000 - ((DEFAULT_TEA+1)<<8)) - lp->receive_ptr - 4; | ||
521 | } else { | ||
522 | pkt_len = next_packet - lp->receive_ptr - 4; | ||
523 | } | ||
524 | |||
525 | if (next_packet < ((DEFAULT_TEA+1)<<8)) { /* is the next_packet address sane? */ | ||
526 | printk("%s: recv packet ring corrupt, resetting board\n",dev->name); | ||
527 | seeq8005_init(dev,1); | ||
528 | return; | ||
529 | } | ||
530 | |||
531 | lp->receive_ptr = next_packet; | ||
532 | |||
533 | if (net_debug>2) { | ||
534 | printk("%s: recv len=0x%04x\n",dev->name,pkt_len); | ||
535 | } | ||
536 | |||
537 | if (pkt_hdr & SEEQPKTS_ANY_ERROR) { /* There was an error. */ | ||
538 | dev->stats.rx_errors++; | ||
539 | if (pkt_hdr & SEEQPKTS_SHORT) dev->stats.rx_frame_errors++; | ||
540 | if (pkt_hdr & SEEQPKTS_DRIB) dev->stats.rx_frame_errors++; | ||
541 | if (pkt_hdr & SEEQPKTS_OVERSIZE) dev->stats.rx_over_errors++; | ||
542 | if (pkt_hdr & SEEQPKTS_CRC_ERR) dev->stats.rx_crc_errors++; | ||
543 | /* skip over this packet */ | ||
544 | outw( SEEQCMD_FIFO_WRITE | SEEQCMD_DMA_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); | ||
545 | outw( (lp->receive_ptr & 0xff00)>>8, SEEQ_REA); | ||
546 | } else { | ||
547 | /* Malloc up new buffer. */ | ||
548 | struct sk_buff *skb; | ||
549 | unsigned char *buf; | ||
550 | |||
551 | skb = dev_alloc_skb(pkt_len); | ||
552 | if (skb == NULL) { | ||
553 | printk("%s: Memory squeeze, dropping packet.\n", dev->name); | ||
554 | dev->stats.rx_dropped++; | ||
555 | break; | ||
556 | } | ||
557 | skb_reserve(skb, 2); /* align data on 16 byte */ | ||
558 | buf = skb_put(skb,pkt_len); | ||
559 | |||
560 | insw(SEEQ_BUFFER, buf, (pkt_len + 1) >> 1); | ||
561 | |||
562 | if (net_debug>2) { | ||
563 | char * p = buf; | ||
564 | printk("%s: recv ",dev->name); | ||
565 | for(i=0;i<14;i++) { | ||
566 | printk("%02x ",*(p++)&0xff); | ||
567 | } | ||
568 | printk("\n"); | ||
569 | } | ||
570 | |||
571 | skb->protocol=eth_type_trans(skb,dev); | ||
572 | netif_rx(skb); | ||
573 | dev->stats.rx_packets++; | ||
574 | dev->stats.rx_bytes += pkt_len; | ||
575 | } | ||
576 | } while ((--boguscount) && (pkt_hdr & SEEQPKTH_CHAIN)); | ||
577 | |||
578 | /* If any worth-while packets have been received, netif_rx() | ||
579 | has done a mark_bh(NET_BH) for us and will work on them | ||
580 | when we get to the bottom-half routine. */ | ||
581 | } | ||
582 | |||
583 | /* The inverse routine to net_open(). */ | ||
584 | static int seeq8005_close(struct net_device *dev) | ||
585 | { | ||
586 | struct net_local *lp = netdev_priv(dev); | ||
587 | int ioaddr = dev->base_addr; | ||
588 | |||
589 | lp->open_time = 0; | ||
590 | |||
591 | netif_stop_queue(dev); | ||
592 | |||
593 | /* Flush the Tx and disable Rx here. */ | ||
594 | outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD); | ||
595 | |||
596 | free_irq(dev->irq, dev); | ||
597 | |||
598 | /* Update the statistics here. */ | ||
599 | |||
600 | return 0; | ||
601 | |||
602 | } | ||
603 | |||
604 | /* Set or clear the multicast filter for this adaptor. | ||
605 | num_addrs == -1 Promiscuous mode, receive all packets | ||
606 | num_addrs == 0 Normal mode, clear multicast list | ||
607 | num_addrs > 0 Multicast mode, receive normal and MC packets, and do | ||
608 | best-effort filtering. | ||
609 | */ | ||
610 | static void set_multicast_list(struct net_device *dev) | ||
611 | { | ||
612 | /* | ||
613 | * I _could_ do up to 6 addresses here, but won't (yet?) | ||
614 | */ | ||
615 | |||
616 | #if 0 | ||
617 | int ioaddr = dev->base_addr; | ||
618 | /* | ||
619 | * hmm, not even sure if my matching works _anyway_ - seem to be receiving | ||
620 | * _everything_ . . . | ||
621 | */ | ||
622 | |||
623 | if (num_addrs) { /* Enable promiscuous mode */ | ||
624 | outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_ALL, SEEQ_CFG1); | ||
625 | dev->flags|=IFF_PROMISC; | ||
626 | } else { /* Disable promiscuous mode, use normal mode */ | ||
627 | outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_BROAD, SEEQ_CFG1); | ||
628 | } | ||
629 | #endif | ||
630 | } | ||
631 | |||
632 | void seeq8005_init(struct net_device *dev, int startp) | ||
633 | { | ||
634 | struct net_local *lp = netdev_priv(dev); | ||
635 | int ioaddr = dev->base_addr; | ||
636 | int i; | ||
637 | |||
638 | outw(SEEQCFG2_RESET, SEEQ_CFG2); /* reset device */ | ||
639 | udelay(5); | ||
640 | |||
641 | outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); | ||
642 | outw( 0, SEEQ_DMAAR); /* load start address into both low and high byte */ | ||
643 | /* wait_for_buffer(dev); */ /* I think that you only need a wait for memory buffer */ | ||
644 | outw( SEEQCFG1_BUFFER_MAC0, SEEQ_CFG1); | ||
645 | |||
646 | for(i=0;i<6;i++) { /* set Station address */ | ||
647 | outb(dev->dev_addr[i], SEEQ_BUFFER); | ||
648 | udelay(2); | ||
649 | } | ||
650 | |||
651 | outw( SEEQCFG1_BUFFER_TEA, SEEQ_CFG1); /* set xmit end area pointer to 16K */ | ||
652 | outb( DEFAULT_TEA, SEEQ_BUFFER); /* this gives us 16K of send buffer and 48K of recv buffer */ | ||
653 | |||
654 | lp->receive_ptr = (DEFAULT_TEA+1)<<8; /* so we can find our packet_header */ | ||
655 | outw( lp->receive_ptr, SEEQ_RPR); /* Receive Pointer Register is set to recv buffer memory */ | ||
656 | |||
657 | outw( 0x00ff, SEEQ_REA); /* Receive Area End */ | ||
658 | |||
659 | if (net_debug>4) { | ||
660 | printk("%s: SA0 = ",dev->name); | ||
661 | |||
662 | outw( SEEQCMD_FIFO_READ | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); | ||
663 | outw( 0, SEEQ_DMAAR); | ||
664 | outw( SEEQCFG1_BUFFER_MAC0, SEEQ_CFG1); | ||
665 | |||
666 | for(i=0;i<6;i++) { | ||
667 | printk("%02x ",inb(SEEQ_BUFFER)); | ||
668 | } | ||
669 | printk("\n"); | ||
670 | } | ||
671 | |||
672 | outw( SEEQCFG1_MAC0_EN | SEEQCFG1_MATCH_BROAD | SEEQCFG1_BUFFER_BUFFER, SEEQ_CFG1); | ||
673 | outw( SEEQCFG2_AUTO_REA | SEEQCFG2_CTRLO, SEEQ_CFG2); | ||
674 | outw( SEEQCMD_SET_RX_ON | SEEQCMD_TX_INT_EN | SEEQCMD_RX_INT_EN, SEEQ_CMD); | ||
675 | |||
676 | if (net_debug>4) { | ||
677 | int old_cfg1; | ||
678 | old_cfg1 = inw(SEEQ_CFG1); | ||
679 | printk("%s: stat = 0x%04x\n",dev->name,inw(SEEQ_STATUS)); | ||
680 | printk("%s: cfg1 = 0x%04x\n",dev->name,old_cfg1); | ||
681 | printk("%s: cfg2 = 0x%04x\n",dev->name,inw(SEEQ_CFG2)); | ||
682 | printk("%s: raer = 0x%04x\n",dev->name,inw(SEEQ_REA)); | ||
683 | printk("%s: dmaar= 0x%04x\n",dev->name,inw(SEEQ_DMAAR)); | ||
684 | |||
685 | } | ||
686 | } | ||
687 | |||
688 | |||
689 | static void hardware_send_packet(struct net_device * dev, char *buf, int length) | ||
690 | { | ||
691 | int ioaddr = dev->base_addr; | ||
692 | int status = inw(SEEQ_STATUS); | ||
693 | int transmit_ptr = 0; | ||
694 | unsigned long tmp; | ||
695 | |||
696 | if (net_debug>4) { | ||
697 | printk("%s: send 0x%04x\n",dev->name,length); | ||
698 | } | ||
699 | |||
700 | /* Set FIFO to writemode and set packet-buffer address */ | ||
701 | outw( SEEQCMD_FIFO_WRITE | (status & SEEQCMD_INT_MASK), SEEQ_CMD); | ||
702 | outw( transmit_ptr, SEEQ_DMAAR); | ||
703 | |||
704 | /* output SEEQ Packet header barfage */ | ||
705 | outw( htons(length + 4), SEEQ_BUFFER); | ||
706 | outw( SEEQPKTH_XMIT | SEEQPKTH_DATA_FOLLOWS | SEEQPKTH_XMIT_INT_EN, SEEQ_BUFFER ); | ||
707 | |||
708 | /* blat the buffer */ | ||
709 | outsw( SEEQ_BUFFER, buf, (length +1) >> 1); | ||
710 | /* paranoia !! */ | ||
711 | outw( 0, SEEQ_BUFFER); | ||
712 | outw( 0, SEEQ_BUFFER); | ||
713 | |||
714 | /* set address of start of transmit chain */ | ||
715 | outw( transmit_ptr, SEEQ_TPR); | ||
716 | |||
717 | /* drain FIFO */ | ||
718 | tmp = jiffies; | ||
719 | while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && time_before(jiffies, tmp + HZ)) | ||
720 | mb(); | ||
721 | |||
722 | /* doit ! */ | ||
723 | outw( SEEQCMD_WINDOW_INT_ACK | SEEQCMD_SET_TX_ON | (status & SEEQCMD_INT_MASK), SEEQ_CMD); | ||
724 | |||
725 | } | ||
726 | |||
727 | |||
728 | #ifdef MODULE | ||
729 | |||
730 | static struct net_device *dev_seeq; | ||
731 | MODULE_LICENSE("GPL"); | ||
732 | module_param(io, int, 0); | ||
733 | module_param(irq, int, 0); | ||
734 | MODULE_PARM_DESC(io, "SEEQ 8005 I/O base address"); | ||
735 | MODULE_PARM_DESC(irq, "SEEQ 8005 IRQ number"); | ||
736 | |||
737 | int __init init_module(void) | ||
738 | { | ||
739 | dev_seeq = seeq8005_probe(-1); | ||
740 | if (IS_ERR(dev_seeq)) | ||
741 | return PTR_ERR(dev_seeq); | ||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | void __exit cleanup_module(void) | ||
746 | { | ||
747 | unregister_netdev(dev_seeq); | ||
748 | release_region(dev_seeq->base_addr, SEEQ8005_IO_EXTENT); | ||
749 | free_netdev(dev_seeq); | ||
750 | } | ||
751 | |||
752 | #endif /* MODULE */ | ||
diff --git a/drivers/net/ethernet/seeq/seeq8005.h b/drivers/net/ethernet/seeq/seeq8005.h new file mode 100644 index 000000000000..5dfb0098c6ca --- /dev/null +++ b/drivers/net/ethernet/seeq/seeq8005.h | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * defines, etc for the seeq8005 | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * This file is distributed under GPL. | ||
7 | * | ||
8 | * This style and layout of this file is also copied | ||
9 | * from many of the other linux network device drivers. | ||
10 | */ | ||
11 | |||
12 | /* The number of low I/O ports used by the ethercard. */ | ||
13 | #define SEEQ8005_IO_EXTENT 16 | ||
14 | |||
15 | #define SEEQ_B (ioaddr) | ||
16 | |||
17 | #define SEEQ_CMD (SEEQ_B) /* Write only */ | ||
18 | #define SEEQ_STATUS (SEEQ_B) /* Read only */ | ||
19 | #define SEEQ_CFG1 (SEEQ_B + 2) | ||
20 | #define SEEQ_CFG2 (SEEQ_B + 4) | ||
21 | #define SEEQ_REA (SEEQ_B + 6) /* Receive End Area Register */ | ||
22 | #define SEEQ_RPR (SEEQ_B + 10) /* Receive Pointer Register */ | ||
23 | #define SEEQ_TPR (SEEQ_B + 12) /* Transmit Pointer Register */ | ||
24 | #define SEEQ_DMAAR (SEEQ_B + 14) /* DMA Address Register */ | ||
25 | #define SEEQ_BUFFER (SEEQ_B + 8) /* Buffer Window Register */ | ||
26 | |||
27 | #define DEFAULT_TEA (0x3f) | ||
28 | |||
29 | #define SEEQCMD_DMA_INT_EN (0x0001) /* DMA Interrupt Enable */ | ||
30 | #define SEEQCMD_RX_INT_EN (0x0002) /* Receive Interrupt Enable */ | ||
31 | #define SEEQCMD_TX_INT_EN (0x0004) /* Transmit Interrupt Enable */ | ||
32 | #define SEEQCMD_WINDOW_INT_EN (0x0008) /* What the hell is this for?? */ | ||
33 | #define SEEQCMD_INT_MASK (0x000f) | ||
34 | |||
35 | #define SEEQCMD_DMA_INT_ACK (0x0010) /* DMA ack */ | ||
36 | #define SEEQCMD_RX_INT_ACK (0x0020) | ||
37 | #define SEEQCMD_TX_INT_ACK (0x0040) | ||
38 | #define SEEQCMD_WINDOW_INT_ACK (0x0080) | ||
39 | #define SEEQCMD_ACK_ALL (0x00f0) | ||
40 | |||
41 | #define SEEQCMD_SET_DMA_ON (0x0100) /* Enables DMA Request logic */ | ||
42 | #define SEEQCMD_SET_RX_ON (0x0200) /* Enables Packet RX */ | ||
43 | #define SEEQCMD_SET_TX_ON (0x0400) /* Starts TX run */ | ||
44 | #define SEEQCMD_SET_DMA_OFF (0x0800) | ||
45 | #define SEEQCMD_SET_RX_OFF (0x1000) | ||
46 | #define SEEQCMD_SET_TX_OFF (0x2000) | ||
47 | #define SEEQCMD_SET_ALL_OFF (0x3800) /* set all logic off */ | ||
48 | |||
49 | #define SEEQCMD_FIFO_READ (0x4000) /* Set FIFO to read mode (read from Buffer) */ | ||
50 | #define SEEQCMD_FIFO_WRITE (0x8000) /* Set FIFO to write mode */ | ||
51 | |||
52 | #define SEEQSTAT_DMA_INT_EN (0x0001) /* Status of interrupt enable */ | ||
53 | #define SEEQSTAT_RX_INT_EN (0x0002) | ||
54 | #define SEEQSTAT_TX_INT_EN (0x0004) | ||
55 | #define SEEQSTAT_WINDOW_INT_EN (0x0008) | ||
56 | |||
57 | #define SEEQSTAT_DMA_INT (0x0010) /* Interrupt flagged */ | ||
58 | #define SEEQSTAT_RX_INT (0x0020) | ||
59 | #define SEEQSTAT_TX_INT (0x0040) | ||
60 | #define SEEQSTAT_WINDOW_INT (0x0080) | ||
61 | #define SEEQSTAT_ANY_INT (0x00f0) | ||
62 | |||
63 | #define SEEQSTAT_DMA_ON (0x0100) /* DMA logic on */ | ||
64 | #define SEEQSTAT_RX_ON (0x0200) /* Packet RX on */ | ||
65 | #define SEEQSTAT_TX_ON (0x0400) /* TX running */ | ||
66 | |||
67 | #define SEEQSTAT_FIFO_FULL (0x2000) | ||
68 | #define SEEQSTAT_FIFO_EMPTY (0x4000) | ||
69 | #define SEEQSTAT_FIFO_DIR (0x8000) /* 1=read, 0=write */ | ||
70 | |||
71 | #define SEEQCFG1_BUFFER_MASK (0x000f) /* define what maps into the BUFFER register */ | ||
72 | #define SEEQCFG1_BUFFER_MAC0 (0x0000) /* MAC station addresses 0-5 */ | ||
73 | #define SEEQCFG1_BUFFER_MAC1 (0x0001) | ||
74 | #define SEEQCFG1_BUFFER_MAC2 (0x0002) | ||
75 | #define SEEQCFG1_BUFFER_MAC3 (0x0003) | ||
76 | #define SEEQCFG1_BUFFER_MAC4 (0x0004) | ||
77 | #define SEEQCFG1_BUFFER_MAC5 (0x0005) | ||
78 | #define SEEQCFG1_BUFFER_PROM (0x0006) /* The Address/CFG PROM */ | ||
79 | #define SEEQCFG1_BUFFER_TEA (0x0007) /* Transmit end area */ | ||
80 | #define SEEQCFG1_BUFFER_BUFFER (0x0008) /* Packet buffer memory */ | ||
81 | #define SEEQCFG1_BUFFER_INT_VEC (0x0009) /* Interrupt Vector */ | ||
82 | |||
83 | #define SEEQCFG1_DMA_INTVL_MASK (0x0030) | ||
84 | #define SEEQCFG1_DMA_CONT (0x0000) | ||
85 | #define SEEQCFG1_DMA_800ns (0x0010) | ||
86 | #define SEEQCFG1_DMA_1600ns (0x0020) | ||
87 | #define SEEQCFG1_DMA_3200ns (0x0030) | ||
88 | |||
89 | #define SEEQCFG1_DMA_LEN_MASK (0x00c0) | ||
90 | #define SEEQCFG1_DMA_LEN1 (0x0000) | ||
91 | #define SEEQCFG1_DMA_LEN2 (0x0040) | ||
92 | #define SEEQCFG1_DMA_LEN4 (0x0080) | ||
93 | #define SEEQCFG1_DMA_LEN8 (0x00c0) | ||
94 | |||
95 | #define SEEQCFG1_MAC_MASK (0x3f00) /* Dis/enable bits for MAC addresses */ | ||
96 | #define SEEQCFG1_MAC0_EN (0x0100) | ||
97 | #define SEEQCFG1_MAC1_EN (0x0200) | ||
98 | #define SEEQCFG1_MAC2_EN (0x0400) | ||
99 | #define SEEQCFG1_MAC3_EN (0x0800) | ||
100 | #define SEEQCFG1_MAC4_EN (0x1000) | ||
101 | #define SEEQCFG1_MAC5_EN (0x2000) | ||
102 | |||
103 | #define SEEQCFG1_MATCH_MASK (0xc000) /* Packet matching logic cfg bits */ | ||
104 | #define SEEQCFG1_MATCH_SPECIFIC (0x0000) /* only matching MAC addresses */ | ||
105 | #define SEEQCFG1_MATCH_BROAD (0x4000) /* matching and broadcast addresses */ | ||
106 | #define SEEQCFG1_MATCH_MULTI (0x8000) /* matching, broadcast and multicast */ | ||
107 | #define SEEQCFG1_MATCH_ALL (0xc000) /* Promiscuous mode */ | ||
108 | |||
109 | #define SEEQCFG1_DEFAULT (SEEQCFG1_BUFFER_BUFFER | SEEQCFG1_MAC0_EN | SEEQCFG1_MATCH_BROAD) | ||
110 | |||
111 | #define SEEQCFG2_BYTE_SWAP (0x0001) /* 0=Intel byte-order */ | ||
112 | #define SEEQCFG2_AUTO_REA (0x0002) /* if set, Receive End Area will be updated when reading from Buffer */ | ||
113 | |||
114 | #define SEEQCFG2_CRC_ERR_EN (0x0008) /* enables receiving of packets with CRC errors */ | ||
115 | #define SEEQCFG2_DRIBBLE_EN (0x0010) /* enables receiving of non-aligned packets */ | ||
116 | #define SEEQCFG2_SHORT_EN (0x0020) /* enables receiving of short packets */ | ||
117 | |||
118 | #define SEEQCFG2_SLOTSEL (0x0040) /* 0= standard IEEE802.3, 1= smaller,faster, non-standard */ | ||
119 | #define SEEQCFG2_NO_PREAM (0x0080) /* 1= user supplies Xmit preamble bytes */ | ||
120 | #define SEEQCFG2_ADDR_LEN (0x0100) /* 1= 2byte addresses */ | ||
121 | #define SEEQCFG2_REC_CRC (0x0200) /* 0= received packets will have CRC stripped from them */ | ||
122 | #define SEEQCFG2_XMIT_NO_CRC (0x0400) /* don't xmit CRC with each packet (user supplies it) */ | ||
123 | #define SEEQCFG2_LOOPBACK (0x0800) | ||
124 | #define SEEQCFG2_CTRLO (0x1000) | ||
125 | #define SEEQCFG2_RESET (0x8000) /* software Hard-reset bit */ | ||
126 | |||
127 | struct seeq_pkt_hdr { | ||
128 | unsigned short next; /* address of next packet header */ | ||
129 | unsigned char babble_int:1, /* enable int on >1514 byte packet */ | ||
130 | coll_int:1, /* enable int on collision */ | ||
131 | coll_16_int:1, /* enable int on >15 collision */ | ||
132 | xmit_int:1, /* enable int on success (or xmit with <15 collision) */ | ||
133 | unused:1, | ||
134 | data_follows:1, /* if not set, process this as a header and pointer only */ | ||
135 | chain_cont:1, /* if set, more headers in chain only cmd bit valid in recv header */ | ||
136 | xmit_recv:1; /* if set, a xmit packet, else a receive packet.*/ | ||
137 | unsigned char status; | ||
138 | }; | ||
139 | |||
140 | #define SEEQPKTH_BAB_INT_EN (0x01) /* xmit only */ | ||
141 | #define SEEQPKTH_COL_INT_EN (0x02) /* xmit only */ | ||
142 | #define SEEQPKTH_COL16_INT_EN (0x04) /* xmit only */ | ||
143 | #define SEEQPKTH_XMIT_INT_EN (0x08) /* xmit only */ | ||
144 | #define SEEQPKTH_DATA_FOLLOWS (0x20) /* supposedly in xmit only */ | ||
145 | #define SEEQPKTH_CHAIN (0x40) /* more headers follow */ | ||
146 | #define SEEQPKTH_XMIT (0x80) | ||
147 | |||
148 | #define SEEQPKTS_BABBLE (0x0100) /* xmit only */ | ||
149 | #define SEEQPKTS_OVERSIZE (0x0100) /* recv only */ | ||
150 | #define SEEQPKTS_COLLISION (0x0200) /* xmit only */ | ||
151 | #define SEEQPKTS_CRC_ERR (0x0200) /* recv only */ | ||
152 | #define SEEQPKTS_COLL16 (0x0400) /* xmit only */ | ||
153 | #define SEEQPKTS_DRIB (0x0400) /* recv only */ | ||
154 | #define SEEQPKTS_SHORT (0x0800) /* recv only */ | ||
155 | #define SEEQPKTS_DONE (0x8000) | ||
156 | #define SEEQPKTS_ANY_ERROR (0x0f00) | ||
diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c new file mode 100644 index 000000000000..52fb7ed9f365 --- /dev/null +++ b/drivers/net/ethernet/seeq/sgiseeq.c | |||
@@ -0,0 +1,858 @@ | |||
1 | /* | ||
2 | * sgiseeq.c: Seeq8003 ethernet driver for SGI machines. | ||
3 | * | ||
4 | * Copyright (C) 1996 David S. Miller (davem@davemloft.net) | ||
5 | */ | ||
6 | |||
7 | #undef DEBUG | ||
8 | |||
9 | #include <linux/dma-mapping.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/netdevice.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/etherdevice.h> | ||
22 | #include <linux/skbuff.h> | ||
23 | |||
24 | #include <asm/sgi/hpc3.h> | ||
25 | #include <asm/sgi/ip22.h> | ||
26 | #include <asm/sgi/seeq.h> | ||
27 | |||
28 | #include "sgiseeq.h" | ||
29 | |||
30 | static char *sgiseeqstr = "SGI Seeq8003"; | ||
31 | |||
32 | /* | ||
33 | * If you want speed, you do something silly, it always has worked for me. So, | ||
34 | * with that in mind, I've decided to make this driver look completely like a | ||
35 | * stupid Lance from a driver architecture perspective. Only difference is that | ||
36 | * here our "ring buffer" looks and acts like a real Lance one does but is | ||
37 | * laid out like how the HPC DMA and the Seeq want it to. You'd be surprised | ||
38 | * how a stupid idea like this can pay off in performance, not to mention | ||
39 | * making this driver 2,000 times easier to write. ;-) | ||
40 | */ | ||
41 | |||
42 | /* Tune these if we tend to run out often etc. */ | ||
43 | #define SEEQ_RX_BUFFERS 16 | ||
44 | #define SEEQ_TX_BUFFERS 16 | ||
45 | |||
46 | #define PKT_BUF_SZ 1584 | ||
47 | |||
48 | #define NEXT_RX(i) (((i) + 1) & (SEEQ_RX_BUFFERS - 1)) | ||
49 | #define NEXT_TX(i) (((i) + 1) & (SEEQ_TX_BUFFERS - 1)) | ||
50 | #define PREV_RX(i) (((i) - 1) & (SEEQ_RX_BUFFERS - 1)) | ||
51 | #define PREV_TX(i) (((i) - 1) & (SEEQ_TX_BUFFERS - 1)) | ||
52 | |||
53 | #define TX_BUFFS_AVAIL(sp) ((sp->tx_old <= sp->tx_new) ? \ | ||
54 | sp->tx_old + (SEEQ_TX_BUFFERS - 1) - sp->tx_new : \ | ||
55 | sp->tx_old - sp->tx_new - 1) | ||
56 | |||
57 | #define VIRT_TO_DMA(sp, v) ((sp)->srings_dma + \ | ||
58 | (dma_addr_t)((unsigned long)(v) - \ | ||
59 | (unsigned long)((sp)->rx_desc))) | ||
60 | |||
61 | /* Copy frames shorter than rx_copybreak, otherwise pass on up in | ||
62 | * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha). | ||
63 | */ | ||
64 | static int rx_copybreak = 100; | ||
65 | |||
66 | #define PAD_SIZE (128 - sizeof(struct hpc_dma_desc) - sizeof(void *)) | ||
67 | |||
68 | struct sgiseeq_rx_desc { | ||
69 | volatile struct hpc_dma_desc rdma; | ||
70 | u8 padding[PAD_SIZE]; | ||
71 | struct sk_buff *skb; | ||
72 | }; | ||
73 | |||
74 | struct sgiseeq_tx_desc { | ||
75 | volatile struct hpc_dma_desc tdma; | ||
76 | u8 padding[PAD_SIZE]; | ||
77 | struct sk_buff *skb; | ||
78 | }; | ||
79 | |||
80 | /* | ||
81 | * Warning: This structure is laid out in a certain way because HPC dma | ||
82 | * descriptors must be 8-byte aligned. So don't touch this without | ||
83 | * some care. | ||
84 | */ | ||
85 | struct sgiseeq_init_block { /* Note the name ;-) */ | ||
86 | struct sgiseeq_rx_desc rxvector[SEEQ_RX_BUFFERS]; | ||
87 | struct sgiseeq_tx_desc txvector[SEEQ_TX_BUFFERS]; | ||
88 | }; | ||
89 | |||
90 | struct sgiseeq_private { | ||
91 | struct sgiseeq_init_block *srings; | ||
92 | dma_addr_t srings_dma; | ||
93 | |||
94 | /* Ptrs to the descriptors in uncached space. */ | ||
95 | struct sgiseeq_rx_desc *rx_desc; | ||
96 | struct sgiseeq_tx_desc *tx_desc; | ||
97 | |||
98 | char *name; | ||
99 | struct hpc3_ethregs *hregs; | ||
100 | struct sgiseeq_regs *sregs; | ||
101 | |||
102 | /* Ring entry counters. */ | ||
103 | unsigned int rx_new, tx_new; | ||
104 | unsigned int rx_old, tx_old; | ||
105 | |||
106 | int is_edlc; | ||
107 | unsigned char control; | ||
108 | unsigned char mode; | ||
109 | |||
110 | spinlock_t tx_lock; | ||
111 | }; | ||
112 | |||
113 | static inline void dma_sync_desc_cpu(struct net_device *dev, void *addr) | ||
114 | { | ||
115 | dma_cache_sync(dev->dev.parent, addr, sizeof(struct sgiseeq_rx_desc), | ||
116 | DMA_FROM_DEVICE); | ||
117 | } | ||
118 | |||
119 | static inline void dma_sync_desc_dev(struct net_device *dev, void *addr) | ||
120 | { | ||
121 | dma_cache_sync(dev->dev.parent, addr, sizeof(struct sgiseeq_rx_desc), | ||
122 | DMA_TO_DEVICE); | ||
123 | } | ||
124 | |||
125 | static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs) | ||
126 | { | ||
127 | hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ; | ||
128 | udelay(20); | ||
129 | hregs->reset = 0; | ||
130 | } | ||
131 | |||
132 | static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs, | ||
133 | struct sgiseeq_regs *sregs) | ||
134 | { | ||
135 | hregs->rx_ctrl = hregs->tx_ctrl = 0; | ||
136 | hpc3_eth_reset(hregs); | ||
137 | } | ||
138 | |||
139 | #define RSTAT_GO_BITS (SEEQ_RCMD_IGOOD | SEEQ_RCMD_IEOF | SEEQ_RCMD_ISHORT | \ | ||
140 | SEEQ_RCMD_IDRIB | SEEQ_RCMD_ICRC) | ||
141 | |||
142 | static inline void seeq_go(struct sgiseeq_private *sp, | ||
143 | struct hpc3_ethregs *hregs, | ||
144 | struct sgiseeq_regs *sregs) | ||
145 | { | ||
146 | sregs->rstat = sp->mode | RSTAT_GO_BITS; | ||
147 | hregs->rx_ctrl = HPC3_ERXCTRL_ACTIVE; | ||
148 | } | ||
149 | |||
150 | static inline void __sgiseeq_set_mac_address(struct net_device *dev) | ||
151 | { | ||
152 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
153 | struct sgiseeq_regs *sregs = sp->sregs; | ||
154 | int i; | ||
155 | |||
156 | sregs->tstat = SEEQ_TCMD_RB0; | ||
157 | for (i = 0; i < 6; i++) | ||
158 | sregs->rw.eth_addr[i] = dev->dev_addr[i]; | ||
159 | } | ||
160 | |||
161 | static int sgiseeq_set_mac_address(struct net_device *dev, void *addr) | ||
162 | { | ||
163 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
164 | struct sockaddr *sa = addr; | ||
165 | |||
166 | memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); | ||
167 | |||
168 | spin_lock_irq(&sp->tx_lock); | ||
169 | __sgiseeq_set_mac_address(dev); | ||
170 | spin_unlock_irq(&sp->tx_lock); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | #define TCNTINFO_INIT (HPCDMA_EOX | HPCDMA_ETXD) | ||
176 | #define RCNTCFG_INIT (HPCDMA_OWN | HPCDMA_EORP | HPCDMA_XIE) | ||
177 | #define RCNTINFO_INIT (RCNTCFG_INIT | (PKT_BUF_SZ & HPCDMA_BCNT)) | ||
178 | |||
179 | static int seeq_init_ring(struct net_device *dev) | ||
180 | { | ||
181 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
182 | int i; | ||
183 | |||
184 | netif_stop_queue(dev); | ||
185 | sp->rx_new = sp->tx_new = 0; | ||
186 | sp->rx_old = sp->tx_old = 0; | ||
187 | |||
188 | __sgiseeq_set_mac_address(dev); | ||
189 | |||
190 | /* Setup tx ring. */ | ||
191 | for(i = 0; i < SEEQ_TX_BUFFERS; i++) { | ||
192 | sp->tx_desc[i].tdma.cntinfo = TCNTINFO_INIT; | ||
193 | dma_sync_desc_dev(dev, &sp->tx_desc[i]); | ||
194 | } | ||
195 | |||
196 | /* And now the rx ring. */ | ||
197 | for (i = 0; i < SEEQ_RX_BUFFERS; i++) { | ||
198 | if (!sp->rx_desc[i].skb) { | ||
199 | dma_addr_t dma_addr; | ||
200 | struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ); | ||
201 | |||
202 | if (skb == NULL) | ||
203 | return -ENOMEM; | ||
204 | skb_reserve(skb, 2); | ||
205 | dma_addr = dma_map_single(dev->dev.parent, | ||
206 | skb->data - 2, | ||
207 | PKT_BUF_SZ, DMA_FROM_DEVICE); | ||
208 | sp->rx_desc[i].skb = skb; | ||
209 | sp->rx_desc[i].rdma.pbuf = dma_addr; | ||
210 | } | ||
211 | sp->rx_desc[i].rdma.cntinfo = RCNTINFO_INIT; | ||
212 | dma_sync_desc_dev(dev, &sp->rx_desc[i]); | ||
213 | } | ||
214 | sp->rx_desc[i - 1].rdma.cntinfo |= HPCDMA_EOR; | ||
215 | dma_sync_desc_dev(dev, &sp->rx_desc[i - 1]); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static void seeq_purge_ring(struct net_device *dev) | ||
220 | { | ||
221 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
222 | int i; | ||
223 | |||
224 | /* clear tx ring. */ | ||
225 | for (i = 0; i < SEEQ_TX_BUFFERS; i++) { | ||
226 | if (sp->tx_desc[i].skb) { | ||
227 | dev_kfree_skb(sp->tx_desc[i].skb); | ||
228 | sp->tx_desc[i].skb = NULL; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /* And now the rx ring. */ | ||
233 | for (i = 0; i < SEEQ_RX_BUFFERS; i++) { | ||
234 | if (sp->rx_desc[i].skb) { | ||
235 | dev_kfree_skb(sp->rx_desc[i].skb); | ||
236 | sp->rx_desc[i].skb = NULL; | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | |||
241 | #ifdef DEBUG | ||
242 | static struct sgiseeq_private *gpriv; | ||
243 | static struct net_device *gdev; | ||
244 | |||
245 | static void sgiseeq_dump_rings(void) | ||
246 | { | ||
247 | static int once; | ||
248 | struct sgiseeq_rx_desc *r = gpriv->rx_desc; | ||
249 | struct sgiseeq_tx_desc *t = gpriv->tx_desc; | ||
250 | struct hpc3_ethregs *hregs = gpriv->hregs; | ||
251 | int i; | ||
252 | |||
253 | if (once) | ||
254 | return; | ||
255 | once++; | ||
256 | printk("RING DUMP:\n"); | ||
257 | for (i = 0; i < SEEQ_RX_BUFFERS; i++) { | ||
258 | printk("RX [%d]: @(%p) [%08x,%08x,%08x] ", | ||
259 | i, (&r[i]), r[i].rdma.pbuf, r[i].rdma.cntinfo, | ||
260 | r[i].rdma.pnext); | ||
261 | i += 1; | ||
262 | printk("-- [%d]: @(%p) [%08x,%08x,%08x]\n", | ||
263 | i, (&r[i]), r[i].rdma.pbuf, r[i].rdma.cntinfo, | ||
264 | r[i].rdma.pnext); | ||
265 | } | ||
266 | for (i = 0; i < SEEQ_TX_BUFFERS; i++) { | ||
267 | printk("TX [%d]: @(%p) [%08x,%08x,%08x] ", | ||
268 | i, (&t[i]), t[i].tdma.pbuf, t[i].tdma.cntinfo, | ||
269 | t[i].tdma.pnext); | ||
270 | i += 1; | ||
271 | printk("-- [%d]: @(%p) [%08x,%08x,%08x]\n", | ||
272 | i, (&t[i]), t[i].tdma.pbuf, t[i].tdma.cntinfo, | ||
273 | t[i].tdma.pnext); | ||
274 | } | ||
275 | printk("INFO: [rx_new = %d rx_old=%d] [tx_new = %d tx_old = %d]\n", | ||
276 | gpriv->rx_new, gpriv->rx_old, gpriv->tx_new, gpriv->tx_old); | ||
277 | printk("RREGS: rx_cbptr[%08x] rx_ndptr[%08x] rx_ctrl[%08x]\n", | ||
278 | hregs->rx_cbptr, hregs->rx_ndptr, hregs->rx_ctrl); | ||
279 | printk("TREGS: tx_cbptr[%08x] tx_ndptr[%08x] tx_ctrl[%08x]\n", | ||
280 | hregs->tx_cbptr, hregs->tx_ndptr, hregs->tx_ctrl); | ||
281 | } | ||
282 | #endif | ||
283 | |||
284 | #define TSTAT_INIT_SEEQ (SEEQ_TCMD_IPT|SEEQ_TCMD_I16|SEEQ_TCMD_IC|SEEQ_TCMD_IUF) | ||
285 | #define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2) | ||
286 | |||
287 | static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp, | ||
288 | struct sgiseeq_regs *sregs) | ||
289 | { | ||
290 | struct hpc3_ethregs *hregs = sp->hregs; | ||
291 | int err; | ||
292 | |||
293 | reset_hpc3_and_seeq(hregs, sregs); | ||
294 | err = seeq_init_ring(dev); | ||
295 | if (err) | ||
296 | return err; | ||
297 | |||
298 | /* Setup to field the proper interrupt types. */ | ||
299 | if (sp->is_edlc) { | ||
300 | sregs->tstat = TSTAT_INIT_EDLC; | ||
301 | sregs->rw.wregs.control = sp->control; | ||
302 | sregs->rw.wregs.frame_gap = 0; | ||
303 | } else { | ||
304 | sregs->tstat = TSTAT_INIT_SEEQ; | ||
305 | } | ||
306 | |||
307 | hregs->rx_ndptr = VIRT_TO_DMA(sp, sp->rx_desc); | ||
308 | hregs->tx_ndptr = VIRT_TO_DMA(sp, sp->tx_desc); | ||
309 | |||
310 | seeq_go(sp, hregs, sregs); | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static void record_rx_errors(struct net_device *dev, unsigned char status) | ||
315 | { | ||
316 | if (status & SEEQ_RSTAT_OVERF || | ||
317 | status & SEEQ_RSTAT_SFRAME) | ||
318 | dev->stats.rx_over_errors++; | ||
319 | if (status & SEEQ_RSTAT_CERROR) | ||
320 | dev->stats.rx_crc_errors++; | ||
321 | if (status & SEEQ_RSTAT_DERROR) | ||
322 | dev->stats.rx_frame_errors++; | ||
323 | if (status & SEEQ_RSTAT_REOF) | ||
324 | dev->stats.rx_errors++; | ||
325 | } | ||
326 | |||
327 | static inline void rx_maybe_restart(struct sgiseeq_private *sp, | ||
328 | struct hpc3_ethregs *hregs, | ||
329 | struct sgiseeq_regs *sregs) | ||
330 | { | ||
331 | if (!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) { | ||
332 | hregs->rx_ndptr = VIRT_TO_DMA(sp, sp->rx_desc + sp->rx_new); | ||
333 | seeq_go(sp, hregs, sregs); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp, | ||
338 | struct hpc3_ethregs *hregs, | ||
339 | struct sgiseeq_regs *sregs) | ||
340 | { | ||
341 | struct sgiseeq_rx_desc *rd; | ||
342 | struct sk_buff *skb = NULL; | ||
343 | struct sk_buff *newskb; | ||
344 | unsigned char pkt_status; | ||
345 | int len = 0; | ||
346 | unsigned int orig_end = PREV_RX(sp->rx_new); | ||
347 | |||
348 | /* Service every received packet. */ | ||
349 | rd = &sp->rx_desc[sp->rx_new]; | ||
350 | dma_sync_desc_cpu(dev, rd); | ||
351 | while (!(rd->rdma.cntinfo & HPCDMA_OWN)) { | ||
352 | len = PKT_BUF_SZ - (rd->rdma.cntinfo & HPCDMA_BCNT) - 3; | ||
353 | dma_unmap_single(dev->dev.parent, rd->rdma.pbuf, | ||
354 | PKT_BUF_SZ, DMA_FROM_DEVICE); | ||
355 | pkt_status = rd->skb->data[len]; | ||
356 | if (pkt_status & SEEQ_RSTAT_FIG) { | ||
357 | /* Packet is OK. */ | ||
358 | /* We don't want to receive our own packets */ | ||
359 | if (memcmp(rd->skb->data + 6, dev->dev_addr, ETH_ALEN)) { | ||
360 | if (len > rx_copybreak) { | ||
361 | skb = rd->skb; | ||
362 | newskb = netdev_alloc_skb(dev, PKT_BUF_SZ); | ||
363 | if (!newskb) { | ||
364 | newskb = skb; | ||
365 | skb = NULL; | ||
366 | goto memory_squeeze; | ||
367 | } | ||
368 | skb_reserve(newskb, 2); | ||
369 | } else { | ||
370 | skb = netdev_alloc_skb_ip_align(dev, len); | ||
371 | if (skb) | ||
372 | skb_copy_to_linear_data(skb, rd->skb->data, len); | ||
373 | |||
374 | newskb = rd->skb; | ||
375 | } | ||
376 | memory_squeeze: | ||
377 | if (skb) { | ||
378 | skb_put(skb, len); | ||
379 | skb->protocol = eth_type_trans(skb, dev); | ||
380 | netif_rx(skb); | ||
381 | dev->stats.rx_packets++; | ||
382 | dev->stats.rx_bytes += len; | ||
383 | } else { | ||
384 | printk(KERN_NOTICE "%s: Memory squeeze, deferring packet.\n", | ||
385 | dev->name); | ||
386 | dev->stats.rx_dropped++; | ||
387 | } | ||
388 | } else { | ||
389 | /* Silently drop my own packets */ | ||
390 | newskb = rd->skb; | ||
391 | } | ||
392 | } else { | ||
393 | record_rx_errors(dev, pkt_status); | ||
394 | newskb = rd->skb; | ||
395 | } | ||
396 | rd->skb = newskb; | ||
397 | rd->rdma.pbuf = dma_map_single(dev->dev.parent, | ||
398 | newskb->data - 2, | ||
399 | PKT_BUF_SZ, DMA_FROM_DEVICE); | ||
400 | |||
401 | /* Return the entry to the ring pool. */ | ||
402 | rd->rdma.cntinfo = RCNTINFO_INIT; | ||
403 | sp->rx_new = NEXT_RX(sp->rx_new); | ||
404 | dma_sync_desc_dev(dev, rd); | ||
405 | rd = &sp->rx_desc[sp->rx_new]; | ||
406 | dma_sync_desc_cpu(dev, rd); | ||
407 | } | ||
408 | dma_sync_desc_cpu(dev, &sp->rx_desc[orig_end]); | ||
409 | sp->rx_desc[orig_end].rdma.cntinfo &= ~(HPCDMA_EOR); | ||
410 | dma_sync_desc_dev(dev, &sp->rx_desc[orig_end]); | ||
411 | dma_sync_desc_cpu(dev, &sp->rx_desc[PREV_RX(sp->rx_new)]); | ||
412 | sp->rx_desc[PREV_RX(sp->rx_new)].rdma.cntinfo |= HPCDMA_EOR; | ||
413 | dma_sync_desc_dev(dev, &sp->rx_desc[PREV_RX(sp->rx_new)]); | ||
414 | rx_maybe_restart(sp, hregs, sregs); | ||
415 | } | ||
416 | |||
417 | static inline void tx_maybe_reset_collisions(struct sgiseeq_private *sp, | ||
418 | struct sgiseeq_regs *sregs) | ||
419 | { | ||
420 | if (sp->is_edlc) { | ||
421 | sregs->rw.wregs.control = sp->control & ~(SEEQ_CTRL_XCNT); | ||
422 | sregs->rw.wregs.control = sp->control; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | static inline void kick_tx(struct net_device *dev, | ||
427 | struct sgiseeq_private *sp, | ||
428 | struct hpc3_ethregs *hregs) | ||
429 | { | ||
430 | struct sgiseeq_tx_desc *td; | ||
431 | int i = sp->tx_old; | ||
432 | |||
433 | /* If the HPC aint doin nothin, and there are more packets | ||
434 | * with ETXD cleared and XIU set we must make very certain | ||
435 | * that we restart the HPC else we risk locking up the | ||
436 | * adapter. The following code is only safe iff the HPCDMA | ||
437 | * is not active! | ||
438 | */ | ||
439 | td = &sp->tx_desc[i]; | ||
440 | dma_sync_desc_cpu(dev, td); | ||
441 | while ((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) == | ||
442 | (HPCDMA_XIU | HPCDMA_ETXD)) { | ||
443 | i = NEXT_TX(i); | ||
444 | td = &sp->tx_desc[i]; | ||
445 | dma_sync_desc_cpu(dev, td); | ||
446 | } | ||
447 | if (td->tdma.cntinfo & HPCDMA_XIU) { | ||
448 | hregs->tx_ndptr = VIRT_TO_DMA(sp, td); | ||
449 | hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | static inline void sgiseeq_tx(struct net_device *dev, struct sgiseeq_private *sp, | ||
454 | struct hpc3_ethregs *hregs, | ||
455 | struct sgiseeq_regs *sregs) | ||
456 | { | ||
457 | struct sgiseeq_tx_desc *td; | ||
458 | unsigned long status = hregs->tx_ctrl; | ||
459 | int j; | ||
460 | |||
461 | tx_maybe_reset_collisions(sp, sregs); | ||
462 | |||
463 | if (!(status & (HPC3_ETXCTRL_ACTIVE | SEEQ_TSTAT_PTRANS))) { | ||
464 | /* Oops, HPC detected some sort of error. */ | ||
465 | if (status & SEEQ_TSTAT_R16) | ||
466 | dev->stats.tx_aborted_errors++; | ||
467 | if (status & SEEQ_TSTAT_UFLOW) | ||
468 | dev->stats.tx_fifo_errors++; | ||
469 | if (status & SEEQ_TSTAT_LCLS) | ||
470 | dev->stats.collisions++; | ||
471 | } | ||
472 | |||
473 | /* Ack 'em... */ | ||
474 | for (j = sp->tx_old; j != sp->tx_new; j = NEXT_TX(j)) { | ||
475 | td = &sp->tx_desc[j]; | ||
476 | |||
477 | dma_sync_desc_cpu(dev, td); | ||
478 | if (!(td->tdma.cntinfo & (HPCDMA_XIU))) | ||
479 | break; | ||
480 | if (!(td->tdma.cntinfo & (HPCDMA_ETXD))) { | ||
481 | if (!(status & HPC3_ETXCTRL_ACTIVE)) { | ||
482 | hregs->tx_ndptr = VIRT_TO_DMA(sp, td); | ||
483 | hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE; | ||
484 | } | ||
485 | break; | ||
486 | } | ||
487 | dev->stats.tx_packets++; | ||
488 | sp->tx_old = NEXT_TX(sp->tx_old); | ||
489 | td->tdma.cntinfo &= ~(HPCDMA_XIU | HPCDMA_XIE); | ||
490 | td->tdma.cntinfo |= HPCDMA_EOX; | ||
491 | if (td->skb) { | ||
492 | dev_kfree_skb_any(td->skb); | ||
493 | td->skb = NULL; | ||
494 | } | ||
495 | dma_sync_desc_dev(dev, td); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id) | ||
500 | { | ||
501 | struct net_device *dev = (struct net_device *) dev_id; | ||
502 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
503 | struct hpc3_ethregs *hregs = sp->hregs; | ||
504 | struct sgiseeq_regs *sregs = sp->sregs; | ||
505 | |||
506 | spin_lock(&sp->tx_lock); | ||
507 | |||
508 | /* Ack the IRQ and set software state. */ | ||
509 | hregs->reset = HPC3_ERST_CLRIRQ; | ||
510 | |||
511 | /* Always check for received packets. */ | ||
512 | sgiseeq_rx(dev, sp, hregs, sregs); | ||
513 | |||
514 | /* Only check for tx acks if we have something queued. */ | ||
515 | if (sp->tx_old != sp->tx_new) | ||
516 | sgiseeq_tx(dev, sp, hregs, sregs); | ||
517 | |||
518 | if ((TX_BUFFS_AVAIL(sp) > 0) && netif_queue_stopped(dev)) { | ||
519 | netif_wake_queue(dev); | ||
520 | } | ||
521 | spin_unlock(&sp->tx_lock); | ||
522 | |||
523 | return IRQ_HANDLED; | ||
524 | } | ||
525 | |||
526 | static int sgiseeq_open(struct net_device *dev) | ||
527 | { | ||
528 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
529 | struct sgiseeq_regs *sregs = sp->sregs; | ||
530 | unsigned int irq = dev->irq; | ||
531 | int err; | ||
532 | |||
533 | if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) { | ||
534 | printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq); | ||
535 | return -EAGAIN; | ||
536 | } | ||
537 | |||
538 | err = init_seeq(dev, sp, sregs); | ||
539 | if (err) | ||
540 | goto out_free_irq; | ||
541 | |||
542 | netif_start_queue(dev); | ||
543 | |||
544 | return 0; | ||
545 | |||
546 | out_free_irq: | ||
547 | free_irq(irq, dev); | ||
548 | |||
549 | return err; | ||
550 | } | ||
551 | |||
552 | static int sgiseeq_close(struct net_device *dev) | ||
553 | { | ||
554 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
555 | struct sgiseeq_regs *sregs = sp->sregs; | ||
556 | unsigned int irq = dev->irq; | ||
557 | |||
558 | netif_stop_queue(dev); | ||
559 | |||
560 | /* Shutdown the Seeq. */ | ||
561 | reset_hpc3_and_seeq(sp->hregs, sregs); | ||
562 | free_irq(irq, dev); | ||
563 | seeq_purge_ring(dev); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | static inline int sgiseeq_reset(struct net_device *dev) | ||
569 | { | ||
570 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
571 | struct sgiseeq_regs *sregs = sp->sregs; | ||
572 | int err; | ||
573 | |||
574 | err = init_seeq(dev, sp, sregs); | ||
575 | if (err) | ||
576 | return err; | ||
577 | |||
578 | dev->trans_start = jiffies; /* prevent tx timeout */ | ||
579 | netif_wake_queue(dev); | ||
580 | |||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
585 | { | ||
586 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
587 | struct hpc3_ethregs *hregs = sp->hregs; | ||
588 | unsigned long flags; | ||
589 | struct sgiseeq_tx_desc *td; | ||
590 | int len, entry; | ||
591 | |||
592 | spin_lock_irqsave(&sp->tx_lock, flags); | ||
593 | |||
594 | /* Setup... */ | ||
595 | len = skb->len; | ||
596 | if (len < ETH_ZLEN) { | ||
597 | if (skb_padto(skb, ETH_ZLEN)) { | ||
598 | spin_unlock_irqrestore(&sp->tx_lock, flags); | ||
599 | return NETDEV_TX_OK; | ||
600 | } | ||
601 | len = ETH_ZLEN; | ||
602 | } | ||
603 | |||
604 | dev->stats.tx_bytes += len; | ||
605 | entry = sp->tx_new; | ||
606 | td = &sp->tx_desc[entry]; | ||
607 | dma_sync_desc_cpu(dev, td); | ||
608 | |||
609 | /* Create entry. There are so many races with adding a new | ||
610 | * descriptor to the chain: | ||
611 | * 1) Assume that the HPC is off processing a DMA chain while | ||
612 | * we are changing all of the following. | ||
613 | * 2) Do no allow the HPC to look at a new descriptor until | ||
614 | * we have completely set up it's state. This means, do | ||
615 | * not clear HPCDMA_EOX in the current last descritptor | ||
616 | * until the one we are adding looks consistent and could | ||
617 | * be processes right now. | ||
618 | * 3) The tx interrupt code must notice when we've added a new | ||
619 | * entry and the HPC got to the end of the chain before we | ||
620 | * added this new entry and restarted it. | ||
621 | */ | ||
622 | td->skb = skb; | ||
623 | td->tdma.pbuf = dma_map_single(dev->dev.parent, skb->data, | ||
624 | len, DMA_TO_DEVICE); | ||
625 | td->tdma.cntinfo = (len & HPCDMA_BCNT) | | ||
626 | HPCDMA_XIU | HPCDMA_EOXP | HPCDMA_XIE | HPCDMA_EOX; | ||
627 | dma_sync_desc_dev(dev, td); | ||
628 | if (sp->tx_old != sp->tx_new) { | ||
629 | struct sgiseeq_tx_desc *backend; | ||
630 | |||
631 | backend = &sp->tx_desc[PREV_TX(sp->tx_new)]; | ||
632 | dma_sync_desc_cpu(dev, backend); | ||
633 | backend->tdma.cntinfo &= ~HPCDMA_EOX; | ||
634 | dma_sync_desc_dev(dev, backend); | ||
635 | } | ||
636 | sp->tx_new = NEXT_TX(sp->tx_new); /* Advance. */ | ||
637 | |||
638 | /* Maybe kick the HPC back into motion. */ | ||
639 | if (!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE)) | ||
640 | kick_tx(dev, sp, hregs); | ||
641 | |||
642 | if (!TX_BUFFS_AVAIL(sp)) | ||
643 | netif_stop_queue(dev); | ||
644 | spin_unlock_irqrestore(&sp->tx_lock, flags); | ||
645 | |||
646 | return NETDEV_TX_OK; | ||
647 | } | ||
648 | |||
649 | static void timeout(struct net_device *dev) | ||
650 | { | ||
651 | printk(KERN_NOTICE "%s: transmit timed out, resetting\n", dev->name); | ||
652 | sgiseeq_reset(dev); | ||
653 | |||
654 | dev->trans_start = jiffies; /* prevent tx timeout */ | ||
655 | netif_wake_queue(dev); | ||
656 | } | ||
657 | |||
658 | static void sgiseeq_set_multicast(struct net_device *dev) | ||
659 | { | ||
660 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
661 | unsigned char oldmode = sp->mode; | ||
662 | |||
663 | if(dev->flags & IFF_PROMISC) | ||
664 | sp->mode = SEEQ_RCMD_RANY; | ||
665 | else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) | ||
666 | sp->mode = SEEQ_RCMD_RBMCAST; | ||
667 | else | ||
668 | sp->mode = SEEQ_RCMD_RBCAST; | ||
669 | |||
670 | /* XXX I know this sucks, but is there a better way to reprogram | ||
671 | * XXX the receiver? At least, this shouldn't happen too often. | ||
672 | */ | ||
673 | |||
674 | if (oldmode != sp->mode) | ||
675 | sgiseeq_reset(dev); | ||
676 | } | ||
677 | |||
678 | static inline void setup_tx_ring(struct net_device *dev, | ||
679 | struct sgiseeq_tx_desc *buf, | ||
680 | int nbufs) | ||
681 | { | ||
682 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
683 | int i = 0; | ||
684 | |||
685 | while (i < (nbufs - 1)) { | ||
686 | buf[i].tdma.pnext = VIRT_TO_DMA(sp, buf + i + 1); | ||
687 | buf[i].tdma.pbuf = 0; | ||
688 | dma_sync_desc_dev(dev, &buf[i]); | ||
689 | i++; | ||
690 | } | ||
691 | buf[i].tdma.pnext = VIRT_TO_DMA(sp, buf); | ||
692 | dma_sync_desc_dev(dev, &buf[i]); | ||
693 | } | ||
694 | |||
695 | static inline void setup_rx_ring(struct net_device *dev, | ||
696 | struct sgiseeq_rx_desc *buf, | ||
697 | int nbufs) | ||
698 | { | ||
699 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
700 | int i = 0; | ||
701 | |||
702 | while (i < (nbufs - 1)) { | ||
703 | buf[i].rdma.pnext = VIRT_TO_DMA(sp, buf + i + 1); | ||
704 | buf[i].rdma.pbuf = 0; | ||
705 | dma_sync_desc_dev(dev, &buf[i]); | ||
706 | i++; | ||
707 | } | ||
708 | buf[i].rdma.pbuf = 0; | ||
709 | buf[i].rdma.pnext = VIRT_TO_DMA(sp, buf); | ||
710 | dma_sync_desc_dev(dev, &buf[i]); | ||
711 | } | ||
712 | |||
713 | static const struct net_device_ops sgiseeq_netdev_ops = { | ||
714 | .ndo_open = sgiseeq_open, | ||
715 | .ndo_stop = sgiseeq_close, | ||
716 | .ndo_start_xmit = sgiseeq_start_xmit, | ||
717 | .ndo_tx_timeout = timeout, | ||
718 | .ndo_set_multicast_list = sgiseeq_set_multicast, | ||
719 | .ndo_set_mac_address = sgiseeq_set_mac_address, | ||
720 | .ndo_change_mtu = eth_change_mtu, | ||
721 | .ndo_validate_addr = eth_validate_addr, | ||
722 | }; | ||
723 | |||
724 | static int __devinit sgiseeq_probe(struct platform_device *pdev) | ||
725 | { | ||
726 | struct sgiseeq_platform_data *pd = pdev->dev.platform_data; | ||
727 | struct hpc3_regs *hpcregs = pd->hpc; | ||
728 | struct sgiseeq_init_block *sr; | ||
729 | unsigned int irq = pd->irq; | ||
730 | struct sgiseeq_private *sp; | ||
731 | struct net_device *dev; | ||
732 | int err; | ||
733 | |||
734 | dev = alloc_etherdev(sizeof (struct sgiseeq_private)); | ||
735 | if (!dev) { | ||
736 | printk(KERN_ERR "Sgiseeq: Etherdev alloc failed, aborting.\n"); | ||
737 | err = -ENOMEM; | ||
738 | goto err_out; | ||
739 | } | ||
740 | |||
741 | platform_set_drvdata(pdev, dev); | ||
742 | sp = netdev_priv(dev); | ||
743 | |||
744 | /* Make private data page aligned */ | ||
745 | sr = dma_alloc_noncoherent(&pdev->dev, sizeof(*sp->srings), | ||
746 | &sp->srings_dma, GFP_KERNEL); | ||
747 | if (!sr) { | ||
748 | printk(KERN_ERR "Sgiseeq: Page alloc failed, aborting.\n"); | ||
749 | err = -ENOMEM; | ||
750 | goto err_out_free_dev; | ||
751 | } | ||
752 | sp->srings = sr; | ||
753 | sp->rx_desc = sp->srings->rxvector; | ||
754 | sp->tx_desc = sp->srings->txvector; | ||
755 | |||
756 | /* A couple calculations now, saves many cycles later. */ | ||
757 | setup_rx_ring(dev, sp->rx_desc, SEEQ_RX_BUFFERS); | ||
758 | setup_tx_ring(dev, sp->tx_desc, SEEQ_TX_BUFFERS); | ||
759 | |||
760 | memcpy(dev->dev_addr, pd->mac, ETH_ALEN); | ||
761 | |||
762 | #ifdef DEBUG | ||
763 | gpriv = sp; | ||
764 | gdev = dev; | ||
765 | #endif | ||
766 | sp->sregs = (struct sgiseeq_regs *) &hpcregs->eth_ext[0]; | ||
767 | sp->hregs = &hpcregs->ethregs; | ||
768 | sp->name = sgiseeqstr; | ||
769 | sp->mode = SEEQ_RCMD_RBCAST; | ||
770 | |||
771 | /* Setup PIO and DMA transfer timing */ | ||
772 | sp->hregs->pconfig = 0x161; | ||
773 | sp->hregs->dconfig = HPC3_EDCFG_FIRQ | HPC3_EDCFG_FEOP | | ||
774 | HPC3_EDCFG_FRXDC | HPC3_EDCFG_PTO | 0x026; | ||
775 | |||
776 | /* Setup PIO and DMA transfer timing */ | ||
777 | sp->hregs->pconfig = 0x161; | ||
778 | sp->hregs->dconfig = HPC3_EDCFG_FIRQ | HPC3_EDCFG_FEOP | | ||
779 | HPC3_EDCFG_FRXDC | HPC3_EDCFG_PTO | 0x026; | ||
780 | |||
781 | /* Reset the chip. */ | ||
782 | hpc3_eth_reset(sp->hregs); | ||
783 | |||
784 | sp->is_edlc = !(sp->sregs->rw.rregs.collision_tx[0] & 0xff); | ||
785 | if (sp->is_edlc) | ||
786 | sp->control = SEEQ_CTRL_XCNT | SEEQ_CTRL_ACCNT | | ||
787 | SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT | | ||
788 | SEEQ_CTRL_ENCARR; | ||
789 | |||
790 | dev->netdev_ops = &sgiseeq_netdev_ops; | ||
791 | dev->watchdog_timeo = (200 * HZ) / 1000; | ||
792 | dev->irq = irq; | ||
793 | |||
794 | if (register_netdev(dev)) { | ||
795 | printk(KERN_ERR "Sgiseeq: Cannot register net device, " | ||
796 | "aborting.\n"); | ||
797 | err = -ENODEV; | ||
798 | goto err_out_free_page; | ||
799 | } | ||
800 | |||
801 | printk(KERN_INFO "%s: %s %pM\n", dev->name, sgiseeqstr, dev->dev_addr); | ||
802 | |||
803 | return 0; | ||
804 | |||
805 | err_out_free_page: | ||
806 | free_page((unsigned long) sp->srings); | ||
807 | err_out_free_dev: | ||
808 | free_netdev(dev); | ||
809 | |||
810 | err_out: | ||
811 | return err; | ||
812 | } | ||
813 | |||
814 | static int __exit sgiseeq_remove(struct platform_device *pdev) | ||
815 | { | ||
816 | struct net_device *dev = platform_get_drvdata(pdev); | ||
817 | struct sgiseeq_private *sp = netdev_priv(dev); | ||
818 | |||
819 | unregister_netdev(dev); | ||
820 | dma_free_noncoherent(&pdev->dev, sizeof(*sp->srings), sp->srings, | ||
821 | sp->srings_dma); | ||
822 | free_netdev(dev); | ||
823 | platform_set_drvdata(pdev, NULL); | ||
824 | |||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | static struct platform_driver sgiseeq_driver = { | ||
829 | .probe = sgiseeq_probe, | ||
830 | .remove = __exit_p(sgiseeq_remove), | ||
831 | .driver = { | ||
832 | .name = "sgiseeq", | ||
833 | .owner = THIS_MODULE, | ||
834 | } | ||
835 | }; | ||
836 | |||
837 | static int __init sgiseeq_module_init(void) | ||
838 | { | ||
839 | if (platform_driver_register(&sgiseeq_driver)) { | ||
840 | printk(KERN_ERR "Driver registration failed\n"); | ||
841 | return -ENODEV; | ||
842 | } | ||
843 | |||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | static void __exit sgiseeq_module_exit(void) | ||
848 | { | ||
849 | platform_driver_unregister(&sgiseeq_driver); | ||
850 | } | ||
851 | |||
852 | module_init(sgiseeq_module_init); | ||
853 | module_exit(sgiseeq_module_exit); | ||
854 | |||
855 | MODULE_DESCRIPTION("SGI Seeq 8003 driver"); | ||
856 | MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>"); | ||
857 | MODULE_LICENSE("GPL"); | ||
858 | MODULE_ALIAS("platform:sgiseeq"); | ||
diff --git a/drivers/net/ethernet/seeq/sgiseeq.h b/drivers/net/ethernet/seeq/sgiseeq.h new file mode 100644 index 000000000000..2211e2987a8d --- /dev/null +++ b/drivers/net/ethernet/seeq/sgiseeq.h | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * sgiseeq.h: Defines for the Seeq8003 ethernet controller. | ||
3 | * | ||
4 | * Copyright (C) 1996 David S. Miller (davem@davemloft.net) | ||
5 | */ | ||
6 | #ifndef _SGISEEQ_H | ||
7 | #define _SGISEEQ_H | ||
8 | |||
9 | struct sgiseeq_wregs { | ||
10 | volatile unsigned int multicase_high[2]; | ||
11 | volatile unsigned int frame_gap; | ||
12 | volatile unsigned int control; | ||
13 | }; | ||
14 | |||
15 | struct sgiseeq_rregs { | ||
16 | volatile unsigned int collision_tx[2]; | ||
17 | volatile unsigned int collision_all[2]; | ||
18 | volatile unsigned int _unused0; | ||
19 | volatile unsigned int rflags; | ||
20 | }; | ||
21 | |||
22 | struct sgiseeq_regs { | ||
23 | union { | ||
24 | volatile unsigned int eth_addr[6]; | ||
25 | volatile unsigned int multicast_low[6]; | ||
26 | struct sgiseeq_wregs wregs; | ||
27 | struct sgiseeq_rregs rregs; | ||
28 | } rw; | ||
29 | volatile unsigned int rstat; | ||
30 | volatile unsigned int tstat; | ||
31 | }; | ||
32 | |||
33 | /* Seeq8003 receive status register */ | ||
34 | #define SEEQ_RSTAT_OVERF 0x001 /* Overflow */ | ||
35 | #define SEEQ_RSTAT_CERROR 0x002 /* CRC error */ | ||
36 | #define SEEQ_RSTAT_DERROR 0x004 /* Dribble error */ | ||
37 | #define SEEQ_RSTAT_SFRAME 0x008 /* Short frame */ | ||
38 | #define SEEQ_RSTAT_REOF 0x010 /* Received end of frame */ | ||
39 | #define SEEQ_RSTAT_FIG 0x020 /* Frame is good */ | ||
40 | #define SEEQ_RSTAT_TIMEO 0x040 /* Timeout, or late receive */ | ||
41 | #define SEEQ_RSTAT_WHICH 0x080 /* Which status, 1=old 0=new */ | ||
42 | #define SEEQ_RSTAT_LITTLE 0x100 /* DMA is done in little endian format */ | ||
43 | #define SEEQ_RSTAT_SDMA 0x200 /* DMA has started */ | ||
44 | #define SEEQ_RSTAT_ADMA 0x400 /* DMA is active */ | ||
45 | #define SEEQ_RSTAT_ROVERF 0x800 /* Receive buffer overflow */ | ||
46 | |||
47 | /* Seeq8003 receive command register */ | ||
48 | #define SEEQ_RCMD_RDISAB 0x000 /* Disable receiver on the Seeq8003 */ | ||
49 | #define SEEQ_RCMD_IOVERF 0x001 /* IRQ on buffer overflows */ | ||
50 | #define SEEQ_RCMD_ICRC 0x002 /* IRQ on CRC errors */ | ||
51 | #define SEEQ_RCMD_IDRIB 0x004 /* IRQ on dribble errors */ | ||
52 | #define SEEQ_RCMD_ISHORT 0x008 /* IRQ on short frames */ | ||
53 | #define SEEQ_RCMD_IEOF 0x010 /* IRQ on end of frame */ | ||
54 | #define SEEQ_RCMD_IGOOD 0x020 /* IRQ on good frames */ | ||
55 | #define SEEQ_RCMD_RANY 0x040 /* Receive any frame */ | ||
56 | #define SEEQ_RCMD_RBCAST 0x080 /* Receive broadcasts */ | ||
57 | #define SEEQ_RCMD_RBMCAST 0x0c0 /* Receive broadcasts/multicasts */ | ||
58 | |||
59 | /* Seeq8003 transmit status register */ | ||
60 | #define SEEQ_TSTAT_UFLOW 0x001 /* Transmit buffer underflow */ | ||
61 | #define SEEQ_TSTAT_CLS 0x002 /* Collision detected */ | ||
62 | #define SEEQ_TSTAT_R16 0x004 /* Did 16 retries to tx a frame */ | ||
63 | #define SEEQ_TSTAT_PTRANS 0x008 /* Packet was transmitted ok */ | ||
64 | #define SEEQ_TSTAT_LCLS 0x010 /* Late collision occurred */ | ||
65 | #define SEEQ_TSTAT_WHICH 0x080 /* Which status, 1=old 0=new */ | ||
66 | #define SEEQ_TSTAT_TLE 0x100 /* DMA is done in little endian format */ | ||
67 | #define SEEQ_TSTAT_SDMA 0x200 /* DMA has started */ | ||
68 | #define SEEQ_TSTAT_ADMA 0x400 /* DMA is active */ | ||
69 | |||
70 | /* Seeq8003 transmit command register */ | ||
71 | #define SEEQ_TCMD_RB0 0x00 /* Register bank zero w/station addr */ | ||
72 | #define SEEQ_TCMD_IUF 0x01 /* IRQ on tx underflow */ | ||
73 | #define SEEQ_TCMD_IC 0x02 /* IRQ on collisions */ | ||
74 | #define SEEQ_TCMD_I16 0x04 /* IRQ after 16 failed attempts to tx frame */ | ||
75 | #define SEEQ_TCMD_IPT 0x08 /* IRQ when packet successfully transmitted */ | ||
76 | #define SEEQ_TCMD_RB1 0x20 /* Register bank one w/multi-cast low byte */ | ||
77 | #define SEEQ_TCMD_RB2 0x40 /* Register bank two w/multi-cast high byte */ | ||
78 | |||
79 | /* Seeq8003 control register */ | ||
80 | #define SEEQ_CTRL_XCNT 0x01 | ||
81 | #define SEEQ_CTRL_ACCNT 0x02 | ||
82 | #define SEEQ_CTRL_SFLAG 0x04 | ||
83 | #define SEEQ_CTRL_EMULTI 0x08 | ||
84 | #define SEEQ_CTRL_ESHORT 0x10 | ||
85 | #define SEEQ_CTRL_ENCARR 0x20 | ||
86 | |||
87 | /* Seeq8003 control registers on the SGI Hollywood HPC. */ | ||
88 | #define SEEQ_HPIO_P1BITS 0x00000001 /* cycles to stay in P1 phase for PIO */ | ||
89 | #define SEEQ_HPIO_P2BITS 0x00000060 /* cycles to stay in P2 phase for PIO */ | ||
90 | #define SEEQ_HPIO_P3BITS 0x00000100 /* cycles to stay in P3 phase for PIO */ | ||
91 | #define SEEQ_HDMA_D1BITS 0x00000006 /* cycles to stay in D1 phase for DMA */ | ||
92 | #define SEEQ_HDMA_D2BITS 0x00000020 /* cycles to stay in D2 phase for DMA */ | ||
93 | #define SEEQ_HDMA_D3BITS 0x00000000 /* cycles to stay in D3 phase for DMA */ | ||
94 | #define SEEQ_HDMA_TIMEO 0x00030000 /* cycles for DMA timeout */ | ||
95 | #define SEEQ_HCTL_NORM 0x00000000 /* Normal operation mode */ | ||
96 | #define SEEQ_HCTL_RESET 0x00000001 /* Reset Seeq8003 and HPC interface */ | ||
97 | #define SEEQ_HCTL_IPEND 0x00000002 /* IRQ is pending for the chip */ | ||
98 | #define SEEQ_HCTL_IPG 0x00001000 /* Inter-packet gap */ | ||
99 | #define SEEQ_HCTL_RFIX 0x00002000 /* At rxdc, clear end-of-packet */ | ||
100 | #define SEEQ_HCTL_EFIX 0x00004000 /* fixes intr status bit settings */ | ||
101 | #define SEEQ_HCTL_IFIX 0x00008000 /* enable startup timeouts */ | ||
102 | |||
103 | #endif /* !(_SGISEEQ_H) */ | ||