More meth updates.
[linux-2.6/linux-mips.git] / drivers / net / atari_bionet.c
blob36d5392c448ef80e37f5526b66cd7d8b342b0bde
1 /* bionet.c BioNet-100 device driver for linux68k.
3 * Version: @(#)bionet.c 1.0 02/06/96
5 * Author: Hartmut Laue <laue@ifk-mp.uni-kiel.de>
6 * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de>
8 * Little adaptions for integration into pl7 by Roman Hodek
10 * Some changes in bionet_poll_rx by Karl-Heinz Lohner
12 What is it ?
13 ------------
14 This driver controls the BIONET-100 LAN-Adapter which connects
15 an ATARI ST/TT via the ACSI-port to an Ethernet-based network.
17 This version can be compiled as a loadable module (See the
18 compile command at the bottom of this file).
19 At load time, you can optionally set the debugging level and the
20 fastest response time on the command line of 'insmod'.
22 'bionet_debug'
23 controls the amount of diagnostic messages:
24 0 : no messages
25 >0 : see code for meaning of printed messages
27 'bionet_min_poll_time' (always >=1)
28 gives the time (in jiffies) between polls. Low values
29 increase the system load (beware!)
31 When loaded, a net device with the name 'bio0' becomes available,
32 which can be controlled with the usual 'ifconfig' command.
34 It is possible to compile this driver into the kernel like other
35 (net) drivers. For this purpose, some source files (e.g. config-files
36 makefiles, Space.c) must be changed accordingly. (You may refer to
37 other drivers how to do it.) In this case, the device will be detected
38 at boot time and (probably) appear as 'eth0'.
40 This code is based on several sources:
41 - The driver code for a parallel port ethernet adapter by
42 Donald Becker (see file 'atp.c' from the PC linux distribution)
43 - The ACSI code by Roman Hodek for the ATARI-ACSI harddisk support
44 and DMA handling.
45 - Very limited information about moving packets in and out of the
46 BIONET-adapter from the TCP package for TOS by BioData GmbH.
48 Theory of Operation
49 -------------------
50 Because the ATARI DMA port is usually shared between several
51 devices (eg. harddisk, floppy) we cannot block the ACSI bus
52 while waiting for interrupts. Therefore we use a polling mechanism
53 to fetch packets from the adapter. For the same reason, we send
54 packets without checking that the previous packet has been sent to
55 the LAN. We rely on the higher levels of the networking code to detect
56 missing packets and resend them.
58 Before we access the ATARI DMA controller, we check if another
59 process is using the DMA. If not, we lock the DMA, perform one or
60 more packet transfers and unlock the DMA before returning.
61 We do not use 'stdma_lock' unconditionally because it is unclear
62 if the networking code can be set to sleep, which will happen if
63 another (possibly slow) device is using the DMA controller.
65 The polling is done via timer interrupts which periodically
66 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies)
67 between polls varies depending on an estimate of the net activity.
68 The allowed range is given by the variable 'bionet_min_poll_time'
69 for the lower (fastest) limit and the constant 'MAX_POLL_TIME'
70 for the higher (slowest) limit.
72 Whenever a packet arrives, we switch to fastest response by setting
73 the polling time to its lowest limit. If the following poll fails,
74 because no packets have arrived, we increase the time for the next
75 poll. When the net activity is low, the polling time effectively
76 stays at its maximum value, resulting in the lowest load for the
77 machine.
80 #define MAX_POLL_TIME 10
82 static char version[] =
83 "bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n";
85 #include <linux/module.h>
87 #include <linux/errno.h>
88 #include <linux/kernel.h>
89 #include <linux/jiffies.h>
90 #include <linux/types.h>
91 #include <linux/fcntl.h>
92 #include <linux/interrupt.h>
93 #include <linux/ioport.h>
94 #include <linux/in.h>
95 #include <linux/slab.h>
96 #include <linux/string.h>
97 #include <linux/delay.h>
98 #include <linux/timer.h>
99 #include <linux/init.h>
101 #include <linux/netdevice.h>
102 #include <linux/etherdevice.h>
103 #include <linux/skbuff.h>
105 #include <asm/setup.h>
106 #include <asm/pgtable.h>
107 #include <asm/system.h>
108 #include <asm/bitops.h>
109 #include <asm/io.h>
110 #include <asm/dma.h>
111 #include <asm/atarihw.h>
112 #include <asm/atariints.h>
113 #include <asm/atari_acsi.h>
114 #include <asm/atari_stdma.h>
117 /* use 0 for production, 1 for verification, >2 for debug
119 #ifndef NET_DEBUG
120 #define NET_DEBUG 0
121 #endif
123 * Global variable 'bionet_debug'. Can be set at load time by 'insmod'
125 unsigned int bionet_debug = NET_DEBUG;
126 MODULE_PARM(bionet_debug, "i");
127 MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)");
128 MODULE_LICENSE("GPL");
130 static unsigned int bionet_min_poll_time = 2;
133 /* Information that need to be kept for each board.
135 struct net_local {
136 struct net_device_stats stats;
137 long open_time; /* for debugging */
138 int poll_time; /* polling time varies with net load */
141 static struct nic_pkt_s { /* packet format */
142 unsigned char status;
143 unsigned char dummy;
144 unsigned char l_lo, l_hi;
145 unsigned char buffer[3000];
146 } *nic_packet;
147 unsigned char *phys_nic_packet;
149 /* Index to functions, as function prototypes.
151 extern int bionet_probe(struct net_device *dev);
153 static int bionet_open(struct net_device *dev);
154 static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev);
155 static void bionet_poll_rx(struct net_device *);
156 static int bionet_close(struct net_device *dev);
157 static struct net_device_stats *net_get_stats(struct net_device *dev);
158 static void bionet_tick(unsigned long);
160 static struct timer_list bionet_timer = TIMER_INITIALIZER(bionet_tick, 0, 0);
162 #define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
164 /* The following routines access the ethernet board connected to the
165 * ACSI port via the st_dma chip.
167 #define NODE_ADR 0x60
169 #define C_READ 8
170 #define C_WRITE 0x0a
171 #define C_GETEA 0x0f
172 #define C_SETCR 0x0e
174 static int
175 sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) {
176 unsigned int c;
178 dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88);
179 dma_wd.fdc_acces_seccount = cmd;
180 dma_wd.dma_mode_status = (mod | 0x8a);
182 if( !acsi_wait_for_IRQ(HZ/2) ) /* wait for cmd ack */
183 return -1; /* timeout */
185 c = dma_wd.fdc_acces_seccount;
186 return (c & 0xff);
190 static void
191 set_status(int cr) {
192 sendcmd(0,0x100,NODE_ADR | C_SETCR); /* CMD: SET CR */
193 sendcmd(1,0x100,cr);
195 dma_wd.dma_mode_status = 0x80;
198 static int
199 get_status(unsigned char *adr) {
200 int i,c;
202 DISABLE_IRQ();
203 c = sendcmd(0,0x00,NODE_ADR | C_GETEA); /* CMD: GET ETH ADR*/
204 if( c < 0 ) goto gsend;
206 /* now read status bytes */
208 for (i=0; i<6; i++) {
209 dma_wd.fdc_acces_seccount = 0; /* request next byte */
211 if( !acsi_wait_for_IRQ(HZ/2) ) { /* wait for cmd ack */
212 c = -1;
213 goto gsend; /* timeout */
215 c = dma_wd.fdc_acces_seccount;
216 *adr++ = (unsigned char)c;
218 c = 1;
219 gsend:
220 dma_wd.dma_mode_status = 0x80;
221 return c;
224 static irqreturn_t
225 bionet_intr(int irq, void *data, struct pt_regs *fp) {
226 return IRQ_HANDLED;
230 static int
231 get_frame(unsigned long paddr, int odd) {
232 int c;
233 unsigned long flags;
235 DISABLE_IRQ();
236 local_irq_save(flags);
238 dma_wd.dma_mode_status = 0x9a;
239 dma_wd.dma_mode_status = 0x19a;
240 dma_wd.dma_mode_status = 0x9a;
241 dma_wd.fdc_acces_seccount = 0x04; /* sector count (was 5) */
242 dma_wd.dma_lo = (unsigned char)paddr;
243 paddr >>= 8;
244 dma_wd.dma_md = (unsigned char)paddr;
245 paddr >>= 8;
246 dma_wd.dma_hi = (unsigned char)paddr;
247 local_irq_restore(flags);
249 c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */
250 if( c < 128 ) goto rend;
252 /* now read block */
254 c = sendcmd(1,0x00,odd); /* odd flag for address shift */
255 dma_wd.dma_mode_status = 0x0a;
257 if( !acsi_wait_for_IRQ(100) ) { /* wait for DMA to complete */
258 c = -1;
259 goto rend;
261 dma_wd.dma_mode_status = 0x8a;
262 dma_wd.dma_mode_status = 0x18a;
263 dma_wd.dma_mode_status = 0x8a;
264 c = dma_wd.fdc_acces_seccount;
266 dma_wd.dma_mode_status = 0x88;
267 c = dma_wd.fdc_acces_seccount;
268 c = 1;
270 rend:
271 dma_wd.dma_mode_status = 0x80;
272 udelay(40);
273 acsi_wait_for_noIRQ(20);
274 return c;
278 static int
279 hardware_send_packet(unsigned long paddr, int cnt) {
280 unsigned int c;
281 unsigned long flags;
283 DISABLE_IRQ();
284 local_irq_save(flags);
286 dma_wd.dma_mode_status = 0x19a;
287 dma_wd.dma_mode_status = 0x9a;
288 dma_wd.dma_mode_status = 0x19a;
289 dma_wd.dma_lo = (unsigned char)paddr;
290 paddr >>= 8;
291 dma_wd.dma_md = (unsigned char)paddr;
292 paddr >>= 8;
293 dma_wd.dma_hi = (unsigned char)paddr;
295 dma_wd.fdc_acces_seccount = 0x4; /* sector count */
296 local_irq_restore(flags);
298 c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */
299 c = sendcmd(1,0x100,cnt&0xff);
300 c = sendcmd(1,0x100,cnt>>8);
302 /* now write block */
304 dma_wd.dma_mode_status = 0x10a; /* DMA enable */
305 if( !acsi_wait_for_IRQ(100) ) /* wait for DMA to complete */
306 goto end;
308 dma_wd.dma_mode_status = 0x19a; /* DMA disable ! */
309 c = dma_wd.fdc_acces_seccount;
311 end:
312 c = sendcmd(1,0x100,0);
313 c = sendcmd(1,0x100,0);
315 dma_wd.dma_mode_status = 0x180;
316 udelay(40);
317 acsi_wait_for_noIRQ(20);
318 return( c & 0x02);
322 /* Check for a network adaptor of this type, and return '0' if one exists.
324 int __init
325 bionet_probe(struct net_device *dev){
326 unsigned char station_addr[6];
327 static unsigned version_printed;
328 static int no_more_found; /* avoid "Probing for..." printed 4 times */
329 int i;
331 if (!MACH_IS_ATARI || no_more_found)
332 return -ENODEV;
334 printk("Probing for BioNet 100 Adapter...\n");
336 stdma_lock(bionet_intr, NULL);
337 i = get_status(station_addr); /* Read the station address PROM. */
338 ENABLE_IRQ();
339 stdma_release();
341 /* Check the first three octets of the S.A. for the manufactor's code.
344 if( i < 0
345 || station_addr[0] != 'B'
346 || station_addr[1] != 'I'
347 || station_addr[2] != 'O' ) {
348 no_more_found = 1;
349 printk( "No BioNet 100 found.\n" );
350 return -ENODEV;
353 SET_MODULE_OWNER(dev);
355 if (bionet_debug > 0 && version_printed++ == 0)
356 printk(version);
358 printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n",
359 dev->name, "BioNet 100",
360 station_addr[0], station_addr[1], station_addr[2],
361 station_addr[3], station_addr[4], station_addr[5]);
363 /* Initialize the device structure. */
365 nic_packet = (struct nic_pkt_s *)acsi_buffer;
366 phys_nic_packet = (unsigned char *)phys_acsi_buffer;
367 if (bionet_debug > 0) {
368 printk("nic_packet at 0x%p, phys at 0x%p\n",
369 nic_packet, phys_nic_packet );
372 if (dev->priv == NULL)
373 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
374 if (!dev->priv)
375 return -ENOMEM;
376 memset(dev->priv, 0, sizeof(struct net_local));
378 dev->open = bionet_open;
379 dev->stop = bionet_close;
380 dev->hard_start_xmit = bionet_send_packet;
381 dev->get_stats = net_get_stats;
383 /* Fill in the fields of the device structure with ethernet-generic
384 * values. This should be in a common file instead of per-driver.
387 for (i = 0; i < ETH_ALEN; i++) {
388 #if 0
389 dev->broadcast[i] = 0xff;
390 #endif
391 dev->dev_addr[i] = station_addr[i];
393 ether_setup(dev);
394 return 0;
397 /* Open/initialize the board. This is called (in the current kernel)
398 sometime after booting when the 'ifconfig' program is run.
400 This routine should set everything up anew at each open, even
401 registers that "should" only need to be set once at boot, so that
402 there is non-reboot way to recover if something goes wrong.
404 static int
405 bionet_open(struct net_device *dev) {
406 struct net_local *lp = (struct net_local *)dev->priv;
408 if (bionet_debug > 0)
409 printk("bionet_open\n");
410 stdma_lock(bionet_intr, NULL);
412 /* Reset the hardware here.
414 set_status(4);
415 lp->open_time = 0; /*jiffies*/
416 lp->poll_time = MAX_POLL_TIME;
418 dev->tbusy = 0;
419 dev->interrupt = 0;
420 dev->start = 1;
422 stdma_release();
423 bionet_timer.data = (long)dev;
424 bionet_timer.expires = jiffies + lp->poll_time;
425 add_timer(&bionet_timer);
426 return 0;
429 static int
430 bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
431 struct net_local *lp = (struct net_local *)dev->priv;
432 unsigned long flags;
434 /* Block a timer-based transmit from overlapping. This could better be
435 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
437 local_irq_save(flags);
439 if (stdma_islocked()) {
440 local_irq_restore(flags);
441 lp->stats.tx_errors++;
443 else {
444 int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
445 unsigned long buf = virt_to_phys(skb->data);
446 int stat;
448 stdma_lock(bionet_intr, NULL);
449 local_irq_restore(flags);
450 if( !STRAM_ADDR(buf+length-1) ) {
451 memcpy(nic_packet->buffer, skb->data, length);
452 buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer;
455 if (bionet_debug >1) {
456 u_char *data = nic_packet->buffer, *p;
457 int i;
459 printk( "%s: TX pkt type 0x%4x from ", dev->name,
460 ((u_short *)data)[6]);
462 for( p = &data[6], i = 0; i < 6; i++ )
463 printk("%02x%s", *p++,i != 5 ? ":" : "" );
464 printk(" to ");
466 for( p = data, i = 0; i < 6; i++ )
467 printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
469 printk( "%s: ", dev->name );
470 printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
471 " %02x%02x%02x%02x len %d\n",
472 data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
473 data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
474 data[28], data[29], data[30], data[31], data[32], data[33],
475 length );
477 dma_cache_maintenance(buf, length, 1);
479 stat = hardware_send_packet(buf, length);
480 ENABLE_IRQ();
481 stdma_release();
483 dev->trans_start = jiffies;
484 dev->tbusy = 0;
485 lp->stats.tx_packets++;
486 lp->stats.tx_bytes+=length;
488 dev_kfree_skb(skb);
490 return 0;
493 /* We have a good packet(s), get it/them out of the buffers.
495 static void
496 bionet_poll_rx(struct net_device *dev) {
497 struct net_local *lp = (struct net_local *)dev->priv;
498 int boguscount = 10;
499 int pkt_len, status;
500 unsigned long flags;
502 local_irq_save(flags);
503 /* ++roman: Take care at locking the ST-DMA... This must be done with ints
504 * off, since otherwise an int could slip in between the question and the
505 * locking itself, and then we'd go to sleep... And locking itself is
506 * necessary to keep the floppy_change timer from working with ST-DMA
507 * registers. */
508 if (stdma_islocked()) {
509 local_irq_restore(flags);
510 return;
512 stdma_lock(bionet_intr, NULL);
513 DISABLE_IRQ();
514 local_irq_restore(flags);
516 if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
518 while(boguscount--) {
519 status = get_frame((unsigned long)phys_nic_packet, 0);
521 if( status == 0 ) break;
523 /* Good packet... */
525 dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0);
527 pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo;
529 lp->poll_time = bionet_min_poll_time; /* fast poll */
530 if( pkt_len >= 60 && pkt_len <= 1520 ) {
531 /* ^^^^ war 1514 KHL */
532 /* Malloc up new buffer.
534 struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 );
535 if (skb == NULL) {
536 printk("%s: Memory squeeze, dropping packet.\n",
537 dev->name);
538 lp->stats.rx_dropped++;
539 break;
542 skb->dev = dev;
543 skb_reserve( skb, 2 ); /* 16 Byte align */
544 skb_put( skb, pkt_len ); /* make room */
546 /* 'skb->data' points to the start of sk_buff data area.
548 memcpy(skb->data, nic_packet->buffer, pkt_len);
549 skb->protocol = eth_type_trans( skb, dev );
550 netif_rx(skb);
551 dev->last_rx = jiffies;
552 lp->stats.rx_packets++;
553 lp->stats.rx_bytes+=pkt_len;
555 /* If any worth-while packets have been received, dev_rint()
556 has done a mark_bh(INET_BH) for us and will work on them
557 when we get to the bottom-half routine.
560 if (bionet_debug >1) {
561 u_char *data = nic_packet->buffer, *p;
562 int i;
564 printk( "%s: RX pkt type 0x%4x from ", dev->name,
565 ((u_short *)data)[6]);
568 for( p = &data[6], i = 0; i < 6; i++ )
569 printk("%02x%s", *p++,i != 5 ? ":" : "" );
570 printk(" to ");
571 for( p = data, i = 0; i < 6; i++ )
572 printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
574 printk( "%s: ", dev->name );
575 printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
576 " %02x%02x%02x%02x len %d\n",
577 data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
578 data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
579 data[28], data[29], data[30], data[31], data[32], data[33],
580 pkt_len );
583 else {
584 printk(" Packet has wrong length: %04d bytes\n", pkt_len);
585 lp->stats.rx_errors++;
588 stdma_release();
589 ENABLE_IRQ();
590 return;
593 /* bionet_tick: called by bionet_timer. Reads packets from the adapter,
594 * passes them to the higher layers and restarts the timer.
596 static void
597 bionet_tick(unsigned long data) {
598 struct net_device *dev = (struct net_device *)data;
599 struct net_local *lp = (struct net_local *)dev->priv;
601 if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 )
602 printk("bionet_tick: %ld\n", lp->open_time);
604 if( !stdma_islocked() ) bionet_poll_rx(dev);
606 bionet_timer.expires = jiffies + lp->poll_time;
607 add_timer(&bionet_timer);
610 /* The inverse routine to bionet_open().
612 static int
613 bionet_close(struct net_device *dev) {
614 struct net_local *lp = (struct net_local *)dev->priv;
616 if (bionet_debug > 0)
617 printk("bionet_close, open_time=%ld\n", lp->open_time);
618 del_timer(&bionet_timer);
619 stdma_lock(bionet_intr, NULL);
621 set_status(0);
622 lp->open_time = 0;
624 dev->tbusy = 1;
625 dev->start = 0;
627 stdma_release();
628 return 0;
631 /* Get the current statistics.
632 This may be called with the card open or closed.
634 static struct net_device_stats *net_get_stats(struct net_device *dev)
636 struct net_local *lp = (struct net_local *)dev->priv;
637 return &lp->stats;
641 #ifdef MODULE
643 static struct net_device bio_dev;
646 init_module(void) {
647 int err;
649 bio_dev.init = bionet_probe;
650 if ((err = register_netdev(&bio_dev))) {
651 if (err == -EEXIST) {
652 printk("BIONET: devices already present. Module not loaded.\n");
654 return err;
656 return 0;
659 void
660 cleanup_module(void) {
661 unregister_netdev(&bio_dev);
664 #endif /* MODULE */
666 /* Local variables:
667 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
668 -b m68k-linuxaout -Wall -Wstrict-prototypes -O2
669 -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c"
670 * version-control: t
671 * kept-new-versions: 5
672 * tab-width: 8
673 * End: