1 /* bionet.c BioNet-100 device driver for linux68k.
2 *
3 * Version: @(#)bionet.c 1.0 02/06/96
4 *
5 * Author: Hartmut Laue <laue@ifk-mp.uni-kiel.de>
6 * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de>
7 *
8 * Little adaptions for integration into pl7 by Roman Hodek
9 *
10 * Some changes in bionet_poll_rx by Karl-Heinz Lohner
11 *
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.
16
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'.
21
22 'bionet_debug'
23 controls the amount of diagnostic messages:
24 0 : no messages
25 >0 : see code for meaning of printed messages
26
27 'bionet_min_poll_time' (always >=1)
28 gives the time (in jiffies) between polls. Low values
29 increase the system load (beware!)
30
31 When loaded, a net device with the name 'bio0' becomes available,
32 which can be controlled with the usual 'ifconfig' command.
33
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'.
39
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.
47
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.
57
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.
64
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.
71
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.
78 */
79
80 #define MAX_POLL_TIME 10
81
82 static char *version =
83 "bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n";
84
85 #include <linux/module.h>
86
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>
101
102 #include <linux/netdevice.h>
103 #include <linux/etherdevice.h>
104 #include <linux/skbuff.h>
105
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>
116
117
118 extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_private);
119
120 /* use 0 for production, 1 for verification, >2 for debug
121 */
122 #ifndef NET_DEBUG
123 #define NET_DEBUG 0
124 #endif
125 /*
126 * Global variable 'bionet_debug'. Can be set at load time by 'insmod'
127 */
128 unsigned int bionet_debug = NET_DEBUG;
129 MODULE_PARM(bionet_debug, "i");
130
131 static unsigned int bionet_min_poll_time = 2;
132
133
134 /* Information that need to be kept for each board.
135 */
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 */
140 };
141
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;
149
150 /* Index to functions, as function prototypes.
151 */
152 extern int bionet_probe(struct net_device *dev);
153
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);
160
161 static struct timer_list bionet_timer = { function: bionet_tick };
162
163 #define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
164
165 /* The following routines access the ethernet board connected to the
166 * ACSI port via the st_dma chip.
167 */
168 #define NODE_ADR 0x60
169
170 #define C_READ 8
171 #define C_WRITE 0x0a
172 #define C_GETEA 0x0f
173 #define C_SETCR 0x0e
174
175 static int
176 sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) {
177 unsigned int c;
178
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);
182
183 if( !acsi_wait_for_IRQ(HZ/2) ) /* wait for cmd ack */
184 return -1; /* timeout */
185
186 c = dma_wd.fdc_acces_seccount;
187 return (c & 0xff);
188 }
189
190
191 static void
192 set_status(int cr) {
193 sendcmd(0,0x100,NODE_ADR | C_SETCR); /* CMD: SET CR */
194 sendcmd(1,0x100,cr);
195
196 dma_wd.dma_mode_status = 0x80;
197 }
198
199 static int
200 get_status(unsigned char *adr) {
201 int i,c;
202
203 DISABLE_IRQ();
204 c = sendcmd(0,0x00,NODE_ADR | C_GETEA); /* CMD: GET ETH ADR*/
205 if( c < 0 ) goto gsend;
206
207 /* now read status bytes */
208
209 for (i=0; i<6; i++) {
210 dma_wd.fdc_acces_seccount = 0; /* request next byte */
211
212 if( !acsi_wait_for_IRQ(HZ/2) ) { /* wait for cmd ack */
213 c = -1;
214 goto gsend; /* timeout */
215 }
216 c = dma_wd.fdc_acces_seccount;
217 *adr++ = (unsigned char)c;
218 }
219 c = 1;
220 gsend:
221 dma_wd.dma_mode_status = 0x80;
222 return c;
223 }
224
225 static void
226 bionet_intr(int irq, void *data, struct pt_regs *fp) {
227 return;
228 }
229
230
231 static int
232 get_frame(unsigned long paddr, int odd) {
233 int c;
234 unsigned long flags;
235
236 DISABLE_IRQ();
237 save_flags(flags);
238 cli();
239
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);
250
251 c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */
252 if( c < 128 ) goto rend;
253
254 /* now read block */
255
256 c = sendcmd(1,0x00,odd); /* odd flag for address shift */
257 dma_wd.dma_mode_status = 0x0a;
258
259 if( !acsi_wait_for_IRQ(100) ) { /* wait for DMA to complete */
260 c = -1;
261 goto rend;
262 }
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;
267
268 dma_wd.dma_mode_status = 0x88;
269 c = dma_wd.fdc_acces_seccount;
270 c = 1;
271
272 rend:
273 dma_wd.dma_mode_status = 0x80;
274 udelay(40);
275 acsi_wait_for_noIRQ(20);
276 return c;
277 }
278
279
280 static int
281 hardware_send_packet(unsigned long paddr, int cnt) {
282 unsigned int c;
283 unsigned long flags;
284
285 DISABLE_IRQ();
286 save_flags(flags);
287 cli();
288
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;
297
298 dma_wd.fdc_acces_seccount = 0x4; /* sector count */
299 restore_flags(flags);
300
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);
304
305 /* now write block */
306
307 dma_wd.dma_mode_status = 0x10a; /* DMA enable */
308 if( !acsi_wait_for_IRQ(100) ) /* wait for DMA to complete */
309 goto end;
310
311 dma_wd.dma_mode_status = 0x19a; /* DMA disable ! */
312 c = dma_wd.fdc_acces_seccount;
313
314 end:
315 c = sendcmd(1,0x100,0);
316 c = sendcmd(1,0x100,0);
317
318 dma_wd.dma_mode_status = 0x180;
319 udelay(40);
320 acsi_wait_for_noIRQ(20);
321 return( c & 0x02);
322 }
323
324
325 /* Check for a network adaptor of this type, and return '' if one exists.
326 */
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;
333
334 if (!MACH_IS_ATARI || no_more_found)
335 return -ENODEV;
336
337 printk("Probing for BioNet 100 Adapter...\n");
338
339 stdma_lock(bionet_intr, NULL);
340 i = get_status(station_addr); /* Read the station address PROM. */
341 ENABLE_IRQ();
342 stdma_release();
343
344 /* Check the first three octets of the S.A. for the manufactor's code.
345 */
346
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;
354 }
355
356 SET_MODULE_OWNER(dev);
357
358 if (bionet_debug > 0 && version_printed++ == 0)
359 printk(version);
360
361 printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n",
362 dev->name, "BioNet 100",
363 station_addr[0], station_addr[1], station_addr[2],
364 station_addr[3], station_addr[4], station_addr[5]);
365
366 /* Initialize the device structure. */
367
368 nic_packet = (struct nic_pkt_s *)acsi_buffer;
369 phys_nic_packet = (unsigned char *)phys_acsi_buffer;
370 if (bionet_debug > 0) {
371 printk("nic_packet at 0x%p, phys at 0x%p\n",
372 nic_packet, phys_nic_packet );
373 }
374
375 if (dev->priv == NULL)
376 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
377 memset(dev->priv, 0, sizeof(struct net_local));
378
379 dev->open = bionet_open;
380 dev->stop = bionet_close;
381 dev->hard_start_xmit = bionet_send_packet;
382 dev->get_stats = net_get_stats;
383
384 /* Fill in the fields of the device structure with ethernet-generic
385 * values. This should be in a common file instead of per-driver.
386 */
387
388 for (i = 0; i < ETH_ALEN; i++) {
389 #if 0
390 dev->broadcast[i] = 0xff;
391 #endif
392 dev->dev_addr[i] = station_addr[i];
393 }
394 ether_setup(dev);
395 return 0;
396 }
397
398 /* Open/initialize the board. This is called (in the current kernel)
399 sometime after booting when the 'ifconfig' program is run.
400
401 This routine should set everything up anew at each open, even
402 registers that "should" only need to be set once at boot, so that
403 there is non-reboot way to recover if something goes wrong.
404 */
405 static int
406 bionet_open(struct net_device *dev) {
407 struct net_local *lp = (struct net_local *)dev->priv;
408
409 if (bionet_debug > 0)
410 printk("bionet_open\n");
411 stdma_lock(bionet_intr, NULL);
412
413 /* Reset the hardware here.
414 */
415 set_status(4);
416 lp->open_time = 0; /*jiffies*/
417 lp->poll_time = MAX_POLL_TIME;
418
419 dev->tbusy = 0;
420 dev->interrupt = 0;
421 dev->start = 1;
422
423 stdma_release();
424 bionet_timer.data = (long)dev;
425 bionet_timer.expires = jiffies + lp->poll_time;
426 add_timer(&bionet_timer);
427 return 0;
428 }
429
430 static int
431 bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
432 struct net_local *lp = (struct net_local *)dev->priv;
433 unsigned long flags;
434
435 /* Block a timer-based transmit from overlapping. This could better be
436 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
437 */
438 save_flags(flags);
439 cli();
440
441 if (stdma_islocked()) {
442 restore_flags(flags);
443 lp->stats.tx_errors++;
444 }
445 else {
446 int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
447 unsigned long buf = virt_to_phys(skb->data);
448 int stat;
449
450 stdma_lock(bionet_intr, NULL);
451 restore_flags(flags);
452 if( !STRAM_ADDR(buf+length-1) ) {
453 memcpy(nic_packet->buffer, skb->data, length);
454 buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer;
455 }
456
457 if (bionet_debug >1) {
458 u_char *data = nic_packet->buffer, *p;
459 int i;
460
461 printk( "%s: TX pkt type 0x%4x from ", dev->name,
462 ((u_short *)data)[6]);
463
464 for( p = &data[6], i = 0; i < 6; i++ )
465 printk("%02x%s", *p++,i != 5 ? ":" : "" );
466 printk(" to ");
467
468 for( p = data, i = 0; i < 6; i++ )
469 printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
470
471 printk( "%s: ", dev->name );
472 printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
473 " %02x%02x%02x%02x len %d\n",
474 data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
475 data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
476 data[28], data[29], data[30], data[31], data[32], data[33],
477 length );
478 }
479 dma_cache_maintenance(buf, length, 1);
480
481 stat = hardware_send_packet(buf, length);
482 ENABLE_IRQ();
483 stdma_release();
484
485 dev->trans_start = jiffies;
486 dev->tbusy = 0;
487 lp->stats.tx_packets++;
488 lp->stats.tx_bytes+=length;
489 }
490 dev_kfree_skb(skb);
491
492 return 0;
493 }
494
495 /* We have a good packet(s), get it/them out of the buffers.
496 */
497 static void
498 bionet_poll_rx(struct net_device *dev) {
499 struct net_local *lp = (struct net_local *)dev->priv;
500 int boguscount = 10;
501 int pkt_len, status;
502 unsigned long flags;
503
504 save_flags(flags);
505 cli();
506 /* ++roman: Take care at locking the ST-DMA... This must be done with ints
507 * off, since otherwise an int could slip in between the question and the
508 * locking itself, and then we'd go to sleep... And locking itself is
509 * necessary to keep the floppy_change timer from working with ST-DMA
510 * registers. */
511 if (stdma_islocked()) {
512 restore_flags(flags);
513 return;
514 }
515 stdma_lock(bionet_intr, NULL);
516 DISABLE_IRQ();
517 restore_flags(flags);
518
519 if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
520
521 while(boguscount--) {
522 status = get_frame((unsigned long)phys_nic_packet, 0);
523
524 if( status == 0 ) break;
525
526 /* Good packet... */
527
528 dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0);
529
530 pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo;
531
532 lp->poll_time = bionet_min_poll_time; /* fast poll */
533 if( pkt_len >= 60 && pkt_len <= 1520 ) {
534 /* ^^^^ war 1514 KHL */
535 /* Malloc up new buffer.
536 */
537 struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 );
538 if (skb == NULL) {
539 printk("%s: Memory squeeze, dropping packet.\n",
540 dev->name);
541 lp->stats.rx_dropped++;
542 break;
543 }
544
545 skb->dev = dev;
546 skb_reserve( skb, 2 ); /* 16 Byte align */
547 skb_put( skb, pkt_len ); /* make room */
548
549 /* 'skb->data' points to the start of sk_buff data area.
550 */
551 memcpy(skb->data, nic_packet->buffer, pkt_len);
552 skb->protocol = eth_type_trans( skb, dev );
553 netif_rx(skb);
554 lp->stats.rx_packets++;
555 lp->stats.rx_bytes+=pkt_len;
556
557 /* If any worth-while packets have been received, dev_rint()
558 has done a mark_bh(INET_BH) for us and will work on them
559 when we get to the bottom-half routine.
560 */
561
562 if (bionet_debug >1) {
563 u_char *data = nic_packet->buffer, *p;
564 int i;
565
566 printk( "%s: RX pkt type 0x%4x from ", dev->name,
567 ((u_short *)data)[6]);
568
569
570 for( p = &data[6], i = 0; i < 6; i++ )
571 printk("%02x%s", *p++,i != 5 ? ":" : "" );
572 printk(" to ");
573 for( p = data, i = 0; i < 6; i++ )
574 printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
575
576 printk( "%s: ", dev->name );
577 printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
578 " %02x%02x%02x%02x len %d\n",
579 data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
580 data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
581 data[28], data[29], data[30], data[31], data[32], data[33],
582 pkt_len );
583 }
584 }
585 else {
586 printk(" Packet has wrong length: %04d bytes\n", pkt_len);
587 lp->stats.rx_errors++;
588 }
589 }
590 stdma_release();
591 ENABLE_IRQ();
592 return;
593 }
594
595 /* bionet_tick: called by bionet_timer. Reads packets from the adapter,
596 * passes them to the higher layers and restarts the timer.
597 */
598 static void
599 bionet_tick(unsigned long data) {
600 struct net_device *dev = (struct net_device *)data;
601 struct net_local *lp = (struct net_local *)dev->priv;
602
603 if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 )
604 printk("bionet_tick: %ld\n", lp->open_time);
605
606 if( !stdma_islocked() ) bionet_poll_rx(dev);
607
608 bionet_timer.expires = jiffies + lp->poll_time;
609 add_timer(&bionet_timer);
610 }
611
612 /* The inverse routine to bionet_open().
613 */
614 static int
615 bionet_close(struct net_device *dev) {
616 struct net_local *lp = (struct net_local *)dev->priv;
617
618 if (bionet_debug > 0)
619 printk("bionet_close, open_time=%ld\n", lp->open_time);
620 del_timer(&bionet_timer);
621 stdma_lock(bionet_intr, NULL);
622
623 set_status(0);
624 lp->open_time = 0;
625
626 dev->tbusy = 1;
627 dev->start = 0;
628
629 stdma_release();
630 return 0;
631 }
632
633 /* Get the current statistics.
634 This may be called with the card open or closed.
635 */
636 static struct net_device_stats *net_get_stats(struct net_device *dev)
637 {
638 struct net_local *lp = (struct net_local *)dev->priv;
639 return &lp->stats;
640 }
641
642
643 #ifdef MODULE
644
645 static struct net_device bio_dev;
646
647 int
648 init_module(void) {
649 int err;
650
651 bio_dev.init = bionet_probe;
652 if ((err = register_netdev(&bio_dev))) {
653 if (err == -EEXIST) {
654 printk("BIONET: devices already present. Module not loaded.\n");
655 }
656 return err;
657 }
658 return 0;
659 }
660
661 void
662 cleanup_module(void) {
663 unregister_netdev(&bio_dev);
664 }
665
666 #endif /* MODULE */
667
668 /* Local variables:
669 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
670 -b m68k-linuxaout -Wall -Wstrict-prototypes -O2
671 -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c"
672 * version-control: t
673 * kept-new-versions: 5
674 * tab-width: 8
675 * End:
676 */
677
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.