blob: 12a8ffffeb03d3e448c8cab167f80c7d42a3dbf9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* 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
17static 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
Jeff Garzik6aa20a22006-09-13 13:24:59 -040023
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 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/slab.h>
41#include <linux/string.h>
42#include <linux/init.h>
43#include <linux/delay.h>
44#include <linux/errno.h>
45#include <linux/netdevice.h>
46#include <linux/etherdevice.h>
47#include <linux/skbuff.h>
48#include <linux/bitops.h>
Marcelo Feitoza Parisiff5688a2006-01-09 18:37:15 -080049#include <linux/jiffies.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51#include <asm/system.h>
52#include <asm/io.h>
53#include <asm/dma.h>
54
55#include "seeq8005.h"
56
57/* First, a few definitions that the brave might change. */
58/* A zero-terminated list of I/O addresses to be probed. */
59static unsigned int seeq8005_portlist[] __initdata =
60 { 0x300, 0x320, 0x340, 0x360, 0};
61
62/* use 0 for production, 1 for verification, >2 for debug */
63#ifndef NET_DEBUG
64#define NET_DEBUG 1
65#endif
66static unsigned int net_debug = NET_DEBUG;
67
68/* Information that need to be kept for each board. */
69struct net_local {
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 unsigned short receive_ptr; /* What address in packet memory do we expect a recv_pkt_header? */
71 long open_time; /* Useless example local info. */
72};
73
74/* The station (ethernet) address prefix, used for IDing the board. */
75#define SA_ADDR0 0x00
76#define SA_ADDR1 0x80
77#define SA_ADDR2 0x4b
78
79/* Index to functions, as function prototypes. */
80
81static int seeq8005_probe1(struct net_device *dev, int ioaddr);
82static int seeq8005_open(struct net_device *dev);
83static void seeq8005_timeout(struct net_device *dev);
84static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +010085static irqreturn_t seeq8005_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086static void seeq8005_rx(struct net_device *dev);
87static int seeq8005_close(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088static 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)
92static void hardware_send_packet(struct net_device *dev, char *buf, int length);
93extern void seeq8005_init(struct net_device *dev, int startp);
94static inline void wait_for_buffer(struct net_device *dev);
95
Jeff Garzik6aa20a22006-09-13 13:24:59 -040096
Linus Torvalds1da177e2005-04-16 15:20:36 -070097/* 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
102static int io = 0x320;
103static int irq = 10;
104
105struct 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;
139out1:
140 release_region(dev->base_addr, SEEQ8005_IO_EXTENT);
141out:
142 free_netdev(dev);
143 return ERR_PTR(err);
144}
145
146/* This is the real probe routine. Linux has a history of friendly device
147 probes on the ISA bus. A good device probes avoids doing writes, and
148 verifies that the correct device exists and functions. */
149
150static int __init seeq8005_probe1(struct net_device *dev, int ioaddr)
151{
152 static unsigned version_printed;
153 int i,j;
154 unsigned char SA_prom[32];
155 int old_cfg1;
156 int old_cfg2;
157 int old_stat;
158 int old_dmaar;
159 int old_rear;
160 int retval;
161
162 if (!request_region(ioaddr, SEEQ8005_IO_EXTENT, "seeq8005"))
163 return -ENODEV;
164
165 if (net_debug>1)
166 printk("seeq8005: probing at 0x%x\n",ioaddr);
167
168 old_stat = inw(SEEQ_STATUS); /* read status register */
169 if (old_stat == 0xffff) {
170 retval = -ENODEV;
171 goto out; /* assume that 0xffff == no device */
172 }
173 if ( (old_stat & 0x1800) != 0x1800 ) { /* assume that unused bits are 1, as my manual says */
174 if (net_debug>1) {
175 printk("seeq8005: reserved stat bits != 0x1800\n");
176 printk(" == 0x%04x\n",old_stat);
177 }
178 retval = -ENODEV;
179 goto out;
180 }
181
182 old_rear = inw(SEEQ_REA);
183 if (old_rear == 0xffff) {
184 outw(0,SEEQ_REA);
185 if (inw(SEEQ_REA) == 0xffff) { /* assume that 0xffff == no device */
186 retval = -ENODEV;
187 goto out;
188 }
189 } else if ((old_rear & 0xff00) != 0xff00) { /* assume that unused bits are 1 */
190 if (net_debug>1) {
191 printk("seeq8005: unused rear bits != 0xff00\n");
192 printk(" == 0x%04x\n",old_rear);
193 }
194 retval = -ENODEV;
195 goto out;
196 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400197
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 old_cfg2 = inw(SEEQ_CFG2); /* read CFG2 register */
199 old_cfg1 = inw(SEEQ_CFG1);
200 old_dmaar = inw(SEEQ_DMAAR);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400201
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 if (net_debug>4) {
203 printk("seeq8005: stat = 0x%04x\n",old_stat);
204 printk("seeq8005: cfg1 = 0x%04x\n",old_cfg1);
205 printk("seeq8005: cfg2 = 0x%04x\n",old_cfg2);
206 printk("seeq8005: raer = 0x%04x\n",old_rear);
207 printk("seeq8005: dmaar= 0x%04x\n",old_dmaar);
208 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); /* setup for reading PROM */
211 outw( 0, SEEQ_DMAAR); /* set starting PROM address */
212 outw( SEEQCFG1_BUFFER_PROM, SEEQ_CFG1); /* set buffer to look at PROM */
213
214
215 j=0;
216 for(i=0; i <32; i++) {
217 j+= SA_prom[i] = inw(SEEQ_BUFFER) & 0xff;
218 }
219
220#if 0
221 /* untested because I only have the one card */
222 if ( (j&0xff) != 0 ) { /* checksum appears to be 8bit = 0 */
223 if (net_debug>1) { /* check this before deciding that we have a card */
224 printk("seeq8005: prom sum error\n");
225 }
226 outw( old_stat, SEEQ_STATUS);
227 outw( old_dmaar, SEEQ_DMAAR);
228 outw( old_cfg1, SEEQ_CFG1);
229 retval = -ENODEV;
230 goto out;
231 }
232#endif
233
234 outw( SEEQCFG2_RESET, SEEQ_CFG2); /* reset the card */
235 udelay(5);
236 outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400237
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 if (net_debug) {
239 printk("seeq8005: prom sum = 0x%08x\n",j);
240 for(j=0; j<32; j+=16) {
241 printk("seeq8005: prom %02x: ",j);
242 for(i=0;i<16;i++) {
243 printk("%02x ",SA_prom[j|i]);
244 }
245 printk(" ");
246 for(i=0;i<16;i++) {
247 if ((SA_prom[j|i]>31)&&(SA_prom[j|i]<127)) {
248 printk("%c", SA_prom[j|i]);
249 } else {
250 printk(" ");
251 }
252 }
253 printk("\n");
254 }
255 }
256
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400257#if 0
258 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 * testing the packet buffer memory doesn't work yet
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400260 * but all other buffer accesses do
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 * - fixing is not a priority
262 */
263 if (net_debug>1) { /* test packet buffer memory */
264 printk("seeq8005: testing packet buffer ... ");
265 outw( SEEQCFG1_BUFFER_BUFFER, SEEQ_CFG1);
266 outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
267 outw( 0 , SEEQ_DMAAR);
268 for(i=0;i<32768;i++) {
269 outw(0x5a5a, SEEQ_BUFFER);
270 }
271 j=jiffies+HZ;
272 while ( ((inw(SEEQ_STATUS) & SEEQSTAT_FIFO_EMPTY) != SEEQSTAT_FIFO_EMPTY) && time_before(jiffies, j) )
273 mb();
274 outw( 0 , SEEQ_DMAAR);
275 while ( ((inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, j+HZ))
276 mb();
277 if ( (inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT)
278 outw( SEEQCMD_WINDOW_INT_ACK | (inw(SEEQ_STATUS)& SEEQCMD_INT_MASK), SEEQ_CMD);
279 outw( SEEQCMD_FIFO_READ | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
280 j=0;
281 for(i=0;i<32768;i++) {
282 if (inw(SEEQ_BUFFER) != 0x5a5a)
283 j++;
284 }
285 if (j) {
286 printk("%i\n",j);
287 } else {
288 printk("ok.\n");
289 }
290 }
291#endif
292
293 if (net_debug && version_printed++ == 0)
294 printk(version);
295
296 printk("%s: %s found at %#3x, ", dev->name, "seeq8005", ioaddr);
297
298 /* Fill in the 'dev' fields. */
299 dev->base_addr = ioaddr;
300 dev->irq = irq;
301
302 /* Retrieve and print the ethernet address. */
303 for (i = 0; i < 6; i++)
Joe Perches0795af52007-10-03 17:59:30 -0700304 dev->dev_addr[i] = SA_prom[i+6];
Johannes Berge1749612008-10-27 15:59:26 -0700305 printk("%pM", dev->dev_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
307 if (dev->irq == 0xff)
308 ; /* Do nothing: a user-level program will set it. */
309 else if (dev->irq < 2) { /* "Auto-IRQ" */
310 unsigned long cookie = probe_irq_on();
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400311
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 outw( SEEQCMD_RX_INT_EN | SEEQCMD_SET_RX_ON | SEEQCMD_SET_RX_OFF, SEEQ_CMD );
313
314 dev->irq = probe_irq_off(cookie);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400315
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 if (net_debug >= 2)
317 printk(" autoirq is %d\n", dev->irq);
318 } else if (dev->irq == 2)
319 /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400320 * or don't know which one to set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 */
322 dev->irq = 9;
323
324#if 0
325 {
326 int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005", dev);
327 if (irqval) {
328 printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
329 dev->irq, irqval);
330 retval = -EAGAIN;
331 goto out;
332 }
333 }
334#endif
335 dev->open = seeq8005_open;
336 dev->stop = seeq8005_close;
337 dev->hard_start_xmit = seeq8005_send_packet;
338 dev->tx_timeout = seeq8005_timeout;
339 dev->watchdog_timeo = HZ/20;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 dev->set_multicast_list = set_multicast_list;
341 dev->flags &= ~IFF_MULTICAST;
342
343 return 0;
344out:
345 release_region(ioaddr, SEEQ8005_IO_EXTENT);
346 return retval;
347}
348
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350/* Open/initialize the board. This is called (in the current kernel)
351 sometime after booting when the 'ifconfig' program is run.
352
353 This routine should set everything up anew at each open, even
354 registers that "should" only need to be set once at boot, so that
355 there is non-reboot way to recover if something goes wrong.
356 */
357static int seeq8005_open(struct net_device *dev)
358{
359 struct net_local *lp = netdev_priv(dev);
360
361 {
362 int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005", dev);
363 if (irqval) {
364 printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
365 dev->irq, irqval);
366 return -EAGAIN;
367 }
368 }
369
370 /* Reset the hardware here. Don't forget to set the station address. */
371 seeq8005_init(dev, 1);
372
373 lp->open_time = jiffies;
374
375 netif_start_queue(dev);
376 return 0;
377}
378
379static void seeq8005_timeout(struct net_device *dev)
380{
381 int ioaddr = dev->base_addr;
382 printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
383 tx_done(dev) ? "IRQ conflict" : "network cable problem");
384 /* Try to restart the adaptor. */
385 seeq8005_init(dev, 1);
386 dev->trans_start = jiffies;
387 netif_wake_queue(dev);
388}
389
390static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
391{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 short length = skb->len;
393 unsigned char *buf;
394
395 if (length < ETH_ZLEN) {
Herbert Xu5b057c62006-06-23 02:06:41 -0700396 if (skb_padto(skb, ETH_ZLEN))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 return 0;
398 length = ETH_ZLEN;
399 }
400 buf = skb->data;
401
402 /* Block a timer-based transmit from overlapping */
403 netif_stop_queue(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400404
405 hardware_send_packet(dev, buf, length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 dev->trans_start = jiffies;
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700407 dev->stats.tx_bytes += length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 dev_kfree_skb (skb);
409 /* You might need to clean up and record Tx statistics here. */
410
411 return 0;
412}
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400413
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414/*
415 * wait_for_buffer
416 *
417 * This routine waits for the SEEQ chip to assert that the FIFO is ready
418 * by checking for a window interrupt, and then clearing it. This has to
419 * occur in the interrupt handler!
420 */
421inline void wait_for_buffer(struct net_device * dev)
422{
423 int ioaddr = dev->base_addr;
424 unsigned long tmp;
425 int status;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400426
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 tmp = jiffies + HZ;
428 while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, tmp))
429 cpu_relax();
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 if ( (status & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT)
432 outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
433}
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400434
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435/* The typical workload of the driver:
436 Handle the network interface interrupts. */
David Howells7d12e782006-10-05 14:55:46 +0100437static irqreturn_t seeq8005_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438{
439 struct net_device *dev = dev_id;
440 struct net_local *lp;
441 int ioaddr, status, boguscount = 0;
442 int handled = 0;
443
444 ioaddr = dev->base_addr;
445 lp = netdev_priv(dev);
446
447 status = inw(SEEQ_STATUS);
448 do {
449 if (net_debug >2) {
450 printk("%s: int, status=0x%04x\n",dev->name,status);
451 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400452
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 if (status & SEEQSTAT_WINDOW_INT) {
454 handled = 1;
455 outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
456 if (net_debug) {
457 printk("%s: window int!\n",dev->name);
458 }
459 }
460 if (status & SEEQSTAT_TX_INT) {
461 handled = 1;
462 outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700463 dev->stats.tx_packets++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 netif_wake_queue(dev); /* Inform upper layers. */
465 }
466 if (status & SEEQSTAT_RX_INT) {
467 handled = 1;
468 /* Got a packet(s). */
469 seeq8005_rx(dev);
470 }
471 status = inw(SEEQ_STATUS);
472 } while ( (++boguscount < 10) && (status & SEEQSTAT_ANY_INT)) ;
473
474 if(net_debug>2) {
475 printk("%s: eoi\n",dev->name);
476 }
477 return IRQ_RETVAL(handled);
478}
479
480/* We have a good packet(s), get it/them out of the buffers. */
481static void seeq8005_rx(struct net_device *dev)
482{
483 struct net_local *lp = netdev_priv(dev);
484 int boguscount = 10;
485 int pkt_hdr;
486 int ioaddr = dev->base_addr;
487
488 do {
489 int next_packet;
490 int pkt_len;
491 int i;
492 int status;
493
494 status = inw(SEEQ_STATUS);
495 outw( lp->receive_ptr, SEEQ_DMAAR);
496 outw(SEEQCMD_FIFO_READ | SEEQCMD_RX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
497 wait_for_buffer(dev);
498 next_packet = ntohs(inw(SEEQ_BUFFER));
499 pkt_hdr = inw(SEEQ_BUFFER);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400500
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 if (net_debug>2) {
502 printk("%s: 0x%04x recv next=0x%04x, hdr=0x%04x\n",dev->name,lp->receive_ptr,next_packet,pkt_hdr);
503 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400504
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 if ((next_packet == 0) || ((pkt_hdr & SEEQPKTH_CHAIN)==0)) { /* Read all the frames? */
506 return; /* Done for now */
507 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400508
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 if ((pkt_hdr & SEEQPKTS_DONE)==0)
510 break;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400511
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 if (next_packet < lp->receive_ptr) {
513 pkt_len = (next_packet + 0x10000 - ((DEFAULT_TEA+1)<<8)) - lp->receive_ptr - 4;
514 } else {
515 pkt_len = next_packet - lp->receive_ptr - 4;
516 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400517
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 if (next_packet < ((DEFAULT_TEA+1)<<8)) { /* is the next_packet address sane? */
519 printk("%s: recv packet ring corrupt, resetting board\n",dev->name);
520 seeq8005_init(dev,1);
521 return;
522 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400523
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 lp->receive_ptr = next_packet;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400525
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 if (net_debug>2) {
527 printk("%s: recv len=0x%04x\n",dev->name,pkt_len);
528 }
529
530 if (pkt_hdr & SEEQPKTS_ANY_ERROR) { /* There was an error. */
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700531 dev->stats.rx_errors++;
532 if (pkt_hdr & SEEQPKTS_SHORT) dev->stats.rx_frame_errors++;
533 if (pkt_hdr & SEEQPKTS_DRIB) dev->stats.rx_frame_errors++;
534 if (pkt_hdr & SEEQPKTS_OVERSIZE) dev->stats.rx_over_errors++;
535 if (pkt_hdr & SEEQPKTS_CRC_ERR) dev->stats.rx_crc_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 /* skip over this packet */
537 outw( SEEQCMD_FIFO_WRITE | SEEQCMD_DMA_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
538 outw( (lp->receive_ptr & 0xff00)>>8, SEEQ_REA);
539 } else {
540 /* Malloc up new buffer. */
541 struct sk_buff *skb;
542 unsigned char *buf;
543
544 skb = dev_alloc_skb(pkt_len);
545 if (skb == NULL) {
546 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700547 dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 break;
549 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 skb_reserve(skb, 2); /* align data on 16 byte */
551 buf = skb_put(skb,pkt_len);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 insw(SEEQ_BUFFER, buf, (pkt_len + 1) >> 1);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400554
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 if (net_debug>2) {
556 char * p = buf;
557 printk("%s: recv ",dev->name);
558 for(i=0;i<14;i++) {
559 printk("%02x ",*(p++)&0xff);
560 }
561 printk("\n");
562 }
563
564 skb->protocol=eth_type_trans(skb,dev);
565 netif_rx(skb);
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700566 dev->stats.rx_packets++;
567 dev->stats.rx_bytes += pkt_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 }
569 } while ((--boguscount) && (pkt_hdr & SEEQPKTH_CHAIN));
570
571 /* If any worth-while packets have been received, netif_rx()
572 has done a mark_bh(NET_BH) for us and will work on them
573 when we get to the bottom-half routine. */
574 return;
575}
576
577/* The inverse routine to net_open(). */
578static int seeq8005_close(struct net_device *dev)
579{
580 struct net_local *lp = netdev_priv(dev);
581 int ioaddr = dev->base_addr;
582
583 lp->open_time = 0;
584
585 netif_stop_queue(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400586
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 /* Flush the Tx and disable Rx here. */
588 outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
589
590 free_irq(dev->irq, dev);
591
592 /* Update the statistics here. */
593
594 return 0;
595
596}
597
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598/* Set or clear the multicast filter for this adaptor.
599 num_addrs == -1 Promiscuous mode, receive all packets
600 num_addrs == 0 Normal mode, clear multicast list
601 num_addrs > 0 Multicast mode, receive normal and MC packets, and do
602 best-effort filtering.
603 */
604static void set_multicast_list(struct net_device *dev)
605{
606/*
607 * I _could_ do up to 6 addresses here, but won't (yet?)
608 */
609
610#if 0
611 int ioaddr = dev->base_addr;
612/*
613 * hmm, not even sure if my matching works _anyway_ - seem to be receiving
614 * _everything_ . . .
615 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 if (num_addrs) { /* Enable promiscuous mode */
618 outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_ALL, SEEQ_CFG1);
619 dev->flags|=IFF_PROMISC;
620 } else { /* Disable promiscuous mode, use normal mode */
621 outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_BROAD, SEEQ_CFG1);
622 }
623#endif
624}
625
626void seeq8005_init(struct net_device *dev, int startp)
627{
628 struct net_local *lp = netdev_priv(dev);
629 int ioaddr = dev->base_addr;
630 int i;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400631
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 outw(SEEQCFG2_RESET, SEEQ_CFG2); /* reset device */
633 udelay(5);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400634
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
636 outw( 0, SEEQ_DMAAR); /* load start address into both low and high byte */
637/* wait_for_buffer(dev); */ /* I think that you only need a wait for memory buffer */
638 outw( SEEQCFG1_BUFFER_MAC0, SEEQ_CFG1);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400639
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 for(i=0;i<6;i++) { /* set Station address */
641 outb(dev->dev_addr[i], SEEQ_BUFFER);
642 udelay(2);
643 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400644
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 outw( SEEQCFG1_BUFFER_TEA, SEEQ_CFG1); /* set xmit end area pointer to 16K */
646 outb( DEFAULT_TEA, SEEQ_BUFFER); /* this gives us 16K of send buffer and 48K of recv buffer */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 lp->receive_ptr = (DEFAULT_TEA+1)<<8; /* so we can find our packet_header */
649 outw( lp->receive_ptr, SEEQ_RPR); /* Receive Pointer Register is set to recv buffer memory */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400650
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 outw( 0x00ff, SEEQ_REA); /* Receive Area End */
652
653 if (net_debug>4) {
654 printk("%s: SA0 = ",dev->name);
655
656 outw( SEEQCMD_FIFO_READ | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
657 outw( 0, SEEQ_DMAAR);
658 outw( SEEQCFG1_BUFFER_MAC0, SEEQ_CFG1);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400659
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 for(i=0;i<6;i++) {
661 printk("%02x ",inb(SEEQ_BUFFER));
662 }
663 printk("\n");
664 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400665
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 outw( SEEQCFG1_MAC0_EN | SEEQCFG1_MATCH_BROAD | SEEQCFG1_BUFFER_BUFFER, SEEQ_CFG1);
667 outw( SEEQCFG2_AUTO_REA | SEEQCFG2_CTRLO, SEEQ_CFG2);
668 outw( SEEQCMD_SET_RX_ON | SEEQCMD_TX_INT_EN | SEEQCMD_RX_INT_EN, SEEQ_CMD);
669
670 if (net_debug>4) {
671 int old_cfg1;
672 old_cfg1 = inw(SEEQ_CFG1);
673 printk("%s: stat = 0x%04x\n",dev->name,inw(SEEQ_STATUS));
674 printk("%s: cfg1 = 0x%04x\n",dev->name,old_cfg1);
675 printk("%s: cfg2 = 0x%04x\n",dev->name,inw(SEEQ_CFG2));
676 printk("%s: raer = 0x%04x\n",dev->name,inw(SEEQ_REA));
677 printk("%s: dmaar= 0x%04x\n",dev->name,inw(SEEQ_DMAAR));
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400678
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400680}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
682
683static void hardware_send_packet(struct net_device * dev, char *buf, int length)
684{
685 int ioaddr = dev->base_addr;
686 int status = inw(SEEQ_STATUS);
687 int transmit_ptr = 0;
Marcelo Feitoza Parisiff5688a2006-01-09 18:37:15 -0800688 unsigned long tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
690 if (net_debug>4) {
691 printk("%s: send 0x%04x\n",dev->name,length);
692 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400693
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 /* Set FIFO to writemode and set packet-buffer address */
695 outw( SEEQCMD_FIFO_WRITE | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
696 outw( transmit_ptr, SEEQ_DMAAR);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400697
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 /* output SEEQ Packet header barfage */
699 outw( htons(length + 4), SEEQ_BUFFER);
700 outw( SEEQPKTH_XMIT | SEEQPKTH_DATA_FOLLOWS | SEEQPKTH_XMIT_INT_EN, SEEQ_BUFFER );
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400701
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 /* blat the buffer */
703 outsw( SEEQ_BUFFER, buf, (length +1) >> 1);
704 /* paranoia !! */
705 outw( 0, SEEQ_BUFFER);
706 outw( 0, SEEQ_BUFFER);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400707
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 /* set address of start of transmit chain */
709 outw( transmit_ptr, SEEQ_TPR);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 /* drain FIFO */
712 tmp = jiffies;
Marcelo Feitoza Parisiff5688a2006-01-09 18:37:15 -0800713 while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && time_before(jiffies, tmp + HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 mb();
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400715
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 /* doit ! */
717 outw( SEEQCMD_WINDOW_INT_ACK | SEEQCMD_SET_TX_ON | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400718
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719}
720
721
722#ifdef MODULE
723
724static struct net_device *dev_seeq;
725MODULE_LICENSE("GPL");
726module_param(io, int, 0);
727module_param(irq, int, 0);
728MODULE_PARM_DESC(io, "SEEQ 8005 I/O base address");
729MODULE_PARM_DESC(irq, "SEEQ 8005 IRQ number");
730
Andrew Mortonc971ef42006-08-14 23:00:08 -0700731int __init init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732{
733 dev_seeq = seeq8005_probe(-1);
734 if (IS_ERR(dev_seeq))
735 return PTR_ERR(dev_seeq);
736 return 0;
737}
738
Al Viroafc8eb42006-06-14 18:50:53 -0400739void __exit cleanup_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740{
741 unregister_netdev(dev_seeq);
742 release_region(dev_seeq->base_addr, SEEQ8005_IO_EXTENT);
743 free_netdev(dev_seeq);
744}
745
746#endif /* MODULE */