1 /* atari_pamsnet.c PAMsNet device driver for linux68k.
3 * Version: @(#)PAMsNet.c 0.2ß 03/31/96
5 * Author: Torsten Lang <Torsten.Lang@ap.physik.uni-giessen.de>
6 * <Torsten.Lang@jung.de>
8 * This driver is based on my driver PAMSDMA.c for MiNT-Net and
9 * on the driver bionet.c written by
10 * Hartmut Laue <laue@ifk-mp.uni-kiel.de>
11 * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de>
13 * Little adaptions for integration into pl7 by Roman Hodek
17 This driver controls the PAMsNet LAN-Adapter which connects
18 an ATARI ST/TT via the ACSI-port to an Ethernet-based network.
20 This version can be compiled as a loadable module (See the
21 compile command at the bottom of this file).
22 At load time, you can optionally set the debugging level and the
23 fastest response time on the command line of 'insmod'.
26 controls the amount of diagnostic messages:
28 >0 : see code for meaning of printed messages
30 'pamsnet_min_poll_time' (always >=1)
31 gives the time (in jiffies) between polls. Low values
32 increase the system load (beware!)
34 When loaded, a net device with the name 'eth?' becomes available,
35 which can be controlled with the usual 'ifconfig' command.
37 It is possible to compile this driver into the kernel like other
38 (net) drivers. For this purpose, some source files (e.g. config-files
39 makefiles, Space.c) must be changed accordingly. (You may refer to
40 other drivers how to do it.) In this case, the device will be detected
41 at boot time and (probably) appear as 'eth0'.
45 Because the ATARI DMA port is usually shared between several
46 devices (eg. harddisk, floppy) we cannot block the ACSI bus
47 while waiting for interrupts. Therefore we use a polling mechanism
48 to fetch packets from the adapter. For the same reason, we send
49 packets without checking that the previous packet has been sent to
50 the LAN. We rely on the higher levels of the networking code to detect
51 missing packets and resend them.
53 Before we access the ATARI DMA controller, we check if another
54 process is using the DMA. If not, we lock the DMA, perform one or
55 more packet transfers and unlock the DMA before returning.
56 We do not use 'stdma_lock' unconditionally because it is unclear
57 if the networking code can be set to sleep, which will happen if
58 another (possibly slow) device is using the DMA controller.
60 The polling is done via timer interrupts which periodically
61 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies)
62 between polls varies depending on an estimate of the net activity.
63 The allowed range is given by the variable 'bionet_min_poll_time'
64 for the lower (fastest) limit and the constant 'MAX_POLL_TIME'
65 for the higher (slowest) limit.
67 Whenever a packet arrives, we switch to fastest response by setting
68 the polling time to its lowest limit. If the following poll fails,
69 because no packets have arrived, we increase the time for the next
70 poll. When the net activity is low, the polling time effectively
71 stays at its maximum value, resulting in the lowest load for the
75 #define MAX_POLL_TIME 10
77 static char *version
=
78 "pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n";
80 #include <linux/module.h>
82 #include <linux/kernel.h>
83 #include <linux/sched.h>
84 #include <linux/types.h>
85 #include <linux/fcntl.h>
86 #include <linux/interrupt.h>
87 #include <linux/ptrace.h>
88 #include <linux/ioport.h>
90 #include <linux/malloc.h>
91 #include <linux/string.h>
92 #include <asm/system.h>
93 #include <asm/pgtable.h>
94 #include <asm/bitops.h>
97 #include <linux/errno.h>
98 #include <asm/atarihw.h>
99 #include <asm/atariints.h>
100 #include <asm/atari_stdma.h>
101 #include <asm/atari_acsi.h>
103 #include <linux/delay.h>
104 #include <linux/timer.h>
105 #include <linux/init.h>
107 #include <linux/netdevice.h>
108 #include <linux/etherdevice.h>
109 #include <linux/skbuff.h>
114 extern struct net_device
*init_etherdev(struct net_device
*dev
, int sizeof_private
);
116 /* use 0 for production, 1 for verification, >2 for debug
122 * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod'
124 unsigned int pamsnet_debug
= NET_DEBUG
;
125 MODULE_PARM(pamsnet_debug
, "i");
127 static unsigned int pamsnet_min_poll_time
= 2;
130 /* Information that need to be kept for each board.
133 struct net_device_stats stats
;
134 long open_time
; /* for debugging */
135 int poll_time
; /* polling time varies with net load */
138 static struct nic_pkt_s
{ /* packet format */
139 unsigned char buffer
[2048];
141 unsigned char *phys_nic_packet
;
143 typedef unsigned char HADDR
[6]; /* 6-byte hardware address of lance */
145 /* Index to functions, as function prototypes.
147 static void start (int target
);
148 static int stop (int target
);
149 static int testpkt (int target
);
150 static int sendpkt (int target
, unsigned char *buffer
, int length
);
151 static int receivepkt (int target
, unsigned char *buffer
);
152 static int inquiry (int target
, unsigned char *buffer
);
153 static HADDR
*read_hw_addr(int target
, unsigned char *buffer
);
154 static void setup_dma (void *address
, unsigned rw_flag
, int num_blocks
);
155 static int send_first (int target
, unsigned char byte
);
156 static int send_1_5 (int lun
, unsigned char *command
, int dma
);
157 static int get_status (void);
158 static int calc_received (void *start_address
);
160 extern int pamsnet_probe(struct net_device
*dev
);
162 static int pamsnet_open(struct net_device
*dev
);
163 static int pamsnet_send_packet(struct sk_buff
*skb
, struct net_device
*dev
);
164 static void pamsnet_poll_rx(struct net_device
*);
165 static int pamsnet_close(struct net_device
*dev
);
166 static struct net_device_stats
*net_get_stats(struct net_device
*dev
);
167 static void pamsnet_tick(unsigned long);
169 static void pamsnet_intr(int irq
, void *data
, struct pt_regs
*fp
);
171 static struct timer_list pamsnet_timer
= { NULL
, NULL
, 0, 0, pamsnet_tick
};
173 #define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
177 unsigned char reserved1
[0x38];
179 unsigned char reserved2
[0x1c2];
183 * Definitions of commands understood by the PAMs DMA adaptor.
185 * In general the DMA adaptor uses LUN 0, 5, 6 and 7 on one ID changeable
186 * by the PAM's Net software.
188 * LUN 0 works as a harddisk. You can boot the PAM's Net driver there.
189 * LUN 5 works as a harddisk and lets you access the RAM and some I/O HW
190 * area. In sector 0, bytes 0x38-0x3d you find the ethernet HW address
192 * LUN 6 works as a harddisk and lets you access the firmware ROM.
193 * LUN 7 lets you send and receive packets.
195 * Some commands like the INQUIRY command work identical on all used LUNs.
197 * UNKNOWN1 seems to read some data.
198 * Command length is 6 bytes.
199 * UNKNOWN2 seems to read some data (command byte 1 must be !=0). The
200 * following bytes seem to be something like an allocation length.
201 * Command length is 6 bytes.
202 * READPKT reads a packet received by the DMA adaptor.
203 * Command length is 6 bytes.
204 * WRITEPKT sends a packet transferred by the following DMA phase. The length
205 * of the packet is transferred in command bytes 3 and 4.
206 * The adaptor automatically replaces the src hw address in an ethernet
207 * packet by its own hw address.
208 * Command length is 6 bytes.
209 * INQUIRY has the same function as the INQUIRY command supported by harddisks
210 * and other SCSI devices. It lets you detect which device you found
211 * at a given address.
212 * Command length is 6 bytes.
213 * START initializes the DMA adaptor. After this command it is able to send
214 * and receive packets. There is no status byte returned!
215 * Command length is 1 byte.
216 * NUMPKTS gives back the number of received packets waiting in the queue in
218 * Command length is 1 byte.
220 * UNKNOWN4 Function of these three commands is unknown.
221 * UNKNOWN5 The command length of these three commands is 1 byte.
222 * DESELECT immediately deselects the DMA adaptor. May important with interrupt
224 * Command length is 1 byte.
225 * STOP resets the DMA adaptor. After this command packets can no longer
226 * be received or transferred.
227 * Command length is 6 byte.
230 enum {UNKNOWN1
=3, READPKT
=8, UNKNOWN2
, WRITEPKT
=10, INQUIRY
=18, START
,
231 NUMPKTS
=22, UNKNOWN3
, UNKNOWN4
, UNKNOWN5
, DESELECT
, STOP
};
233 #define READSECTOR READPKT
234 #define WRITESECTOR WRITEPKT
236 u_char
*inquire8
="MV PAM's NET/GK";
238 #define DMALOW dma_wd.dma_lo
239 #define DMAMID dma_wd.dma_md
240 #define DMAHIGH dma_wd.dma_hi
241 #define DACCESS dma_wd.fdc_acces_seccount
243 #define MFP_GPIP mfp.par_dt_reg
245 /* Some useful functions */
247 #define INT (!(MFP_GPIP & 0x20))
248 #define DELAY ({MFP_GPIP; MFP_GPIP; MFP_GPIP;})
249 #define WRITEMODE(value) \
250 ({ u_short dummy = value; \
251 __asm__ volatile("movew %0, 0xFFFF8606" : : "d"(dummy)); \
254 #define WRITEBOTH(value1, value2) \
255 ({ u_long dummy = (u_long)(value1)<<16 | (u_short)(value2); \
256 __asm__ volatile("movel %0, 0xFFFF8604" : : "d"(dummy)); \
260 /* Definitions for DMODE */
265 #define DMA_FDC 0x080
266 #define DMA_ACSI 0x000
268 #define DMA_DISABLE 0x040
270 #define SEC_COUNT 0x010
271 #define DMA_WINDOW 0x000
273 #define REG_ACSI 0x008
274 #define REG_FDC 0x000
278 /* Timeout constants */
280 #define TIMEOUTCMD HZ/2 /* ca. 500ms */
281 #define TIMEOUTDMA HZ /* ca. 1s */
282 #define COMMAND_DELAY 500 /* ca. 0.5ms */
285 int lance_target
= -1;
288 /* The following routines access the ethernet board connected to the
289 * ACSI port via the st_dma chip.
292 /* The following lowlevel routines work on physical addresses only and assume
293 * that eventually needed buffers are
294 * - completely located in ST RAM
295 * - are contigous in the physical address space
298 /* Setup the DMA counter */
301 setup_dma (address
, rw_flag
, num_blocks
)
306 WRITEMODE((unsigned) rw_flag
| DMA_FDC
| SEC_COUNT
| REG_ACSI
|
308 WRITEMODE((unsigned)(rw_flag
^ WRITE
) | DMA_FDC
| SEC_COUNT
| REG_ACSI
|
310 WRITEMODE((unsigned) rw_flag
| DMA_FDC
| SEC_COUNT
| REG_ACSI
|
312 DMALOW
= (unsigned char)((unsigned long)address
& 0xFF);
313 DMAMID
= (unsigned char)(((unsigned long)address
>> 8) & 0xFF);
314 DMAHIGH
= (unsigned char)(((unsigned long)address
>> 16) & 0xFF);
315 WRITEBOTH((unsigned)num_blocks
& 0xFF,
316 rw_flag
| DMA_FDC
| DMA_WINDOW
| REG_ACSI
| A1
);
320 /* Send the first byte of an command block */
323 send_first (target
, byte
)
328 acsi_delay_end(COMMAND_DELAY
);
332 WRITEMODE(DMA_FDC
| DMA_WINDOW
| REG_ACSI
);
336 WRITEBOTH((target
<< 5) | (byte
& 0x1F), DMA_FDC
|
337 DMA_WINDOW
| REG_ACSI
| A1
);
338 return (!acsi_wait_for_IRQ(TIMEOUTCMD
));
341 /* Send the rest of an command block */
344 send_1_5 (lun
, command
, dma
)
346 unsigned char *command
;
351 for (i
=0; i
<5; i
++) {
352 WRITEBOTH((!i
? (((lun
& 0x7) << 5) | (command
[i
] & 0x1F))
354 rw
| REG_ACSI
| DMA_WINDOW
|
358 if (i
< 4 && (j
= !acsi_wait_for_IRQ(TIMEOUTCMD
)))
364 /* Read a status byte */
369 WRITEMODE(DMA_FDC
| DMA_WINDOW
| REG_ACSI
| A1
);
371 return ((int)(DACCESS
& 0xFF));
374 /* Calculate the number of received bytes */
377 calc_received (start_address
)
381 (((unsigned long)DMAHIGH
<< 16) | ((unsigned)DMAMID
<< 8) | DMALOW
)
382 - (unsigned long)start_address
);
385 /* The following midlevel routines still work on physical addresses ... */
387 /* start() starts the PAM's DMA adaptor */
393 send_first(target
, START
);
396 /* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */
403 unsigned char cmd_buffer
[5];
405 if (send_first(target
, STOP
))
407 cmd_buffer
[0] = cmd_buffer
[1] = cmd_buffer
[2] =
408 cmd_buffer
[3] = cmd_buffer
[4] = 0;
409 if (send_1_5(7, cmd_buffer
, 0) ||
410 !acsi_wait_for_IRQ(TIMEOUTDMA
) ||
418 /* testpkt() returns the number of received packets waiting in the queue */
426 if (send_first(target
, NUMPKTS
))
433 /* inquiry() returns 0 when PAM's DMA found, -1 when timeout, -2 otherwise */
434 /* Please note: The buffer is for internal use only but must be defined! */
437 inquiry (target
, buffer
)
439 unsigned char *buffer
;
442 unsigned char *vbuffer
= phys_to_virt((unsigned long)buffer
);
443 unsigned char cmd_buffer
[5];
445 if (send_first(target
, INQUIRY
))
447 setup_dma(buffer
, READ
, 1);
448 vbuffer
[8] = vbuffer
[27] = 0; /* Avoid confusion with previous read data */
449 cmd_buffer
[0] = cmd_buffer
[1] = cmd_buffer
[2] = cmd_buffer
[4] = 0;
451 if (send_1_5(5, cmd_buffer
, 1) ||
452 !acsi_wait_for_IRQ(TIMEOUTDMA
) ||
454 (calc_received(buffer
) < 32))
456 dma_cache_maintenance((unsigned long)(buffer
+8), 20, 0);
457 if (memcmp(inquire8
, vbuffer
+8, 20))
463 printk("inquiry of target %d: %s\n", target
, vbuffer
+8);
469 * read_hw_addr() reads the sector containing the hwaddr and returns
470 * a pointer to it (virtual address!) or 0 in case of an error
474 *read_hw_addr(target
, buffer
)
476 unsigned char *buffer
;
479 unsigned char cmd_buffer
[5];
481 if (send_first(target
, READSECTOR
))
483 setup_dma(buffer
, READ
, 1);
484 cmd_buffer
[0] = cmd_buffer
[1] = cmd_buffer
[2] = cmd_buffer
[4] = 0;
486 if (send_1_5(5, cmd_buffer
, 1) ||
487 !acsi_wait_for_IRQ(TIMEOUTDMA
) ||
490 ret
= phys_to_virt(&(((DMAHWADDR
*)buffer
)->hwaddr
));
491 dma_cache_maintenance((unsigned long)buffer
, 512, 0);
497 pamsnet_intr(irq
, data
, fp
)
505 /* receivepkt() loads a packet to a given buffer and returns its length */
508 receivepkt (target
, buffer
)
510 unsigned char *buffer
;
513 unsigned char cmd_buffer
[5];
515 if (send_first(target
, READPKT
))
517 setup_dma(buffer
, READ
, 3);
518 cmd_buffer
[0] = cmd_buffer
[1] = cmd_buffer
[2] = cmd_buffer
[4] = 0;
520 if (send_1_5(7, cmd_buffer
, 1) ||
521 !acsi_wait_for_IRQ(TIMEOUTDMA
) ||
524 ret
= calc_received(buffer
);
529 /* sendpkt() sends a packet and returns a value of zero when the packet was sent
533 sendpkt (target
, buffer
, length
)
535 unsigned char *buffer
;
539 unsigned char cmd_buffer
[5];
541 if (send_first(target
, WRITEPKT
))
543 setup_dma(buffer
, WRITE
, 3);
544 cmd_buffer
[0] = cmd_buffer
[1] = cmd_buffer
[4] = 0;
545 cmd_buffer
[2] = length
>> 8;
546 cmd_buffer
[3] = length
& 0xFF;
547 if (send_1_5(7, cmd_buffer
, 1) ||
548 !acsi_wait_for_IRQ(TIMEOUTDMA
) ||
556 /* The following higher level routines work on virtual addresses and convert them to
557 * physical addresses when passed to the lowlevel routines. It's up to the higher level
558 * routines to copy data from Alternate RAM to ST RAM if neccesary!
561 /* Check for a network adaptor of this type, and return '0' if one exists.
566 struct net_device
*dev
;
571 unsigned char station_addr
[6];
572 static unsigned version_printed
= 0;
573 /* avoid "Probing for..." printed 4 times - the driver is supporting only one adapter now! */
574 static int no_more_found
= 0;
581 printk("Probing for PAM's Net/GK Adapter...\n");
583 /* Allocate the DMA buffer here since we need it for probing! */
585 nic_packet
= (struct nic_pkt_s
*)acsi_buffer
;
586 phys_nic_packet
= (unsigned char *)phys_acsi_buffer
;
587 if (pamsnet_debug
> 0) {
588 printk("nic_packet at 0x%p, phys at 0x%p\n",
589 nic_packet
, phys_nic_packet
);
592 stdma_lock(pamsnet_intr
, NULL
);
595 for (i
=0; i
<8; i
++) {
596 /* Do two inquiries to cover cases with strange equipment on previous ID */
597 /* blocking the ACSI bus (like the SLMC804 laser printer controller... */
598 inquiry(i
, phys_nic_packet
);
599 if (!inquiry(i
, phys_nic_packet
)) {
606 printk("ID: %d\n",i
);
608 if (lance_target
>= 0) {
609 if (!(hwaddr
= read_hw_addr(lance_target
, phys_nic_packet
)))
612 memcpy (station_addr
, hwaddr
, ETH_ALEN
);
618 if (lance_target
< 0)
619 printk("No PAM's Net/GK found.\n");
621 if ((dev
== NULL
) || (lance_target
< 0))
623 if (pamsnet_debug
> 0 && version_printed
++ == 0)
626 printk("%s: %s found on target %01d, eth-addr: %02x:%02x:%02x:%02x:%02x:%02x.\n",
627 dev
->name
, "PAM's Net/GK", lance_target
,
628 station_addr
[0], station_addr
[1], station_addr
[2],
629 station_addr
[3], station_addr
[4], station_addr
[5]);
631 /* Initialize the device structure. */
632 if (dev
->priv
== NULL
)
633 dev
->priv
= kmalloc(sizeof(struct net_local
), GFP_KERNEL
);
634 memset(dev
->priv
, 0, sizeof(struct net_local
));
636 dev
->open
= pamsnet_open
;
637 dev
->stop
= pamsnet_close
;
638 dev
->hard_start_xmit
= pamsnet_send_packet
;
639 dev
->get_stats
= net_get_stats
;
641 /* Fill in the fields of the device structure with ethernet-generic
642 * values. This should be in a common file instead of per-driver.
645 for (i
= 0; i
< ETH_ALEN
; i
++) {
647 dev
->broadcast
[i
] = 0xff;
649 dev
->dev_addr
[i
] = station_addr
[i
];
656 /* Open/initialize the board. This is called (in the current kernel)
657 sometime after booting when the 'ifconfig' program is run.
659 This routine should set everything up anew at each open, even
660 registers that "should" only need to be set once at boot, so that
661 there is non-reboot way to recover if something goes wrong.
664 pamsnet_open(struct net_device
*dev
) {
665 struct net_local
*lp
= (struct net_local
*)dev
->priv
;
667 if (pamsnet_debug
> 0)
668 printk("pamsnet_open\n");
669 stdma_lock(pamsnet_intr
, NULL
);
672 /* Reset the hardware here.
677 lp
->open_time
= 0; /*jiffies*/
678 lp
->poll_time
= MAX_POLL_TIME
;
686 pamsnet_timer
.data
= (long)dev
;
687 pamsnet_timer
.expires
= jiffies
+ lp
->poll_time
;
688 add_timer(&pamsnet_timer
);
694 pamsnet_send_packet(struct sk_buff
*skb
, struct net_device
*dev
) {
695 struct net_local
*lp
= (struct net_local
*)dev
->priv
;
698 /* Block a timer-based transmit from overlapping. This could better be
699 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
704 if (stdma_islocked()) {
705 restore_flags(flags
);
706 lp
->stats
.tx_errors
++;
709 int length
= ETH_ZLEN
< skb
->len
? skb
->len
: ETH_ZLEN
;
710 unsigned long buf
= virt_to_phys(skb
->data
);
713 stdma_lock(pamsnet_intr
, NULL
);
716 restore_flags(flags
);
717 if( !STRAM_ADDR(buf
+length
-1) ) {
718 memcpy(nic_packet
->buffer
, skb
->data
, length
);
719 buf
= (unsigned long)phys_nic_packet
;
722 dma_cache_maintenance(buf
, length
, 1);
724 stat
= sendpkt(lance_target
, (unsigned char *)buf
, length
);
728 dev
->trans_start
= jiffies
;
730 lp
->stats
.tx_packets
++;
731 lp
->stats
.tx_bytes
+=length
;
738 /* We have a good packet(s), get it/them out of the buffers.
741 pamsnet_poll_rx(struct net_device
*dev
) {
742 struct net_local
*lp
= (struct net_local
*)dev
->priv
;
750 /* ++roman: Take care at locking the ST-DMA... This must be done with ints
751 * off, since otherwise an int could slip in between the question and the
752 * locking itself, and then we'd go to sleep... And locking itself is
753 * necessary to keep the floppy_change timer from working with ST-DMA
755 if (stdma_islocked()) {
756 restore_flags(flags
);
759 stdma_lock(pamsnet_intr
, NULL
);
761 restore_flags(flags
);
763 boguscount
= testpkt(lance_target
);
764 if( lp
->poll_time
< MAX_POLL_TIME
) lp
->poll_time
++;
766 while(boguscount
--) {
767 pkt_len
= receivepkt(lance_target
, phys_nic_packet
);
769 if( pkt_len
< 60 ) break;
773 dma_cache_maintenance((unsigned long)phys_nic_packet
, pkt_len
, 0);
775 lp
->poll_time
= pamsnet_min_poll_time
; /* fast poll */
776 if( pkt_len
>= 60 && pkt_len
<= 2048 ) {
780 /* Malloc up new buffer.
782 skb
= alloc_skb(pkt_len
, GFP_ATOMIC
);
784 printk("%s: Memory squeeze, dropping packet.\n",
786 lp
->stats
.rx_dropped
++;
792 /* 'skb->data' points to the start of sk_buff data area.
794 memcpy(skb
->data
, nic_packet
->buffer
, pkt_len
);
796 lp
->stats
.rx_packets
++;
797 lp
->stats
.rx_bytes
+=pkt_len
;
801 /* If any worth-while packets have been received, dev_rint()
802 has done a mark_bh(INET_BH) for us and will work on them
803 when we get to the bottom-half routine.
811 /* pamsnet_tick: called by pamsnet_timer. Reads packets from the adapter,
812 * passes them to the higher layers and restarts the timer.
815 pamsnet_tick(unsigned long data
) {
816 struct net_device
*dev
= (struct net_device
*)data
;
817 struct net_local
*lp
= (struct net_local
*)dev
->priv
;
819 if( pamsnet_debug
> 0 && (lp
->open_time
++ & 7) == 8 )
820 printk("pamsnet_tick: %ld\n", lp
->open_time
);
822 pamsnet_poll_rx(dev
);
824 pamsnet_timer
.expires
= jiffies
+ lp
->poll_time
;
825 add_timer(&pamsnet_timer
);
828 /* The inverse routine to pamsnet_open().
831 pamsnet_close(struct net_device
*dev
) {
832 struct net_local
*lp
= (struct net_local
*)dev
->priv
;
834 if (pamsnet_debug
> 0)
835 printk("pamsnet_close, open_time=%ld\n", lp
->open_time
);
836 del_timer(&pamsnet_timer
);
837 stdma_lock(pamsnet_intr
, NULL
);
855 /* Get the current statistics.
856 This may be called with the card open or closed.
858 static struct net_device_stats
*net_get_stats(struct net_device
*dev
)
860 struct net_local
*lp
= (struct net_local
*)dev
->priv
;
867 static char devicename
[9] = { 0, };
868 static struct net_device pam_dev
=
870 devicename
, /* filled in by register_netdev() */
871 0, 0, 0, 0, /* memory */
872 0, 0, /* base, irq */
873 0, 0, 0, NULL
, pamsnet_probe
,
880 if ((err
= register_netdev(&pam_dev
))) {
881 if (err
== -EEXIST
) {
882 printk("PAM's Net/GK: devices already present. Module not loaded.\n");
890 cleanup_module(void) {
891 unregister_netdev(&pam_dev
);
897 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
898 -b m68k-linuxaout -Wall -Wstrict-prototypes -O2
899 -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c atari_pamsnet.c"
901 * kept-new-versions: 5