blob: 4bce7c4f373ce8754964818a7a3c3f53ee535823 [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 {
70 struct net_device_stats stats;
71 unsigned short receive_ptr; /* What address in packet memory do we expect a recv_pkt_header? */
72 long open_time; /* Useless example local info. */
73};
74
75/* The station (ethernet) address prefix, used for IDing the board. */
76#define SA_ADDR0 0x00
77#define SA_ADDR1 0x80
78#define SA_ADDR2 0x4b
79
80/* Index to functions, as function prototypes. */
81
82static int seeq8005_probe1(struct net_device *dev, int ioaddr);
83static int seeq8005_open(struct net_device *dev);
84static void seeq8005_timeout(struct net_device *dev);
85static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +010086static irqreturn_t seeq8005_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087static void seeq8005_rx(struct net_device *dev);
88static int seeq8005_close(struct net_device *dev);
89static struct net_device_stats *seeq8005_get_stats(struct net_device *dev);
90static void set_multicast_list(struct net_device *dev);
91
92/* Example routines you must write ;->. */
93#define tx_done(dev) (inw(SEEQ_STATUS) & SEEQSTAT_TX_ON)
94static void hardware_send_packet(struct net_device *dev, char *buf, int length);
95extern void seeq8005_init(struct net_device *dev, int startp);
96static inline void wait_for_buffer(struct net_device *dev);
97
Jeff Garzik6aa20a22006-09-13 13:24:59 -040098
Linus Torvalds1da177e2005-04-16 15:20:36 -070099/* Check for a network adaptor of this type, and return '0' iff one exists.
100 If dev->base_addr == 0, probe all likely locations.
101 If dev->base_addr == 1, always return failure.
102 */
103
104static int io = 0x320;
105static int irq = 10;
106
107struct net_device * __init seeq8005_probe(int unit)
108{
109 struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
110 unsigned *port;
111 int err = 0;
112
113 if (!dev)
114 return ERR_PTR(-ENODEV);
115
116 if (unit >= 0) {
117 sprintf(dev->name, "eth%d", unit);
118 netdev_boot_setup_check(dev);
119 io = dev->base_addr;
120 irq = dev->irq;
121 }
122
123 if (io > 0x1ff) { /* Check a single specified location. */
124 err = seeq8005_probe1(dev, io);
125 } else if (io != 0) { /* Don't probe at all. */
126 err = -ENXIO;
127 } else {
128 for (port = seeq8005_portlist; *port; port++) {
129 if (seeq8005_probe1(dev, *port) == 0)
130 break;
131 }
132 if (!*port)
133 err = -ENODEV;
134 }
135 if (err)
136 goto out;
137 err = register_netdev(dev);
138 if (err)
139 goto out1;
140 return dev;
141out1:
142 release_region(dev->base_addr, SEEQ8005_IO_EXTENT);
143out:
144 free_netdev(dev);
145 return ERR_PTR(err);
146}
147
148/* This is the real probe routine. Linux has a history of friendly device
149 probes on the ISA bus. A good device probes avoids doing writes, and
150 verifies that the correct device exists and functions. */
151
152static int __init seeq8005_probe1(struct net_device *dev, int ioaddr)
153{
154 static unsigned version_printed;
155 int i,j;
156 unsigned char SA_prom[32];
157 int old_cfg1;
158 int old_cfg2;
159 int old_stat;
160 int old_dmaar;
161 int old_rear;
162 int retval;
163
164 if (!request_region(ioaddr, SEEQ8005_IO_EXTENT, "seeq8005"))
165 return -ENODEV;
166
167 if (net_debug>1)
168 printk("seeq8005: probing at 0x%x\n",ioaddr);
169
170 old_stat = inw(SEEQ_STATUS); /* read status register */
171 if (old_stat == 0xffff) {
172 retval = -ENODEV;
173 goto out; /* assume that 0xffff == no device */
174 }
175 if ( (old_stat & 0x1800) != 0x1800 ) { /* assume that unused bits are 1, as my manual says */
176 if (net_debug>1) {
177 printk("seeq8005: reserved stat bits != 0x1800\n");
178 printk(" == 0x%04x\n",old_stat);
179 }
180 retval = -ENODEV;
181 goto out;
182 }
183
184 old_rear = inw(SEEQ_REA);
185 if (old_rear == 0xffff) {
186 outw(0,SEEQ_REA);
187 if (inw(SEEQ_REA) == 0xffff) { /* assume that 0xffff == no device */
188 retval = -ENODEV;
189 goto out;
190 }
191 } else if ((old_rear & 0xff00) != 0xff00) { /* assume that unused bits are 1 */
192 if (net_debug>1) {
193 printk("seeq8005: unused rear bits != 0xff00\n");
194 printk(" == 0x%04x\n",old_rear);
195 }
196 retval = -ENODEV;
197 goto out;
198 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400199
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 old_cfg2 = inw(SEEQ_CFG2); /* read CFG2 register */
201 old_cfg1 = inw(SEEQ_CFG1);
202 old_dmaar = inw(SEEQ_DMAAR);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 if (net_debug>4) {
205 printk("seeq8005: stat = 0x%04x\n",old_stat);
206 printk("seeq8005: cfg1 = 0x%04x\n",old_cfg1);
207 printk("seeq8005: cfg2 = 0x%04x\n",old_cfg2);
208 printk("seeq8005: raer = 0x%04x\n",old_rear);
209 printk("seeq8005: dmaar= 0x%04x\n",old_dmaar);
210 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400211
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); /* setup for reading PROM */
213 outw( 0, SEEQ_DMAAR); /* set starting PROM address */
214 outw( SEEQCFG1_BUFFER_PROM, SEEQ_CFG1); /* set buffer to look at PROM */
215
216
217 j=0;
218 for(i=0; i <32; i++) {
219 j+= SA_prom[i] = inw(SEEQ_BUFFER) & 0xff;
220 }
221
222#if 0
223 /* untested because I only have the one card */
224 if ( (j&0xff) != 0 ) { /* checksum appears to be 8bit = 0 */
225 if (net_debug>1) { /* check this before deciding that we have a card */
226 printk("seeq8005: prom sum error\n");
227 }
228 outw( old_stat, SEEQ_STATUS);
229 outw( old_dmaar, SEEQ_DMAAR);
230 outw( old_cfg1, SEEQ_CFG1);
231 retval = -ENODEV;
232 goto out;
233 }
234#endif
235
236 outw( SEEQCFG2_RESET, SEEQ_CFG2); /* reset the card */
237 udelay(5);
238 outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400239
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 if (net_debug) {
241 printk("seeq8005: prom sum = 0x%08x\n",j);
242 for(j=0; j<32; j+=16) {
243 printk("seeq8005: prom %02x: ",j);
244 for(i=0;i<16;i++) {
245 printk("%02x ",SA_prom[j|i]);
246 }
247 printk(" ");
248 for(i=0;i<16;i++) {
249 if ((SA_prom[j|i]>31)&&(SA_prom[j|i]<127)) {
250 printk("%c", SA_prom[j|i]);
251 } else {
252 printk(" ");
253 }
254 }
255 printk("\n");
256 }
257 }
258
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400259#if 0
260 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 * testing the packet buffer memory doesn't work yet
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400262 * but all other buffer accesses do
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 * - fixing is not a priority
264 */
265 if (net_debug>1) { /* test packet buffer memory */
266 printk("seeq8005: testing packet buffer ... ");
267 outw( SEEQCFG1_BUFFER_BUFFER, SEEQ_CFG1);
268 outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
269 outw( 0 , SEEQ_DMAAR);
270 for(i=0;i<32768;i++) {
271 outw(0x5a5a, SEEQ_BUFFER);
272 }
273 j=jiffies+HZ;
274 while ( ((inw(SEEQ_STATUS) & SEEQSTAT_FIFO_EMPTY) != SEEQSTAT_FIFO_EMPTY) && time_before(jiffies, j) )
275 mb();
276 outw( 0 , SEEQ_DMAAR);
277 while ( ((inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, j+HZ))
278 mb();
279 if ( (inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT)
280 outw( SEEQCMD_WINDOW_INT_ACK | (inw(SEEQ_STATUS)& SEEQCMD_INT_MASK), SEEQ_CMD);
281 outw( SEEQCMD_FIFO_READ | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
282 j=0;
283 for(i=0;i<32768;i++) {
284 if (inw(SEEQ_BUFFER) != 0x5a5a)
285 j++;
286 }
287 if (j) {
288 printk("%i\n",j);
289 } else {
290 printk("ok.\n");
291 }
292 }
293#endif
294
295 if (net_debug && version_printed++ == 0)
296 printk(version);
297
298 printk("%s: %s found at %#3x, ", dev->name, "seeq8005", ioaddr);
299
300 /* Fill in the 'dev' fields. */
301 dev->base_addr = ioaddr;
302 dev->irq = irq;
303
304 /* Retrieve and print the ethernet address. */
305 for (i = 0; i < 6; i++)
306 printk(" %2.2x", dev->dev_addr[i] = SA_prom[i+6]);
307
308 if (dev->irq == 0xff)
309 ; /* Do nothing: a user-level program will set it. */
310 else if (dev->irq < 2) { /* "Auto-IRQ" */
311 unsigned long cookie = probe_irq_on();
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 outw( SEEQCMD_RX_INT_EN | SEEQCMD_SET_RX_ON | SEEQCMD_SET_RX_OFF, SEEQ_CMD );
314
315 dev->irq = probe_irq_off(cookie);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400316
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 if (net_debug >= 2)
318 printk(" autoirq is %d\n", dev->irq);
319 } else if (dev->irq == 2)
320 /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400321 * or don't know which one to set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 */
323 dev->irq = 9;
324
325#if 0
326 {
327 int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005", dev);
328 if (irqval) {
329 printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
330 dev->irq, irqval);
331 retval = -EAGAIN;
332 goto out;
333 }
334 }
335#endif
336 dev->open = seeq8005_open;
337 dev->stop = seeq8005_close;
338 dev->hard_start_xmit = seeq8005_send_packet;
339 dev->tx_timeout = seeq8005_timeout;
340 dev->watchdog_timeo = HZ/20;
341 dev->get_stats = seeq8005_get_stats;
342 dev->set_multicast_list = set_multicast_list;
343 dev->flags &= ~IFF_MULTICAST;
344
345 return 0;
346out:
347 release_region(ioaddr, SEEQ8005_IO_EXTENT);
348 return retval;
349}
350
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400351
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352/* Open/initialize the board. This is called (in the current kernel)
353 sometime after booting when the 'ifconfig' program is run.
354
355 This routine should set everything up anew at each open, even
356 registers that "should" only need to be set once at boot, so that
357 there is non-reboot way to recover if something goes wrong.
358 */
359static int seeq8005_open(struct net_device *dev)
360{
361 struct net_local *lp = netdev_priv(dev);
362
363 {
364 int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005", dev);
365 if (irqval) {
366 printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
367 dev->irq, irqval);
368 return -EAGAIN;
369 }
370 }
371
372 /* Reset the hardware here. Don't forget to set the station address. */
373 seeq8005_init(dev, 1);
374
375 lp->open_time = jiffies;
376
377 netif_start_queue(dev);
378 return 0;
379}
380
381static void seeq8005_timeout(struct net_device *dev)
382{
383 int ioaddr = dev->base_addr;
384 printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
385 tx_done(dev) ? "IRQ conflict" : "network cable problem");
386 /* Try to restart the adaptor. */
387 seeq8005_init(dev, 1);
388 dev->trans_start = jiffies;
389 netif_wake_queue(dev);
390}
391
392static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
393{
394 struct net_local *lp = netdev_priv(dev);
395 short length = skb->len;
396 unsigned char *buf;
397
398 if (length < ETH_ZLEN) {
Herbert Xu5b057c62006-06-23 02:06:41 -0700399 if (skb_padto(skb, ETH_ZLEN))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 return 0;
401 length = ETH_ZLEN;
402 }
403 buf = skb->data;
404
405 /* Block a timer-based transmit from overlapping */
406 netif_stop_queue(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400407
408 hardware_send_packet(dev, buf, length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 dev->trans_start = jiffies;
410 lp->stats.tx_bytes += length;
411 dev_kfree_skb (skb);
412 /* You might need to clean up and record Tx statistics here. */
413
414 return 0;
415}
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417/*
418 * wait_for_buffer
419 *
420 * This routine waits for the SEEQ chip to assert that the FIFO is ready
421 * by checking for a window interrupt, and then clearing it. This has to
422 * occur in the interrupt handler!
423 */
424inline void wait_for_buffer(struct net_device * dev)
425{
426 int ioaddr = dev->base_addr;
427 unsigned long tmp;
428 int status;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400429
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 tmp = jiffies + HZ;
431 while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, tmp))
432 cpu_relax();
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400433
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 if ( (status & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT)
435 outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
436}
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400437
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438/* The typical workload of the driver:
439 Handle the network interface interrupts. */
David Howells7d12e782006-10-05 14:55:46 +0100440static irqreturn_t seeq8005_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441{
442 struct net_device *dev = dev_id;
443 struct net_local *lp;
444 int ioaddr, status, boguscount = 0;
445 int handled = 0;
446
447 ioaddr = dev->base_addr;
448 lp = netdev_priv(dev);
449
450 status = inw(SEEQ_STATUS);
451 do {
452 if (net_debug >2) {
453 printk("%s: int, status=0x%04x\n",dev->name,status);
454 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400455
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 if (status & SEEQSTAT_WINDOW_INT) {
457 handled = 1;
458 outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
459 if (net_debug) {
460 printk("%s: window int!\n",dev->name);
461 }
462 }
463 if (status & SEEQSTAT_TX_INT) {
464 handled = 1;
465 outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
466 lp->stats.tx_packets++;
467 netif_wake_queue(dev); /* Inform upper layers. */
468 }
469 if (status & SEEQSTAT_RX_INT) {
470 handled = 1;
471 /* Got a packet(s). */
472 seeq8005_rx(dev);
473 }
474 status = inw(SEEQ_STATUS);
475 } while ( (++boguscount < 10) && (status & SEEQSTAT_ANY_INT)) ;
476
477 if(net_debug>2) {
478 printk("%s: eoi\n",dev->name);
479 }
480 return IRQ_RETVAL(handled);
481}
482
483/* We have a good packet(s), get it/them out of the buffers. */
484static void seeq8005_rx(struct net_device *dev)
485{
486 struct net_local *lp = netdev_priv(dev);
487 int boguscount = 10;
488 int pkt_hdr;
489 int ioaddr = dev->base_addr;
490
491 do {
492 int next_packet;
493 int pkt_len;
494 int i;
495 int status;
496
497 status = inw(SEEQ_STATUS);
498 outw( lp->receive_ptr, SEEQ_DMAAR);
499 outw(SEEQCMD_FIFO_READ | SEEQCMD_RX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
500 wait_for_buffer(dev);
501 next_packet = ntohs(inw(SEEQ_BUFFER));
502 pkt_hdr = inw(SEEQ_BUFFER);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400503
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 if (net_debug>2) {
505 printk("%s: 0x%04x recv next=0x%04x, hdr=0x%04x\n",dev->name,lp->receive_ptr,next_packet,pkt_hdr);
506 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400507
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 if ((next_packet == 0) || ((pkt_hdr & SEEQPKTH_CHAIN)==0)) { /* Read all the frames? */
509 return; /* Done for now */
510 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400511
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 if ((pkt_hdr & SEEQPKTS_DONE)==0)
513 break;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 if (next_packet < lp->receive_ptr) {
516 pkt_len = (next_packet + 0x10000 - ((DEFAULT_TEA+1)<<8)) - lp->receive_ptr - 4;
517 } else {
518 pkt_len = next_packet - lp->receive_ptr - 4;
519 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400520
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 if (next_packet < ((DEFAULT_TEA+1)<<8)) { /* is the next_packet address sane? */
522 printk("%s: recv packet ring corrupt, resetting board\n",dev->name);
523 seeq8005_init(dev,1);
524 return;
525 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 lp->receive_ptr = next_packet;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400528
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 if (net_debug>2) {
530 printk("%s: recv len=0x%04x\n",dev->name,pkt_len);
531 }
532
533 if (pkt_hdr & SEEQPKTS_ANY_ERROR) { /* There was an error. */
534 lp->stats.rx_errors++;
535 if (pkt_hdr & SEEQPKTS_SHORT) lp->stats.rx_frame_errors++;
536 if (pkt_hdr & SEEQPKTS_DRIB) lp->stats.rx_frame_errors++;
537 if (pkt_hdr & SEEQPKTS_OVERSIZE) lp->stats.rx_over_errors++;
538 if (pkt_hdr & SEEQPKTS_CRC_ERR) lp->stats.rx_crc_errors++;
539 /* skip over this packet */
540 outw( SEEQCMD_FIFO_WRITE | SEEQCMD_DMA_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
541 outw( (lp->receive_ptr & 0xff00)>>8, SEEQ_REA);
542 } else {
543 /* Malloc up new buffer. */
544 struct sk_buff *skb;
545 unsigned char *buf;
546
547 skb = dev_alloc_skb(pkt_len);
548 if (skb == NULL) {
549 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
550 lp->stats.rx_dropped++;
551 break;
552 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 skb_reserve(skb, 2); /* align data on 16 byte */
554 buf = skb_put(skb,pkt_len);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400555
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 insw(SEEQ_BUFFER, buf, (pkt_len + 1) >> 1);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400557
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 if (net_debug>2) {
559 char * p = buf;
560 printk("%s: recv ",dev->name);
561 for(i=0;i<14;i++) {
562 printk("%02x ",*(p++)&0xff);
563 }
564 printk("\n");
565 }
566
567 skb->protocol=eth_type_trans(skb,dev);
568 netif_rx(skb);
569 dev->last_rx = jiffies;
570 lp->stats.rx_packets++;
571 lp->stats.rx_bytes += pkt_len;
572 }
573 } while ((--boguscount) && (pkt_hdr & SEEQPKTH_CHAIN));
574
575 /* If any worth-while packets have been received, netif_rx()
576 has done a mark_bh(NET_BH) for us and will work on them
577 when we get to the bottom-half routine. */
578 return;
579}
580
581/* The inverse routine to net_open(). */
582static int seeq8005_close(struct net_device *dev)
583{
584 struct net_local *lp = netdev_priv(dev);
585 int ioaddr = dev->base_addr;
586
587 lp->open_time = 0;
588
589 netif_stop_queue(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400590
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 /* Flush the Tx and disable Rx here. */
592 outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
593
594 free_irq(dev->irq, dev);
595
596 /* Update the statistics here. */
597
598 return 0;
599
600}
601
602/* Get the current statistics. This may be called with the card open or
603 closed. */
604static struct net_device_stats *seeq8005_get_stats(struct net_device *dev)
605{
606 struct net_local *lp = netdev_priv(dev);
607
608 return &lp->stats;
609}
610
611/* Set or clear the multicast filter for this adaptor.
612 num_addrs == -1 Promiscuous mode, receive all packets
613 num_addrs == 0 Normal mode, clear multicast list
614 num_addrs > 0 Multicast mode, receive normal and MC packets, and do
615 best-effort filtering.
616 */
617static void set_multicast_list(struct net_device *dev)
618{
619/*
620 * I _could_ do up to 6 addresses here, but won't (yet?)
621 */
622
623#if 0
624 int ioaddr = dev->base_addr;
625/*
626 * hmm, not even sure if my matching works _anyway_ - seem to be receiving
627 * _everything_ . . .
628 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400629
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 if (num_addrs) { /* Enable promiscuous mode */
631 outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_ALL, SEEQ_CFG1);
632 dev->flags|=IFF_PROMISC;
633 } else { /* Disable promiscuous mode, use normal mode */
634 outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_BROAD, SEEQ_CFG1);
635 }
636#endif
637}
638
639void seeq8005_init(struct net_device *dev, int startp)
640{
641 struct net_local *lp = netdev_priv(dev);
642 int ioaddr = dev->base_addr;
643 int i;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400644
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 outw(SEEQCFG2_RESET, SEEQ_CFG2); /* reset device */
646 udelay(5);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
649 outw( 0, SEEQ_DMAAR); /* load start address into both low and high byte */
650/* wait_for_buffer(dev); */ /* I think that you only need a wait for memory buffer */
651 outw( SEEQCFG1_BUFFER_MAC0, SEEQ_CFG1);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400652
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 for(i=0;i<6;i++) { /* set Station address */
654 outb(dev->dev_addr[i], SEEQ_BUFFER);
655 udelay(2);
656 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400657
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 outw( SEEQCFG1_BUFFER_TEA, SEEQ_CFG1); /* set xmit end area pointer to 16K */
659 outb( DEFAULT_TEA, SEEQ_BUFFER); /* this gives us 16K of send buffer and 48K of recv buffer */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400660
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 lp->receive_ptr = (DEFAULT_TEA+1)<<8; /* so we can find our packet_header */
662 outw( lp->receive_ptr, SEEQ_RPR); /* Receive Pointer Register is set to recv buffer memory */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400663
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 outw( 0x00ff, SEEQ_REA); /* Receive Area End */
665
666 if (net_debug>4) {
667 printk("%s: SA0 = ",dev->name);
668
669 outw( SEEQCMD_FIFO_READ | SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
670 outw( 0, SEEQ_DMAAR);
671 outw( SEEQCFG1_BUFFER_MAC0, SEEQ_CFG1);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400672
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 for(i=0;i<6;i++) {
674 printk("%02x ",inb(SEEQ_BUFFER));
675 }
676 printk("\n");
677 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400678
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 outw( SEEQCFG1_MAC0_EN | SEEQCFG1_MATCH_BROAD | SEEQCFG1_BUFFER_BUFFER, SEEQ_CFG1);
680 outw( SEEQCFG2_AUTO_REA | SEEQCFG2_CTRLO, SEEQ_CFG2);
681 outw( SEEQCMD_SET_RX_ON | SEEQCMD_TX_INT_EN | SEEQCMD_RX_INT_EN, SEEQ_CMD);
682
683 if (net_debug>4) {
684 int old_cfg1;
685 old_cfg1 = inw(SEEQ_CFG1);
686 printk("%s: stat = 0x%04x\n",dev->name,inw(SEEQ_STATUS));
687 printk("%s: cfg1 = 0x%04x\n",dev->name,old_cfg1);
688 printk("%s: cfg2 = 0x%04x\n",dev->name,inw(SEEQ_CFG2));
689 printk("%s: raer = 0x%04x\n",dev->name,inw(SEEQ_REA));
690 printk("%s: dmaar= 0x%04x\n",dev->name,inw(SEEQ_DMAAR));
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400691
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400693}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694
695
696static void hardware_send_packet(struct net_device * dev, char *buf, int length)
697{
698 int ioaddr = dev->base_addr;
699 int status = inw(SEEQ_STATUS);
700 int transmit_ptr = 0;
Marcelo Feitoza Parisiff5688a2006-01-09 18:37:15 -0800701 unsigned long tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
703 if (net_debug>4) {
704 printk("%s: send 0x%04x\n",dev->name,length);
705 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400706
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 /* Set FIFO to writemode and set packet-buffer address */
708 outw( SEEQCMD_FIFO_WRITE | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
709 outw( transmit_ptr, SEEQ_DMAAR);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 /* output SEEQ Packet header barfage */
712 outw( htons(length + 4), SEEQ_BUFFER);
713 outw( SEEQPKTH_XMIT | SEEQPKTH_DATA_FOLLOWS | SEEQPKTH_XMIT_INT_EN, SEEQ_BUFFER );
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400714
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 /* blat the buffer */
716 outsw( SEEQ_BUFFER, buf, (length +1) >> 1);
717 /* paranoia !! */
718 outw( 0, SEEQ_BUFFER);
719 outw( 0, SEEQ_BUFFER);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400720
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 /* set address of start of transmit chain */
722 outw( transmit_ptr, SEEQ_TPR);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400723
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 /* drain FIFO */
725 tmp = jiffies;
Marcelo Feitoza Parisiff5688a2006-01-09 18:37:15 -0800726 while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && time_before(jiffies, tmp + HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 mb();
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400728
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 /* doit ! */
730 outw( SEEQCMD_WINDOW_INT_ACK | SEEQCMD_SET_TX_ON | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400731
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732}
733
734
735#ifdef MODULE
736
737static struct net_device *dev_seeq;
738MODULE_LICENSE("GPL");
739module_param(io, int, 0);
740module_param(irq, int, 0);
741MODULE_PARM_DESC(io, "SEEQ 8005 I/O base address");
742MODULE_PARM_DESC(irq, "SEEQ 8005 IRQ number");
743
Andrew Mortonc971ef42006-08-14 23:00:08 -0700744int __init init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745{
746 dev_seeq = seeq8005_probe(-1);
747 if (IS_ERR(dev_seeq))
748 return PTR_ERR(dev_seeq);
749 return 0;
750}
751
Al Viroafc8eb42006-06-14 18:50:53 -0400752void __exit cleanup_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753{
754 unregister_netdev(dev_seeq);
755 release_region(dev_seeq->base_addr, SEEQ8005_IO_EXTENT);
756 free_netdev(dev_seeq);
757}
758
759#endif /* MODULE */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400760
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761/*
762 * Local variables:
763 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
764 * version-control: t
765 * kept-new-versions: 5
766 * tab-width: 4
767 * End:
768 */