Commit | Line | Data |
---|---|---|
1da177e4 LT |
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/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> | |
100 | #include <linux/bitops.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/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> | |
115 | ||
116 | ||
117 | /* use 0 for production, 1 for verification, >2 for debug | |
118 | */ | |
119 | #ifndef NET_DEBUG | |
120 | #define NET_DEBUG 0 | |
121 | #endif | |
122 | /* | |
123 | * Global variable 'bionet_debug'. Can be set at load time by 'insmod' | |
124 | */ | |
125 | unsigned int bionet_debug = NET_DEBUG; | |
8d3b33f6 | 126 | module_param(bionet_debug, int, 0); |
1da177e4 LT |
127 | MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)"); |
128 | MODULE_LICENSE("GPL"); | |
129 | ||
130 | static unsigned int bionet_min_poll_time = 2; | |
131 | ||
132 | ||
133 | /* Information that need to be kept for each board. | |
134 | */ | |
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 */ | |
139 | }; | |
140 | ||
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; | |
148 | ||
149 | /* Index to functions, as function prototypes. | |
150 | */ | |
151 | static int bionet_open(struct net_device *dev); | |
152 | static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev); | |
153 | static void bionet_poll_rx(struct net_device *); | |
154 | static int bionet_close(struct net_device *dev); | |
155 | static struct net_device_stats *net_get_stats(struct net_device *dev); | |
156 | static void bionet_tick(unsigned long); | |
157 | ||
8d06afab | 158 | static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0); |
1da177e4 LT |
159 | |
160 | #define STRAM_ADDR(a) (((a) & 0xff000000) == 0) | |
161 | ||
162 | /* The following routines access the ethernet board connected to the | |
163 | * ACSI port via the st_dma chip. | |
164 | */ | |
165 | #define NODE_ADR 0x60 | |
166 | ||
167 | #define C_READ 8 | |
168 | #define C_WRITE 0x0a | |
169 | #define C_GETEA 0x0f | |
170 | #define C_SETCR 0x0e | |
171 | ||
172 | static int | |
173 | sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) { | |
174 | unsigned int c; | |
175 | ||
176 | dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88); | |
177 | dma_wd.fdc_acces_seccount = cmd; | |
178 | dma_wd.dma_mode_status = (mod | 0x8a); | |
179 | ||
180 | if( !acsi_wait_for_IRQ(HZ/2) ) /* wait for cmd ack */ | |
181 | return -1; /* timeout */ | |
182 | ||
183 | c = dma_wd.fdc_acces_seccount; | |
184 | return (c & 0xff); | |
185 | } | |
186 | ||
187 | ||
188 | static void | |
189 | set_status(int cr) { | |
190 | sendcmd(0,0x100,NODE_ADR | C_SETCR); /* CMD: SET CR */ | |
191 | sendcmd(1,0x100,cr); | |
192 | ||
193 | dma_wd.dma_mode_status = 0x80; | |
194 | } | |
195 | ||
196 | static int | |
197 | get_status(unsigned char *adr) { | |
198 | int i,c; | |
199 | ||
200 | DISABLE_IRQ(); | |
201 | c = sendcmd(0,0x00,NODE_ADR | C_GETEA); /* CMD: GET ETH ADR*/ | |
202 | if( c < 0 ) goto gsend; | |
203 | ||
204 | /* now read status bytes */ | |
205 | ||
206 | for (i=0; i<6; i++) { | |
207 | dma_wd.fdc_acces_seccount = 0; /* request next byte */ | |
208 | ||
209 | if( !acsi_wait_for_IRQ(HZ/2) ) { /* wait for cmd ack */ | |
210 | c = -1; | |
211 | goto gsend; /* timeout */ | |
212 | } | |
213 | c = dma_wd.fdc_acces_seccount; | |
214 | *adr++ = (unsigned char)c; | |
215 | } | |
216 | c = 1; | |
217 | gsend: | |
218 | dma_wd.dma_mode_status = 0x80; | |
219 | return c; | |
220 | } | |
221 | ||
222 | static irqreturn_t | |
7d12e780 | 223 | bionet_intr(int irq, void *data) { |
1da177e4 LT |
224 | return IRQ_HANDLED; |
225 | } | |
226 | ||
227 | ||
228 | static int | |
229 | get_frame(unsigned long paddr, int odd) { | |
230 | int c; | |
231 | unsigned long flags; | |
232 | ||
233 | DISABLE_IRQ(); | |
234 | local_irq_save(flags); | |
235 | ||
236 | dma_wd.dma_mode_status = 0x9a; | |
237 | dma_wd.dma_mode_status = 0x19a; | |
238 | dma_wd.dma_mode_status = 0x9a; | |
239 | dma_wd.fdc_acces_seccount = 0x04; /* sector count (was 5) */ | |
240 | dma_wd.dma_lo = (unsigned char)paddr; | |
241 | paddr >>= 8; | |
242 | dma_wd.dma_md = (unsigned char)paddr; | |
243 | paddr >>= 8; | |
244 | dma_wd.dma_hi = (unsigned char)paddr; | |
245 | local_irq_restore(flags); | |
246 | ||
247 | c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */ | |
248 | if( c < 128 ) goto rend; | |
249 | ||
250 | /* now read block */ | |
251 | ||
252 | c = sendcmd(1,0x00,odd); /* odd flag for address shift */ | |
253 | dma_wd.dma_mode_status = 0x0a; | |
254 | ||
255 | if( !acsi_wait_for_IRQ(100) ) { /* wait for DMA to complete */ | |
256 | c = -1; | |
257 | goto rend; | |
258 | } | |
259 | dma_wd.dma_mode_status = 0x8a; | |
260 | dma_wd.dma_mode_status = 0x18a; | |
261 | dma_wd.dma_mode_status = 0x8a; | |
262 | c = dma_wd.fdc_acces_seccount; | |
263 | ||
264 | dma_wd.dma_mode_status = 0x88; | |
265 | c = dma_wd.fdc_acces_seccount; | |
266 | c = 1; | |
267 | ||
268 | rend: | |
269 | dma_wd.dma_mode_status = 0x80; | |
270 | udelay(40); | |
271 | acsi_wait_for_noIRQ(20); | |
272 | return c; | |
273 | } | |
274 | ||
275 | ||
276 | static int | |
277 | hardware_send_packet(unsigned long paddr, int cnt) { | |
278 | unsigned int c; | |
279 | unsigned long flags; | |
280 | ||
281 | DISABLE_IRQ(); | |
282 | local_irq_save(flags); | |
283 | ||
284 | dma_wd.dma_mode_status = 0x19a; | |
285 | dma_wd.dma_mode_status = 0x9a; | |
286 | dma_wd.dma_mode_status = 0x19a; | |
287 | dma_wd.dma_lo = (unsigned char)paddr; | |
288 | paddr >>= 8; | |
289 | dma_wd.dma_md = (unsigned char)paddr; | |
290 | paddr >>= 8; | |
291 | dma_wd.dma_hi = (unsigned char)paddr; | |
292 | ||
293 | dma_wd.fdc_acces_seccount = 0x4; /* sector count */ | |
294 | local_irq_restore(flags); | |
295 | ||
296 | c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */ | |
297 | c = sendcmd(1,0x100,cnt&0xff); | |
298 | c = sendcmd(1,0x100,cnt>>8); | |
299 | ||
300 | /* now write block */ | |
301 | ||
302 | dma_wd.dma_mode_status = 0x10a; /* DMA enable */ | |
303 | if( !acsi_wait_for_IRQ(100) ) /* wait for DMA to complete */ | |
304 | goto end; | |
305 | ||
306 | dma_wd.dma_mode_status = 0x19a; /* DMA disable ! */ | |
307 | c = dma_wd.fdc_acces_seccount; | |
308 | ||
309 | end: | |
310 | c = sendcmd(1,0x100,0); | |
311 | c = sendcmd(1,0x100,0); | |
312 | ||
313 | dma_wd.dma_mode_status = 0x180; | |
314 | udelay(40); | |
315 | acsi_wait_for_noIRQ(20); | |
316 | return( c & 0x02); | |
317 | } | |
318 | ||
319 | ||
320 | /* Check for a network adaptor of this type, and return '0' if one exists. | |
321 | */ | |
322 | struct net_device * __init bionet_probe(int unit) | |
323 | { | |
324 | struct net_device *dev; | |
325 | unsigned char station_addr[6]; | |
326 | static unsigned version_printed; | |
327 | static int no_more_found; /* avoid "Probing for..." printed 4 times */ | |
328 | int i; | |
329 | int err; | |
330 | ||
331 | if (!MACH_IS_ATARI || no_more_found) | |
332 | return ERR_PTR(-ENODEV); | |
333 | ||
334 | dev = alloc_etherdev(sizeof(struct net_local)); | |
335 | if (!dev) | |
336 | return ERR_PTR(-ENOMEM); | |
337 | if (unit >= 0) { | |
338 | sprintf(dev->name, "eth%d", unit); | |
339 | netdev_boot_setup_check(dev); | |
340 | } | |
341 | SET_MODULE_OWNER(dev); | |
342 | ||
343 | printk("Probing for BioNet 100 Adapter...\n"); | |
344 | ||
345 | stdma_lock(bionet_intr, NULL); | |
346 | i = get_status(station_addr); /* Read the station address PROM. */ | |
347 | ENABLE_IRQ(); | |
348 | stdma_release(); | |
349 | ||
350 | /* Check the first three octets of the S.A. for the manufactor's code. | |
351 | */ | |
352 | ||
353 | if( i < 0 | |
354 | || station_addr[0] != 'B' | |
355 | || station_addr[1] != 'I' | |
356 | || station_addr[2] != 'O' ) { | |
357 | no_more_found = 1; | |
358 | printk( "No BioNet 100 found.\n" ); | |
359 | free_netdev(dev); | |
360 | return ERR_PTR(-ENODEV); | |
361 | } | |
362 | ||
363 | if (bionet_debug > 0 && version_printed++ == 0) | |
364 | printk(version); | |
365 | ||
366 | printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n", | |
367 | dev->name, "BioNet 100", | |
368 | station_addr[0], station_addr[1], station_addr[2], | |
369 | station_addr[3], station_addr[4], station_addr[5]); | |
370 | ||
371 | /* Initialize the device structure. */ | |
372 | ||
373 | nic_packet = (struct nic_pkt_s *)acsi_buffer; | |
374 | phys_nic_packet = (unsigned char *)phys_acsi_buffer; | |
375 | if (bionet_debug > 0) { | |
376 | printk("nic_packet at 0x%p, phys at 0x%p\n", | |
377 | nic_packet, phys_nic_packet ); | |
378 | } | |
379 | ||
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; | |
384 | ||
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. | |
387 | */ | |
388 | ||
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]; | |
394 | } | |
395 | err = register_netdev(dev); | |
396 | if (!err) | |
397 | return dev; | |
398 | free_netdev(dev); | |
399 | return ERR_PTR(err); | |
400 | } | |
401 | ||
402 | /* Open/initialize the board. This is called (in the current kernel) | |
403 | sometime after booting when the 'ifconfig' program is run. | |
404 | ||
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. | |
408 | */ | |
409 | static int | |
410 | bionet_open(struct net_device *dev) { | |
411 | struct net_local *lp = netdev_priv(dev); | |
412 | ||
413 | if (bionet_debug > 0) | |
414 | printk("bionet_open\n"); | |
415 | stdma_lock(bionet_intr, NULL); | |
416 | ||
417 | /* Reset the hardware here. | |
418 | */ | |
419 | set_status(4); | |
420 | lp->open_time = 0; /*jiffies*/ | |
421 | lp->poll_time = MAX_POLL_TIME; | |
422 | ||
423 | dev->tbusy = 0; | |
424 | dev->interrupt = 0; | |
425 | dev->start = 1; | |
426 | ||
427 | stdma_release(); | |
428 | bionet_timer.data = (long)dev; | |
429 | bionet_timer.expires = jiffies + lp->poll_time; | |
430 | add_timer(&bionet_timer); | |
431 | return 0; | |
432 | } | |
433 | ||
434 | static int | |
435 | bionet_send_packet(struct sk_buff *skb, struct net_device *dev) { | |
436 | struct net_local *lp = netdev_priv(dev); | |
437 | unsigned long flags; | |
438 | ||
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. | |
441 | */ | |
442 | local_irq_save(flags); | |
443 | ||
444 | if (stdma_islocked()) { | |
445 | local_irq_restore(flags); | |
446 | lp->stats.tx_errors++; | |
447 | } | |
448 | else { | |
449 | int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; | |
450 | unsigned long buf = virt_to_phys(skb->data); | |
451 | int stat; | |
452 | ||
453 | stdma_lock(bionet_intr, NULL); | |
454 | local_irq_restore(flags); | |
455 | if( !STRAM_ADDR(buf+length-1) ) { | |
456 | memcpy(nic_packet->buffer, skb->data, length); | |
457 | buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer; | |
458 | } | |
459 | ||
460 | if (bionet_debug >1) { | |
461 | u_char *data = nic_packet->buffer, *p; | |
462 | int i; | |
6aa20a22 | 463 | |
1da177e4 LT |
464 | printk( "%s: TX pkt type 0x%4x from ", dev->name, |
465 | ((u_short *)data)[6]); | |
466 | ||
467 | for( p = &data[6], i = 0; i < 6; i++ ) | |
468 | printk("%02x%s", *p++,i != 5 ? ":" : "" ); | |
469 | printk(" to "); | |
470 | ||
471 | for( p = data, i = 0; i < 6; i++ ) | |
472 | printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); | |
473 | ||
474 | printk( "%s: ", dev->name ); | |
475 | printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" | |
476 | " %02x%02x%02x%02x len %d\n", | |
477 | data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], | |
478 | data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], | |
479 | data[28], data[29], data[30], data[31], data[32], data[33], | |
480 | length ); | |
481 | } | |
482 | dma_cache_maintenance(buf, length, 1); | |
483 | ||
484 | stat = hardware_send_packet(buf, length); | |
485 | ENABLE_IRQ(); | |
486 | stdma_release(); | |
487 | ||
488 | dev->trans_start = jiffies; | |
489 | dev->tbusy = 0; | |
490 | lp->stats.tx_packets++; | |
491 | lp->stats.tx_bytes+=length; | |
492 | } | |
493 | dev_kfree_skb(skb); | |
494 | ||
495 | return 0; | |
496 | } | |
497 | ||
498 | /* We have a good packet(s), get it/them out of the buffers. | |
499 | */ | |
500 | static void | |
501 | bionet_poll_rx(struct net_device *dev) { | |
502 | struct net_local *lp = netdev_priv(dev); | |
503 | int boguscount = 10; | |
504 | int pkt_len, status; | |
505 | unsigned long flags; | |
506 | ||
507 | local_irq_save(flags); | |
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 | local_irq_restore(flags); | |
515 | return; | |
516 | } | |
517 | stdma_lock(bionet_intr, NULL); | |
518 | DISABLE_IRQ(); | |
519 | local_irq_restore(flags); | |
520 | ||
521 | if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; | |
522 | ||
523 | while(boguscount--) { | |
524 | status = get_frame((unsigned long)phys_nic_packet, 0); | |
525 | ||
526 | if( status == 0 ) break; | |
527 | ||
528 | /* Good packet... */ | |
529 | ||
530 | dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0); | |
531 | ||
532 | pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo; | |
533 | ||
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. | |
538 | */ | |
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; | |
545 | } | |
546 | ||
547 | skb->dev = dev; | |
548 | skb_reserve( skb, 2 ); /* 16 Byte align */ | |
549 | skb_put( skb, pkt_len ); /* make room */ | |
550 | ||
551 | /* 'skb->data' points to the start of sk_buff data area. | |
552 | */ | |
553 | memcpy(skb->data, nic_packet->buffer, pkt_len); | |
6aa20a22 | 554 | skb->protocol = eth_type_trans( skb, dev ); |
1da177e4 LT |
555 | netif_rx(skb); |
556 | dev->last_rx = jiffies; | |
557 | lp->stats.rx_packets++; | |
558 | lp->stats.rx_bytes+=pkt_len; | |
559 | ||
560 | /* If any worth-while packets have been received, dev_rint() | |
561 | has done a mark_bh(INET_BH) for us and will work on them | |
562 | when we get to the bottom-half routine. | |
563 | */ | |
564 | ||
565 | if (bionet_debug >1) { | |
566 | u_char *data = nic_packet->buffer, *p; | |
567 | int i; | |
6aa20a22 | 568 | |
1da177e4 LT |
569 | printk( "%s: RX pkt type 0x%4x from ", dev->name, |
570 | ((u_short *)data)[6]); | |
6aa20a22 JG |
571 | |
572 | ||
1da177e4 LT |
573 | for( p = &data[6], i = 0; i < 6; i++ ) |
574 | printk("%02x%s", *p++,i != 5 ? ":" : "" ); | |
575 | printk(" to "); | |
576 | for( p = data, i = 0; i < 6; i++ ) | |
577 | printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); | |
6aa20a22 | 578 | |
1da177e4 LT |
579 | printk( "%s: ", dev->name ); |
580 | printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" | |
581 | " %02x%02x%02x%02x len %d\n", | |
582 | data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], | |
583 | data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], | |
584 | data[28], data[29], data[30], data[31], data[32], data[33], | |
585 | pkt_len ); | |
586 | } | |
587 | } | |
588 | else { | |
589 | printk(" Packet has wrong length: %04d bytes\n", pkt_len); | |
590 | lp->stats.rx_errors++; | |
591 | } | |
592 | } | |
593 | stdma_release(); | |
594 | ENABLE_IRQ(); | |
595 | return; | |
596 | } | |
597 | ||
598 | /* bionet_tick: called by bionet_timer. Reads packets from the adapter, | |
599 | * passes them to the higher layers and restarts the timer. | |
600 | */ | |
601 | static void | |
602 | bionet_tick(unsigned long data) { | |
603 | struct net_device *dev = (struct net_device *)data; | |
604 | struct net_local *lp = netdev_priv(dev); | |
605 | ||
606 | if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 ) | |
607 | printk("bionet_tick: %ld\n", lp->open_time); | |
608 | ||
609 | if( !stdma_islocked() ) bionet_poll_rx(dev); | |
610 | ||
611 | bionet_timer.expires = jiffies + lp->poll_time; | |
612 | add_timer(&bionet_timer); | |
613 | } | |
614 | ||
615 | /* The inverse routine to bionet_open(). | |
616 | */ | |
617 | static int | |
618 | bionet_close(struct net_device *dev) { | |
619 | struct net_local *lp = netdev_priv(dev); | |
620 | ||
621 | if (bionet_debug > 0) | |
622 | printk("bionet_close, open_time=%ld\n", lp->open_time); | |
623 | del_timer(&bionet_timer); | |
624 | stdma_lock(bionet_intr, NULL); | |
625 | ||
626 | set_status(0); | |
627 | lp->open_time = 0; | |
628 | ||
629 | dev->tbusy = 1; | |
630 | dev->start = 0; | |
631 | ||
632 | stdma_release(); | |
633 | return 0; | |
634 | } | |
635 | ||
636 | /* Get the current statistics. | |
637 | This may be called with the card open or closed. | |
638 | */ | |
6aa20a22 | 639 | static struct net_device_stats *net_get_stats(struct net_device *dev) |
1da177e4 LT |
640 | { |
641 | struct net_local *lp = netdev_priv(dev); | |
642 | return &lp->stats; | |
643 | } | |
644 | ||
645 | ||
646 | #ifdef MODULE | |
647 | ||
648 | static struct net_device *bio_dev; | |
649 | ||
650 | int init_module(void) | |
651 | { | |
652 | bio_dev = bionet_probe(-1); | |
653 | if (IS_ERR(bio_dev)) | |
654 | return PTR_ERR(bio_dev); | |
655 | return 0; | |
656 | } | |
657 | ||
658 | void cleanup_module(void) | |
659 | { | |
660 | unregister_netdev(bio_dev); | |
661 | free_netdev(bio_dev); | |
662 | } | |
663 | ||
664 | #endif /* MODULE */ | |
665 | ||
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: | |
674 | */ |