* add p cc
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / net / atari_bionet.c
blobcb8b20918f753d8639ed61b331119aee7c0acf12
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/sched.h>
90 #include <linux/types.h>
91 #include <linux/fcntl.h>
92 #include <linux/interrupt.h>
93 #include <linux/ptrace.h>
94 #include <linux/ioport.h>
95 #include <linux/in.h>
96 #include <linux/malloc.h>
97 #include <linux/string.h>
98 #include <linux/delay.h>
99 #include <linux/timer.h>
100 #include <linux/init.h>
102 #include <linux/netdevice.h>
103 #include <linux/etherdevice.h>
104 #include <linux/skbuff.h>
106 #include <asm/setup.h>
107 #include <asm/pgtable.h>
108 #include <asm/system.h>
109 #include <asm/bitops.h>
110 #include <asm/io.h>
111 #include <asm/dma.h>
112 #include <asm/atarihw.h>
113 #include <asm/atariints.h>
114 #include <asm/atari_acsi.h>
115 #include <asm/atari_stdma.h>
118 extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_private);
120 /* use 0 for production, 1 for verification, >2 for debug
122 #ifndef NET_DEBUG
123 #define NET_DEBUG 0
124 #endif
126 * Global variable 'bionet_debug'. Can be set at load time by 'insmod'
128 unsigned int bionet_debug = NET_DEBUG;
129 MODULE_PARM(bionet_debug, "i");
131 static unsigned int bionet_min_poll_time = 2;
134 /* Information that need to be kept for each board.
136 struct net_local {
137 struct net_device_stats stats;
138 long open_time; /* for debugging */
139 int poll_time; /* polling time varies with net load */
142 static struct nic_pkt_s { /* packet format */
143 unsigned char status;
144 unsigned char dummy;
145 unsigned char l_lo, l_hi;
146 unsigned char buffer[3000];
147 } *nic_packet;
148 unsigned char *phys_nic_packet;
150 /* Index to functions, as function prototypes.
152 extern int bionet_probe(struct net_device *dev);
154 static int bionet_open(struct net_device *dev);
155 static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev);
156 static void bionet_poll_rx(struct net_device *);
157 static int bionet_close(struct net_device *dev);
158 static struct net_device_stats *net_get_stats(struct net_device *dev);
159 static void bionet_tick(unsigned long);
161 static struct timer_list bionet_timer = { NULL, NULL, 0, 0, bionet_tick };
163 #define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
165 /* The following routines access the ethernet board connected to the
166 * ACSI port via the st_dma chip.
168 #define NODE_ADR 0x60
170 #define C_READ 8
171 #define C_WRITE 0x0a
172 #define C_GETEA 0x0f
173 #define C_SETCR 0x0e
175 static int
176 sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) {
177 unsigned int c;
179 dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88);
180 dma_wd.fdc_acces_seccount = cmd;
181 dma_wd.dma_mode_status = (mod | 0x8a);
183 if( !acsi_wait_for_IRQ(HZ/2) ) /* wait for cmd ack */
184 return -1; /* timeout */
186 c = dma_wd.fdc_acces_seccount;
187 return (c & 0xff);
191 static void
192 set_status(int cr) {
193 sendcmd(0,0x100,NODE_ADR | C_SETCR); /* CMD: SET CR */
194 sendcmd(1,0x100,cr);
196 dma_wd.dma_mode_status = 0x80;
199 static int
200 get_status(unsigned char *adr) {
201 int i,c;
203 DISABLE_IRQ();
204 c = sendcmd(0,0x00,NODE_ADR | C_GETEA); /* CMD: GET ETH ADR*/
205 if( c < 0 ) goto gsend;
207 /* now read status bytes */
209 for (i=0; i<6; i++) {
210 dma_wd.fdc_acces_seccount = 0; /* request next byte */
212 if( !acsi_wait_for_IRQ(HZ/2) ) { /* wait for cmd ack */
213 c = -1;
214 goto gsend; /* timeout */
216 c = dma_wd.fdc_acces_seccount;
217 *adr++ = (unsigned char)c;
219 c = 1;
220 gsend:
221 dma_wd.dma_mode_status = 0x80;
222 return c;
225 static void
226 bionet_intr(int irq, void *data, struct pt_regs *fp) {
227 return;
231 static int
232 get_frame(unsigned long paddr, int odd) {
233 int c;
234 unsigned long flags;
236 DISABLE_IRQ();
237 save_flags(flags);
238 cli();
240 dma_wd.dma_mode_status = 0x9a;
241 dma_wd.dma_mode_status = 0x19a;
242 dma_wd.dma_mode_status = 0x9a;
243 dma_wd.fdc_acces_seccount = 0x04; /* sector count (was 5) */
244 dma_wd.dma_lo = (unsigned char)paddr;
245 paddr >>= 8;
246 dma_wd.dma_md = (unsigned char)paddr;
247 paddr >>= 8;
248 dma_wd.dma_hi = (unsigned char)paddr;
249 restore_flags(flags);
251 c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */
252 if( c < 128 ) goto rend;
254 /* now read block */
256 c = sendcmd(1,0x00,odd); /* odd flag for address shift */
257 dma_wd.dma_mode_status = 0x0a;
259 if( !acsi_wait_for_IRQ(100) ) { /* wait for DMA to complete */
260 c = -1;
261 goto rend;
263 dma_wd.dma_mode_status = 0x8a;
264 dma_wd.dma_mode_status = 0x18a;
265 dma_wd.dma_mode_status = 0x8a;
266 c = dma_wd.fdc_acces_seccount;
268 dma_wd.dma_mode_status = 0x88;
269 c = dma_wd.fdc_acces_seccount;
270 c = 1;
272 rend:
273 dma_wd.dma_mode_status = 0x80;
274 udelay(40);
275 acsi_wait_for_noIRQ(20);
276 return c;
280 static int
281 hardware_send_packet(unsigned long paddr, int cnt) {
282 unsigned int c;
283 unsigned long flags;
285 DISABLE_IRQ();
286 save_flags(flags);
287 cli();
289 dma_wd.dma_mode_status = 0x19a;
290 dma_wd.dma_mode_status = 0x9a;
291 dma_wd.dma_mode_status = 0x19a;
292 dma_wd.dma_lo = (unsigned char)paddr;
293 paddr >>= 8;
294 dma_wd.dma_md = (unsigned char)paddr;
295 paddr >>= 8;
296 dma_wd.dma_hi = (unsigned char)paddr;
298 dma_wd.fdc_acces_seccount = 0x4; /* sector count */
299 restore_flags(flags);
301 c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */
302 c = sendcmd(1,0x100,cnt&0xff);
303 c = sendcmd(1,0x100,cnt>>8);
305 /* now write block */
307 dma_wd.dma_mode_status = 0x10a; /* DMA enable */
308 if( !acsi_wait_for_IRQ(100) ) /* wait for DMA to complete */
309 goto end;
311 dma_wd.dma_mode_status = 0x19a; /* DMA disable ! */
312 c = dma_wd.fdc_acces_seccount;
314 end:
315 c = sendcmd(1,0x100,0);
316 c = sendcmd(1,0x100,0);
318 dma_wd.dma_mode_status = 0x180;
319 udelay(40);
320 acsi_wait_for_noIRQ(20);
321 return( c & 0x02);
325 /* Check for a network adaptor of this type, and return '0' if one exists.
327 int __init
328 bionet_probe(struct net_device *dev){
329 unsigned char station_addr[6];
330 static unsigned version_printed = 0;
331 static int no_more_found = 0; /* avoid "Probing for..." printed 4 times */
332 int i;
334 if (!MACH_IS_ATARI || no_more_found)
335 return ENODEV;
337 printk("Probing for BioNet 100 Adapter...\n");
339 stdma_lock(bionet_intr, NULL);
340 i = get_status(station_addr); /* Read the station address PROM. */
341 ENABLE_IRQ();
342 stdma_release();
344 /* Check the first three octets of the S.A. for the manufactor's code.
347 if( i < 0
348 || station_addr[0] != 'B'
349 || station_addr[1] != 'I'
350 || station_addr[2] != 'O' ) {
351 no_more_found = 1;
352 printk( "No BioNet 100 found.\n" );
353 return ENODEV;
357 if (dev == NULL)
358 return ENODEV;
359 if (bionet_debug > 0 && version_printed++ == 0)
360 printk(version);
362 printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n",
363 dev->name, "BioNet 100",
364 station_addr[0], station_addr[1], station_addr[2],
365 station_addr[3], station_addr[4], station_addr[5]);
367 /* Initialize the device structure. */
369 nic_packet = (struct nic_pkt_s *)acsi_buffer;
370 phys_nic_packet = (unsigned char *)phys_acsi_buffer;
371 if (bionet_debug > 0) {
372 printk("nic_packet at 0x%p, phys at 0x%p\n",
373 nic_packet, phys_nic_packet );
376 if (dev->priv == NULL)
377 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
378 memset(dev->priv, 0, sizeof(struct net_local));
380 dev->open = bionet_open;
381 dev->stop = bionet_close;
382 dev->hard_start_xmit = bionet_send_packet;
383 dev->get_stats = net_get_stats;
385 /* Fill in the fields of the device structure with ethernet-generic
386 * values. This should be in a common file instead of per-driver.
389 for (i = 0; i < ETH_ALEN; i++) {
390 #if 0
391 dev->broadcast[i] = 0xff;
392 #endif
393 dev->dev_addr[i] = station_addr[i];
395 ether_setup(dev);
396 return 0;
399 /* Open/initialize the board. This is called (in the current kernel)
400 sometime after booting when the 'ifconfig' program is run.
402 This routine should set everything up anew at each open, even
403 registers that "should" only need to be set once at boot, so that
404 there is non-reboot way to recover if something goes wrong.
406 static int
407 bionet_open(struct net_device *dev) {
408 struct net_local *lp = (struct net_local *)dev->priv;
410 if (bionet_debug > 0)
411 printk("bionet_open\n");
412 stdma_lock(bionet_intr, NULL);
414 /* Reset the hardware here.
416 set_status(4);
417 lp->open_time = 0; /*jiffies*/
418 lp->poll_time = MAX_POLL_TIME;
420 dev->tbusy = 0;
421 dev->interrupt = 0;
422 dev->start = 1;
424 stdma_release();
425 bionet_timer.data = (long)dev;
426 bionet_timer.expires = jiffies + lp->poll_time;
427 add_timer(&bionet_timer);
428 MOD_INC_USE_COUNT;
429 return 0;
432 static int
433 bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
434 struct net_local *lp = (struct net_local *)dev->priv;
435 unsigned long flags;
437 /* Block a timer-based transmit from overlapping. This could better be
438 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
440 save_flags(flags);
441 cli();
443 if (stdma_islocked()) {
444 restore_flags(flags);
445 lp->stats.tx_errors++;
447 else {
448 int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
449 unsigned long buf = virt_to_phys(skb->data);
450 int stat;
452 stdma_lock(bionet_intr, NULL);
453 restore_flags(flags);
454 if( !STRAM_ADDR(buf+length-1) ) {
455 memcpy(nic_packet->buffer, skb->data, length);
456 buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer;
459 if (bionet_debug >1) {
460 u_char *data = nic_packet->buffer, *p;
461 int i;
463 printk( "%s: TX pkt type 0x%4x from ", dev->name,
464 ((u_short *)data)[6]);
466 for( p = &data[6], i = 0; i < 6; i++ )
467 printk("%02x%s", *p++,i != 5 ? ":" : "" );
468 printk(" to ");
470 for( p = data, i = 0; i < 6; i++ )
471 printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
473 printk( "%s: ", dev->name );
474 printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
475 " %02x%02x%02x%02x len %d\n",
476 data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
477 data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
478 data[28], data[29], data[30], data[31], data[32], data[33],
479 length );
481 dma_cache_maintenance(buf, length, 1);
483 stat = hardware_send_packet(buf, length);
484 ENABLE_IRQ();
485 stdma_release();
487 dev->trans_start = jiffies;
488 dev->tbusy = 0;
489 lp->stats.tx_packets++;
490 lp->stats.tx_bytes+=length;
492 dev_kfree_skb(skb);
494 return 0;
497 /* We have a good packet(s), get it/them out of the buffers.
499 static void
500 bionet_poll_rx(struct net_device *dev) {
501 struct net_local *lp = (struct net_local *)dev->priv;
502 int boguscount = 10;
503 int pkt_len, status;
504 unsigned long flags;
506 save_flags(flags);
507 cli();
508 /* ++roman: Take care at locking the ST-DMA... This must be done with ints
509 * off, since otherwise an int could slip in between the question and the
510 * locking itself, and then we'd go to sleep... And locking itself is
511 * necessary to keep the floppy_change timer from working with ST-DMA
512 * registers. */
513 if (stdma_islocked()) {
514 restore_flags(flags);
515 return;
517 stdma_lock(bionet_intr, NULL);
518 DISABLE_IRQ();
519 restore_flags(flags);
521 if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
523 while(boguscount--) {
524 status = get_frame((unsigned long)phys_nic_packet, 0);
526 if( status == 0 ) break;
528 /* Good packet... */
530 dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0);
532 pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo;
534 lp->poll_time = bionet_min_poll_time; /* fast poll */
535 if( pkt_len >= 60 && pkt_len <= 1520 ) {
536 /* ^^^^ war 1514 KHL */
537 /* Malloc up new buffer.
539 struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 );
540 if (skb == NULL) {
541 printk("%s: Memory squeeze, dropping packet.\n",
542 dev->name);
543 lp->stats.rx_dropped++;
544 break;
547 skb->dev = dev;
548 skb_reserve( skb, 2 ); /* 16 Byte align */
549 skb_put( skb, pkt_len ); /* make room */
551 /* 'skb->data' points to the start of sk_buff data area.
553 memcpy(skb->data, nic_packet->buffer, pkt_len);
554 skb->protocol = eth_type_trans( skb, dev );
555 netif_rx(skb);
556 lp->stats.rx_packets++;
557 lp->stats.rx_bytes+=pkt_len;
559 /* If any worth-while packets have been received, dev_rint()
560 has done a mark_bh(INET_BH) for us and will work on them
561 when we get to the bottom-half routine.
564 if (bionet_debug >1) {
565 u_char *data = nic_packet->buffer, *p;
566 int i;
568 printk( "%s: RX pkt type 0x%4x from ", dev->name,
569 ((u_short *)data)[6]);
572 for( p = &data[6], i = 0; i < 6; i++ )
573 printk("%02x%s", *p++,i != 5 ? ":" : "" );
574 printk(" to ");
575 for( p = data, i = 0; i < 6; i++ )
576 printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
578 printk( "%s: ", dev->name );
579 printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
580 " %02x%02x%02x%02x len %d\n",
581 data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
582 data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
583 data[28], data[29], data[30], data[31], data[32], data[33],
584 pkt_len );
587 else {
588 printk(" Packet has wrong length: %04d bytes\n", pkt_len);
589 lp->stats.rx_errors++;
592 stdma_release();
593 ENABLE_IRQ();
594 return;
597 /* bionet_tick: called by bionet_timer. Reads packets from the adapter,
598 * passes them to the higher layers and restarts the timer.
600 static void
601 bionet_tick(unsigned long data) {
602 struct net_device *dev = (struct net_device *)data;
603 struct net_local *lp = (struct net_local *)dev->priv;
605 if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 )
606 printk("bionet_tick: %ld\n", lp->open_time);
608 if( !stdma_islocked() ) bionet_poll_rx(dev);
610 bionet_timer.expires = jiffies + lp->poll_time;
611 add_timer(&bionet_timer);
614 /* The inverse routine to bionet_open().
616 static int
617 bionet_close(struct net_device *dev) {
618 struct net_local *lp = (struct net_local *)dev->priv;
620 if (bionet_debug > 0)
621 printk("bionet_close, open_time=%ld\n", lp->open_time);
622 del_timer(&bionet_timer);
623 stdma_lock(bionet_intr, NULL);
625 set_status(0);
626 lp->open_time = 0;
628 dev->tbusy = 1;
629 dev->start = 0;
631 stdma_release();
632 MOD_DEC_USE_COUNT;
633 return 0;
636 /* Get the current statistics.
637 This may be called with the card open or closed.
639 static struct net_device_stats *net_get_stats(struct net_device *dev)
641 struct net_local *lp = (struct net_local *)dev->priv;
642 return &lp->stats;
646 #ifdef MODULE
648 static char bio_name[16];
649 static struct net_device bio_dev =
651 bio_name, /* filled in by register_netdev() */
652 0, 0, 0, 0, /* memory */
653 0, 0, /* base, irq */
654 0, 0, 0, NULL, bionet_probe,
658 init_module(void) {
659 int err;
661 if ((err = register_netdev(&bio_dev))) {
662 if (err == -EEXIST) {
663 printk("BIONET: devices already present. Module not loaded.\n");
665 return err;
667 return 0;
670 void
671 cleanup_module(void) {
672 unregister_netdev(&bio_dev);
675 #endif /* MODULE */
677 /* Local variables:
678 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
679 -b m68k-linuxaout -Wall -Wstrict-prototypes -O2
680 -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c"
681 * version-control: t
682 * kept-new-versions: 5
683 * tab-width: 8
684 * End: