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
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'.
23 controls the amount of diagnostic 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
45 - Very limited information about moving packets in and out of the
46 BIONET-adapter from the TCP package for TOS by BioData GmbH.
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
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>
96 #include <linux/slab.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>
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
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");
130 MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)");
131 MODULE_LICENSE("GPL");
133 static unsigned int bionet_min_poll_time = 2;
136 /* Information that need to be kept for each board.
139 struct net_device_stats stats;
140 long open_time; /* for debugging */
141 int poll_time; /* polling time varies with net load */
144 static struct nic_pkt_s { /* packet format */
145 unsigned char status;
147 unsigned char l_lo, l_hi;
148 unsigned char buffer[3000];
150 unsigned char *phys_nic_packet;
152 /* Index to functions, as function prototypes.
154 extern int bionet_probe(struct net_device *dev);
156 static int bionet_open(struct net_device *dev);
157 static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev);
158 static void bionet_poll_rx(struct net_device *);
159 static int bionet_close(struct net_device *dev);
160 static struct net_device_stats *net_get_stats(struct net_device *dev);
161 static void bionet_tick(unsigned long);
163 static struct timer_list bionet_timer = { function: bionet_tick };
165 #define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
167 /* The following routines access the ethernet board connected to the
168 * ACSI port via the st_dma chip.
170 #define NODE_ADR 0x60
178 sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) {
181 dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88);
182 dma_wd.fdc_acces_seccount = cmd;
183 dma_wd.dma_mode_status = (mod | 0x8a);
185 if( !acsi_wait_for_IRQ(HZ/2) ) /* wait for cmd ack */
186 return -1; /* timeout */
188 c = dma_wd.fdc_acces_seccount;
195 sendcmd(0,0x100,NODE_ADR | C_SETCR); /* CMD: SET CR */
198 dma_wd.dma_mode_status = 0x80;
202 get_status(unsigned char *adr) {
206 c = sendcmd(0,0x00,NODE_ADR | C_GETEA); /* CMD: GET ETH ADR*/
207 if( c < 0 ) goto gsend;
209 /* now read status bytes */
211 for (i=0; i<6; i++) {
212 dma_wd.fdc_acces_seccount = 0; /* request next byte */
214 if( !acsi_wait_for_IRQ(HZ/2) ) { /* wait for cmd ack */
216 goto gsend; /* timeout */
218 c = dma_wd.fdc_acces_seccount;
219 *adr++ = (unsigned char)c;
223 dma_wd.dma_mode_status = 0x80;
228 bionet_intr(int irq, void *data, struct pt_regs *fp) {
234 get_frame(unsigned long paddr, int odd) {
242 dma_wd.dma_mode_status = 0x9a;
243 dma_wd.dma_mode_status = 0x19a;
244 dma_wd.dma_mode_status = 0x9a;
245 dma_wd.fdc_acces_seccount = 0x04; /* sector count (was 5) */
246 dma_wd.dma_lo = (unsigned char)paddr;
248 dma_wd.dma_md = (unsigned char)paddr;
250 dma_wd.dma_hi = (unsigned char)paddr;
251 restore_flags(flags);
253 c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */
254 if( c < 128 ) goto rend;
258 c = sendcmd(1,0x00,odd); /* odd flag for address shift */
259 dma_wd.dma_mode_status = 0x0a;
261 if( !acsi_wait_for_IRQ(100) ) { /* wait for DMA to complete */
265 dma_wd.dma_mode_status = 0x8a;
266 dma_wd.dma_mode_status = 0x18a;
267 dma_wd.dma_mode_status = 0x8a;
268 c = dma_wd.fdc_acces_seccount;
270 dma_wd.dma_mode_status = 0x88;
271 c = dma_wd.fdc_acces_seccount;
275 dma_wd.dma_mode_status = 0x80;
277 acsi_wait_for_noIRQ(20);
283 hardware_send_packet(unsigned long paddr, int cnt) {
291 dma_wd.dma_mode_status = 0x19a;
292 dma_wd.dma_mode_status = 0x9a;
293 dma_wd.dma_mode_status = 0x19a;
294 dma_wd.dma_lo = (unsigned char)paddr;
296 dma_wd.dma_md = (unsigned char)paddr;
298 dma_wd.dma_hi = (unsigned char)paddr;
300 dma_wd.fdc_acces_seccount = 0x4; /* sector count */
301 restore_flags(flags);
303 c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */
304 c = sendcmd(1,0x100,cnt&0xff);
305 c = sendcmd(1,0x100,cnt>>8);
307 /* now write block */
309 dma_wd.dma_mode_status = 0x10a; /* DMA enable */
310 if( !acsi_wait_for_IRQ(100) ) /* wait for DMA to complete */
313 dma_wd.dma_mode_status = 0x19a; /* DMA disable ! */
314 c = dma_wd.fdc_acces_seccount;
317 c = sendcmd(1,0x100,0);
318 c = sendcmd(1,0x100,0);
320 dma_wd.dma_mode_status = 0x180;
322 acsi_wait_for_noIRQ(20);
327 /* Check for a network adaptor of this type, and return '0' if one exists.
330 bionet_probe(struct net_device *dev){
331 unsigned char station_addr[6];
332 static unsigned version_printed;
333 static int no_more_found; /* avoid "Probing for..." printed 4 times */
336 if (!MACH_IS_ATARI || no_more_found)
339 printk("Probing for BioNet 100 Adapter...\n");
341 stdma_lock(bionet_intr, NULL);
342 i = get_status(station_addr); /* Read the station address PROM. */
346 /* Check the first three octets of the S.A. for the manufactor's code.
350 || station_addr[0] != 'B'
351 || station_addr[1] != 'I'
352 || station_addr[2] != 'O' ) {
354 printk( "No BioNet 100 found.\n" );
358 SET_MODULE_OWNER(dev);
360 if (bionet_debug > 0 && version_printed++ == 0)
363 printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n",
364 dev->name, "BioNet 100",
365 station_addr[0], station_addr[1], station_addr[2],
366 station_addr[3], station_addr[4], station_addr[5]);
368 /* Initialize the device structure. */
370 nic_packet = (struct nic_pkt_s *)acsi_buffer;
371 phys_nic_packet = (unsigned char *)phys_acsi_buffer;
372 if (bionet_debug > 0) {
373 printk("nic_packet at 0x%p, phys at 0x%p\n",
374 nic_packet, phys_nic_packet );
377 if (dev->priv == NULL)
378 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
381 memset(dev->priv, 0, sizeof(struct net_local));
383 dev->open = bionet_open;
384 dev->stop = bionet_close;
385 dev->hard_start_xmit = bionet_send_packet;
386 dev->get_stats = net_get_stats;
388 /* Fill in the fields of the device structure with ethernet-generic
389 * values. This should be in a common file instead of per-driver.
392 for (i = 0; i < ETH_ALEN; i++) {
394 dev->broadcast[i] = 0xff;
396 dev->dev_addr[i] = station_addr[i];
402 /* Open/initialize the board. This is called (in the current kernel)
403 sometime after booting when the 'ifconfig' program is run.
405 This routine should set everything up anew at each open, even
406 registers that "should" only need to be set once at boot, so that
407 there is non-reboot way to recover if something goes wrong.
410 bionet_open(struct net_device *dev) {
411 struct net_local *lp = (struct net_local *)dev->priv;
413 if (bionet_debug > 0)
414 printk("bionet_open\n");
415 stdma_lock(bionet_intr, NULL);
417 /* Reset the hardware here.
420 lp->open_time = 0; /*jiffies*/
421 lp->poll_time = MAX_POLL_TIME;
428 bionet_timer.data = (long)dev;
429 bionet_timer.expires = jiffies + lp->poll_time;
430 add_timer(&bionet_timer);
435 bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
436 struct net_local *lp = (struct net_local *)dev->priv;
439 /* Block a timer-based transmit from overlapping. This could better be
440 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
445 if (stdma_islocked()) {
446 restore_flags(flags);
447 lp->stats.tx_errors++;
450 int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
451 unsigned long buf = virt_to_phys(skb->data);
454 stdma_lock(bionet_intr, NULL);
455 restore_flags(flags);
456 if( !STRAM_ADDR(buf+length-1) ) {
457 memcpy(nic_packet->buffer, skb->data, length);
458 buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer;
461 if (bionet_debug >1) {
462 u_char *data = nic_packet->buffer, *p;
465 printk( "%s: TX pkt type 0x%4x from ", dev->name,
466 ((u_short *)data)[6]);
468 for( p = &data[6], i = 0; i < 6; i++ )
469 printk("%02x%s", *p++,i != 5 ? ":" : "" );
472 for( p = data, i = 0; i < 6; i++ )
473 printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
475 printk( "%s: ", dev->name );
476 printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
477 " %02x%02x%02x%02x len %d\n",
478 data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
479 data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
480 data[28], data[29], data[30], data[31], data[32], data[33],
483 dma_cache_maintenance(buf, length, 1);
485 stat = hardware_send_packet(buf, length);
489 dev->trans_start = jiffies;
491 lp->stats.tx_packets++;
492 lp->stats.tx_bytes+=length;
499 /* We have a good packet(s), get it/them out of the buffers.
502 bionet_poll_rx(struct net_device *dev) {
503 struct net_local *lp = (struct net_local *)dev->priv;
510 /* ++roman: Take care at locking the ST-DMA... This must be done with ints
511 * off, since otherwise an int could slip in between the question and the
512 * locking itself, and then we'd go to sleep... And locking itself is
513 * necessary to keep the floppy_change timer from working with ST-DMA
515 if (stdma_islocked()) {
516 restore_flags(flags);
519 stdma_lock(bionet_intr, NULL);
521 restore_flags(flags);
523 if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
525 while(boguscount--) {
526 status = get_frame((unsigned long)phys_nic_packet, 0);
528 if( status == 0 ) break;
532 dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0);
534 pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo;
536 lp->poll_time = bionet_min_poll_time; /* fast poll */
537 if( pkt_len >= 60 && pkt_len <= 1520 ) {
538 /* ^^^^ war 1514 KHL */
539 /* Malloc up new buffer.
541 struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 );
543 printk("%s: Memory squeeze, dropping packet.\n",
545 lp->stats.rx_dropped++;
550 skb_reserve( skb, 2 ); /* 16 Byte align */
551 skb_put( skb, pkt_len ); /* make room */
553 /* 'skb->data' points to the start of sk_buff data area.
555 memcpy(skb->data, nic_packet->buffer, pkt_len);
556 skb->protocol = eth_type_trans( skb, dev );
558 dev->last_rx = jiffies;
559 lp->stats.rx_packets++;
560 lp->stats.rx_bytes+=pkt_len;
562 /* If any worth-while packets have been received, dev_rint()
563 has done a mark_bh(INET_BH) for us and will work on them
564 when we get to the bottom-half routine.
567 if (bionet_debug >1) {
568 u_char *data = nic_packet->buffer, *p;
571 printk( "%s: RX pkt type 0x%4x from ", dev->name,
572 ((u_short *)data)[6]);
575 for( p = &data[6], i = 0; i < 6; i++ )
576 printk("%02x%s", *p++,i != 5 ? ":" : "" );
578 for( p = data, i = 0; i < 6; i++ )
579 printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
581 printk( "%s: ", dev->name );
582 printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
583 " %02x%02x%02x%02x len %d\n",
584 data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
585 data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
586 data[28], data[29], data[30], data[31], data[32], data[33],
591 printk(" Packet has wrong length: %04d bytes\n", pkt_len);
592 lp->stats.rx_errors++;
600 /* bionet_tick: called by bionet_timer. Reads packets from the adapter,
601 * passes them to the higher layers and restarts the timer.
604 bionet_tick(unsigned long data) {
605 struct net_device *dev = (struct net_device *)data;
606 struct net_local *lp = (struct net_local *)dev->priv;
608 if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 )
609 printk("bionet_tick: %ld\n", lp->open_time);
611 if( !stdma_islocked() ) bionet_poll_rx(dev);
613 bionet_timer.expires = jiffies + lp->poll_time;
614 add_timer(&bionet_timer);
617 /* The inverse routine to bionet_open().
620 bionet_close(struct net_device *dev) {
621 struct net_local *lp = (struct net_local *)dev->priv;
623 if (bionet_debug > 0)
624 printk("bionet_close, open_time=%ld\n", lp->open_time);
625 del_timer(&bionet_timer);
626 stdma_lock(bionet_intr, NULL);
638 /* Get the current statistics.
639 This may be called with the card open or closed.
641 static struct net_device_stats *net_get_stats(struct net_device *dev)
643 struct net_local *lp = (struct net_local *)dev->priv;
650 static struct net_device bio_dev;
656 bio_dev.init = bionet_probe;
657 if ((err = register_netdev(&bio_dev))) {
658 if (err == -EEXIST) {
659 printk("BIONET: devices already present. Module not loaded.\n");
667 cleanup_module(void) {
668 unregister_netdev(&bio_dev);
674 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
675 -b m68k-linuxaout -Wall -Wstrict-prototypes -O2
676 -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c"
678 * kept-new-versions: 5