diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Kconfig | 16 | ||||
-rw-r--r-- | drivers/net/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/Space.c | 8 | ||||
-rw-r--r-- | drivers/net/atari_bionet.c | 675 | ||||
-rw-r--r-- | drivers/net/atari_pamsnet.c | 878 |
5 files changed, 0 insertions, 1579 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 7903f9c7839e..713ab05a87c0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -405,22 +405,6 @@ config ATARILANCE | |||
405 | on the AMD Lance chipset: RieblCard (with or without battery), or | 405 | on the AMD Lance chipset: RieblCard (with or without battery), or |
406 | PAMCard VME (also the version by Rhotron, with different addresses). | 406 | PAMCard VME (also the version by Rhotron, with different addresses). |
407 | 407 | ||
408 | config ATARI_BIONET | ||
409 | tristate "BioNet-100 support" | ||
410 | depends on ATARI && ATARI_ACSI && BROKEN | ||
411 | help | ||
412 | Say Y to include support for BioData's BioNet-100 Ethernet adapter | ||
413 | for the ACSI port. The driver works (has to work...) with a polled | ||
414 | I/O scheme, so it's rather slow :-( | ||
415 | |||
416 | config ATARI_PAMSNET | ||
417 | tristate "PAMsNet support" | ||
418 | depends on ATARI && ATARI_ACSI && BROKEN | ||
419 | help | ||
420 | Say Y to include support for the PAMsNet Ethernet adapter for the | ||
421 | ACSI port ("ACSI node"). The driver works (has to work...) with a | ||
422 | polled I/O scheme, so it's rather slow :-( | ||
423 | |||
424 | config SUN3LANCE | 408 | config SUN3LANCE |
425 | tristate "Sun3/Sun3x on-board LANCE support" | 409 | tristate "Sun3/Sun3x on-board LANCE support" |
426 | depends on SUN3 || SUN3X | 410 | depends on SUN3 || SUN3X |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index b95b1b237a26..eb4167622a6a 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -181,8 +181,6 @@ obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o | |||
181 | obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o | 181 | obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o |
182 | obj-$(CONFIG_DECLANCE) += declance.o | 182 | obj-$(CONFIG_DECLANCE) += declance.o |
183 | obj-$(CONFIG_ATARILANCE) += atarilance.o | 183 | obj-$(CONFIG_ATARILANCE) += atarilance.o |
184 | obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o | ||
185 | obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o | ||
186 | obj-$(CONFIG_A2065) += a2065.o | 184 | obj-$(CONFIG_A2065) += a2065.o |
187 | obj-$(CONFIG_HYDRA) += hydra.o | 185 | obj-$(CONFIG_HYDRA) += hydra.o |
188 | obj-$(CONFIG_ARIADNE) += ariadne.o | 186 | obj-$(CONFIG_ARIADNE) += ariadne.o |
diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 1c3e293fbaf7..3b79c6cf21a3 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c | |||
@@ -75,8 +75,6 @@ extern struct net_device *atarilance_probe(int unit); | |||
75 | extern struct net_device *sun3lance_probe(int unit); | 75 | extern struct net_device *sun3lance_probe(int unit); |
76 | extern struct net_device *sun3_82586_probe(int unit); | 76 | extern struct net_device *sun3_82586_probe(int unit); |
77 | extern struct net_device *apne_probe(int unit); | 77 | extern struct net_device *apne_probe(int unit); |
78 | extern struct net_device *bionet_probe(int unit); | ||
79 | extern struct net_device *pamsnet_probe(int unit); | ||
80 | extern struct net_device *cs89x0_probe(int unit); | 78 | extern struct net_device *cs89x0_probe(int unit); |
81 | extern struct net_device *hplance_probe(int unit); | 79 | extern struct net_device *hplance_probe(int unit); |
82 | extern struct net_device *bagetlance_probe(int unit); | 80 | extern struct net_device *bagetlance_probe(int unit); |
@@ -264,12 +262,6 @@ static struct devprobe2 m68k_probes[] __initdata = { | |||
264 | #ifdef CONFIG_APNE /* A1200 PCMCIA NE2000 */ | 262 | #ifdef CONFIG_APNE /* A1200 PCMCIA NE2000 */ |
265 | {apne_probe, 0}, | 263 | {apne_probe, 0}, |
266 | #endif | 264 | #endif |
267 | #ifdef CONFIG_ATARI_BIONET /* Atari Bionet Ethernet board */ | ||
268 | {bionet_probe, 0}, | ||
269 | #endif | ||
270 | #ifdef CONFIG_ATARI_PAMSNET /* Atari PAMsNet Ethernet board */ | ||
271 | {pamsnet_probe, 0}, | ||
272 | #endif | ||
273 | #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ | 265 | #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ |
274 | {mvme147lance_probe, 0}, | 266 | {mvme147lance_probe, 0}, |
275 | #endif | 267 | #endif |
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c deleted file mode 100644 index 3d87bd2b4194..000000000000 --- a/drivers/net/atari_bionet.c +++ /dev/null | |||
@@ -1,675 +0,0 @@ | |||
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; | ||
126 | module_param(bionet_debug, int, 0); | ||
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 | |||
158 | static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0); | ||
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 | ||
223 | bionet_intr(int irq, void *data) { | ||
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 | skb_copy_from_linear_data(skb, nic_packet->buffer, | ||
457 | length); | ||
458 | buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer; | ||
459 | } | ||
460 | |||
461 | if (bionet_debug >1) { | ||
462 | u_char *data = nic_packet->buffer, *p; | ||
463 | int i; | ||
464 | |||
465 | printk( "%s: TX pkt type 0x%4x from ", dev->name, | ||
466 | ((u_short *)data)[6]); | ||
467 | |||
468 | for( p = &data[6], i = 0; i < 6; i++ ) | ||
469 | printk("%02x%s", *p++,i != 5 ? ":" : "" ); | ||
470 | printk(" to "); | ||
471 | |||
472 | for( p = data, i = 0; i < 6; i++ ) | ||
473 | printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); | ||
474 | |||
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], | ||
481 | length ); | ||
482 | } | ||
483 | dma_cache_maintenance(buf, length, 1); | ||
484 | |||
485 | stat = hardware_send_packet(buf, length); | ||
486 | ENABLE_IRQ(); | ||
487 | stdma_release(); | ||
488 | |||
489 | dev->trans_start = jiffies; | ||
490 | dev->tbusy = 0; | ||
491 | lp->stats.tx_packets++; | ||
492 | lp->stats.tx_bytes+=length; | ||
493 | } | ||
494 | dev_kfree_skb(skb); | ||
495 | |||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | /* We have a good packet(s), get it/them out of the buffers. | ||
500 | */ | ||
501 | static void | ||
502 | bionet_poll_rx(struct net_device *dev) { | ||
503 | struct net_local *lp = netdev_priv(dev); | ||
504 | int boguscount = 10; | ||
505 | int pkt_len, status; | ||
506 | unsigned long flags; | ||
507 | |||
508 | local_irq_save(flags); | ||
509 | /* ++roman: Take care at locking the ST-DMA... This must be done with ints | ||
510 | * off, since otherwise an int could slip in between the question and the | ||
511 | * locking itself, and then we'd go to sleep... And locking itself is | ||
512 | * necessary to keep the floppy_change timer from working with ST-DMA | ||
513 | * registers. */ | ||
514 | if (stdma_islocked()) { | ||
515 | local_irq_restore(flags); | ||
516 | return; | ||
517 | } | ||
518 | stdma_lock(bionet_intr, NULL); | ||
519 | DISABLE_IRQ(); | ||
520 | local_irq_restore(flags); | ||
521 | |||
522 | if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; | ||
523 | |||
524 | while(boguscount--) { | ||
525 | status = get_frame((unsigned long)phys_nic_packet, 0); | ||
526 | |||
527 | if( status == 0 ) break; | ||
528 | |||
529 | /* Good packet... */ | ||
530 | |||
531 | dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0); | ||
532 | |||
533 | pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo; | ||
534 | |||
535 | lp->poll_time = bionet_min_poll_time; /* fast poll */ | ||
536 | if( pkt_len >= 60 && pkt_len <= 1520 ) { | ||
537 | /* ^^^^ war 1514 KHL */ | ||
538 | /* Malloc up new buffer. | ||
539 | */ | ||
540 | struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 ); | ||
541 | if (skb == NULL) { | ||
542 | printk("%s: Memory squeeze, dropping packet.\n", | ||
543 | dev->name); | ||
544 | lp->stats.rx_dropped++; | ||
545 | break; | ||
546 | } | ||
547 | |||
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 | skb_copy_to_linear_data(skb, nic_packet->buffer, | ||
554 | pkt_len); | ||
555 | skb->protocol = eth_type_trans( skb, dev ); | ||
556 | netif_rx(skb); | ||
557 | dev->last_rx = jiffies; | ||
558 | lp->stats.rx_packets++; | ||
559 | lp->stats.rx_bytes+=pkt_len; | ||
560 | |||
561 | /* If any worth-while packets have been received, dev_rint() | ||
562 | has done a mark_bh(INET_BH) for us and will work on them | ||
563 | when we get to the bottom-half routine. | ||
564 | */ | ||
565 | |||
566 | if (bionet_debug >1) { | ||
567 | u_char *data = nic_packet->buffer, *p; | ||
568 | int i; | ||
569 | |||
570 | printk( "%s: RX pkt type 0x%4x from ", dev->name, | ||
571 | ((u_short *)data)[6]); | ||
572 | |||
573 | |||
574 | for( p = &data[6], i = 0; i < 6; i++ ) | ||
575 | printk("%02x%s", *p++,i != 5 ? ":" : "" ); | ||
576 | printk(" to "); | ||
577 | for( p = data, i = 0; i < 6; i++ ) | ||
578 | printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); | ||
579 | |||
580 | printk( "%s: ", dev->name ); | ||
581 | printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" | ||
582 | " %02x%02x%02x%02x len %d\n", | ||
583 | data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], | ||
584 | data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], | ||
585 | data[28], data[29], data[30], data[31], data[32], data[33], | ||
586 | pkt_len ); | ||
587 | } | ||
588 | } | ||
589 | else { | ||
590 | printk(" Packet has wrong length: %04d bytes\n", pkt_len); | ||
591 | lp->stats.rx_errors++; | ||
592 | } | ||
593 | } | ||
594 | stdma_release(); | ||
595 | ENABLE_IRQ(); | ||
596 | return; | ||
597 | } | ||
598 | |||
599 | /* bionet_tick: called by bionet_timer. Reads packets from the adapter, | ||
600 | * passes them to the higher layers and restarts the timer. | ||
601 | */ | ||
602 | static void | ||
603 | bionet_tick(unsigned long data) { | ||
604 | struct net_device *dev = (struct net_device *)data; | ||
605 | struct net_local *lp = netdev_priv(dev); | ||
606 | |||
607 | if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 ) | ||
608 | printk("bionet_tick: %ld\n", lp->open_time); | ||
609 | |||
610 | if( !stdma_islocked() ) bionet_poll_rx(dev); | ||
611 | |||
612 | bionet_timer.expires = jiffies + lp->poll_time; | ||
613 | add_timer(&bionet_timer); | ||
614 | } | ||
615 | |||
616 | /* The inverse routine to bionet_open(). | ||
617 | */ | ||
618 | static int | ||
619 | bionet_close(struct net_device *dev) { | ||
620 | struct net_local *lp = netdev_priv(dev); | ||
621 | |||
622 | if (bionet_debug > 0) | ||
623 | printk("bionet_close, open_time=%ld\n", lp->open_time); | ||
624 | del_timer(&bionet_timer); | ||
625 | stdma_lock(bionet_intr, NULL); | ||
626 | |||
627 | set_status(0); | ||
628 | lp->open_time = 0; | ||
629 | |||
630 | dev->tbusy = 1; | ||
631 | dev->start = 0; | ||
632 | |||
633 | stdma_release(); | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | /* Get the current statistics. | ||
638 | This may be called with the card open or closed. | ||
639 | */ | ||
640 | static struct net_device_stats *net_get_stats(struct net_device *dev) | ||
641 | { | ||
642 | struct net_local *lp = netdev_priv(dev); | ||
643 | return &lp->stats; | ||
644 | } | ||
645 | |||
646 | |||
647 | #ifdef MODULE | ||
648 | |||
649 | static struct net_device *bio_dev; | ||
650 | |||
651 | int init_module(void) | ||
652 | { | ||
653 | bio_dev = bionet_probe(-1); | ||
654 | if (IS_ERR(bio_dev)) | ||
655 | return PTR_ERR(bio_dev); | ||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | void cleanup_module(void) | ||
660 | { | ||
661 | unregister_netdev(bio_dev); | ||
662 | free_netdev(bio_dev); | ||
663 | } | ||
664 | |||
665 | #endif /* MODULE */ | ||
666 | |||
667 | /* Local variables: | ||
668 | * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include | ||
669 | -b m68k-linuxaout -Wall -Wstrict-prototypes -O2 | ||
670 | -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c" | ||
671 | * version-control: t | ||
672 | * kept-new-versions: 5 | ||
673 | * tab-width: 8 | ||
674 | * End: | ||
675 | */ | ||
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c deleted file mode 100644 index f7356374a2e7..000000000000 --- a/drivers/net/atari_pamsnet.c +++ /dev/null | |||
@@ -1,878 +0,0 @@ | |||
1 | /* atari_pamsnet.c PAMsNet device driver for linux68k. | ||
2 | * | ||
3 | * Version: @(#)PAMsNet.c 0.2ß 03/31/96 | ||
4 | * | ||
5 | * Author: Torsten Lang <Torsten.Lang@ap.physik.uni-giessen.de> | ||
6 | * <Torsten.Lang@jung.de> | ||
7 | * | ||
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> | ||
12 | * | ||
13 | * Little adaptions for integration into pl7 by Roman Hodek | ||
14 | * | ||
15 | What is it ? | ||
16 | ------------ | ||
17 | This driver controls the PAMsNet LAN-Adapter which connects | ||
18 | an ATARI ST/TT via the ACSI-port to an Ethernet-based network. | ||
19 | |||
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'. | ||
24 | |||
25 | 'pamsnet_debug' | ||
26 | controls the amount of diagnostic messages: | ||
27 | 0 : no messages | ||
28 | >0 : see code for meaning of printed messages | ||
29 | |||
30 | 'pamsnet_min_poll_time' (always >=1) | ||
31 | gives the time (in jiffies) between polls. Low values | ||
32 | increase the system load (beware!) | ||
33 | |||
34 | When loaded, a net device with the name 'eth?' becomes available, | ||
35 | which can be controlled with the usual 'ifconfig' command. | ||
36 | |||
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'. | ||
42 | |||
43 | Theory of Operation | ||
44 | ------------------- | ||
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. | ||
52 | |||
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. | ||
59 | |||
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. | ||
66 | |||
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 | ||
72 | machine. | ||
73 | */ | ||
74 | |||
75 | #define MAX_POLL_TIME 10 | ||
76 | |||
77 | static char *version = | ||
78 | "pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n"; | ||
79 | |||
80 | #include <linux/module.h> | ||
81 | |||
82 | #include <linux/kernel.h> | ||
83 | #include <linux/jiffies.h> | ||
84 | #include <linux/types.h> | ||
85 | #include <linux/fcntl.h> | ||
86 | #include <linux/interrupt.h> | ||
87 | #include <linux/ioport.h> | ||
88 | #include <linux/in.h> | ||
89 | #include <linux/slab.h> | ||
90 | #include <linux/string.h> | ||
91 | #include <linux/bitops.h> | ||
92 | #include <asm/system.h> | ||
93 | #include <asm/pgtable.h> | ||
94 | #include <asm/io.h> | ||
95 | #include <asm/dma.h> | ||
96 | #include <linux/errno.h> | ||
97 | #include <asm/atarihw.h> | ||
98 | #include <asm/atariints.h> | ||
99 | #include <asm/atari_stdma.h> | ||
100 | #include <asm/atari_acsi.h> | ||
101 | |||
102 | #include <linux/delay.h> | ||
103 | #include <linux/timer.h> | ||
104 | #include <linux/init.h> | ||
105 | |||
106 | #include <linux/netdevice.h> | ||
107 | #include <linux/etherdevice.h> | ||
108 | #include <linux/skbuff.h> | ||
109 | |||
110 | #undef READ | ||
111 | #undef WRITE | ||
112 | |||
113 | /* use 0 for production, 1 for verification, >2 for debug | ||
114 | */ | ||
115 | #ifndef NET_DEBUG | ||
116 | #define NET_DEBUG 0 | ||
117 | #endif | ||
118 | /* | ||
119 | * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod' | ||
120 | */ | ||
121 | unsigned int pamsnet_debug = NET_DEBUG; | ||
122 | module_param(pamsnet_debug, int, 0); | ||
123 | MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)"); | ||
124 | MODULE_LICENSE("GPL"); | ||
125 | |||
126 | static unsigned int pamsnet_min_poll_time = 2; | ||
127 | |||
128 | |||
129 | /* Information that need to be kept for each board. | ||
130 | */ | ||
131 | struct net_local { | ||
132 | struct net_device_stats stats; | ||
133 | long open_time; /* for debugging */ | ||
134 | int poll_time; /* polling time varies with net load */ | ||
135 | }; | ||
136 | |||
137 | static struct nic_pkt_s { /* packet format */ | ||
138 | unsigned char buffer[2048]; | ||
139 | } *nic_packet = 0; | ||
140 | unsigned char *phys_nic_packet; | ||
141 | |||
142 | typedef unsigned char HADDR[6]; /* 6-byte hardware address of lance */ | ||
143 | |||
144 | /* Index to functions, as function prototypes. | ||
145 | */ | ||
146 | static void start (int target); | ||
147 | static int stop (int target); | ||
148 | static int testpkt (int target); | ||
149 | static int sendpkt (int target, unsigned char *buffer, int length); | ||
150 | static int receivepkt (int target, unsigned char *buffer); | ||
151 | static int inquiry (int target, unsigned char *buffer); | ||
152 | static HADDR *read_hw_addr(int target, unsigned char *buffer); | ||
153 | static void setup_dma (void *address, unsigned rw_flag, int num_blocks); | ||
154 | static int send_first (int target, unsigned char byte); | ||
155 | static int send_1_5 (int lun, unsigned char *command, int dma); | ||
156 | static int get_status (void); | ||
157 | static int calc_received (void *start_address); | ||
158 | |||
159 | static int pamsnet_open(struct net_device *dev); | ||
160 | static int pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev); | ||
161 | static void pamsnet_poll_rx(struct net_device *); | ||
162 | static int pamsnet_close(struct net_device *dev); | ||
163 | static struct net_device_stats *net_get_stats(struct net_device *dev); | ||
164 | static void pamsnet_tick(unsigned long); | ||
165 | |||
166 | static irqreturn_t pamsnet_intr(int irq, void *data); | ||
167 | |||
168 | static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0); | ||
169 | |||
170 | #define STRAM_ADDR(a) (((a) & 0xff000000) == 0) | ||
171 | |||
172 | typedef struct | ||
173 | { | ||
174 | unsigned char reserved1[0x38]; | ||
175 | HADDR hwaddr; | ||
176 | unsigned char reserved2[0x1c2]; | ||
177 | } DMAHWADDR; | ||
178 | |||
179 | /* | ||
180 | * Definitions of commands understood by the PAMs DMA adaptor. | ||
181 | * | ||
182 | * In general the DMA adaptor uses LUN 0, 5, 6 and 7 on one ID changeable | ||
183 | * by the PAM's Net software. | ||
184 | * | ||
185 | * LUN 0 works as a harddisk. You can boot the PAM's Net driver there. | ||
186 | * LUN 5 works as a harddisk and lets you access the RAM and some I/O HW | ||
187 | * area. In sector 0, bytes 0x38-0x3d you find the ethernet HW address | ||
188 | * of the adaptor. | ||
189 | * LUN 6 works as a harddisk and lets you access the firmware ROM. | ||
190 | * LUN 7 lets you send and receive packets. | ||
191 | * | ||
192 | * Some commands like the INQUIRY command work identical on all used LUNs. | ||
193 | * | ||
194 | * UNKNOWN1 seems to read some data. | ||
195 | * Command length is 6 bytes. | ||
196 | * UNKNOWN2 seems to read some data (command byte 1 must be !=0). The | ||
197 | * following bytes seem to be something like an allocation length. | ||
198 | * Command length is 6 bytes. | ||
199 | * READPKT reads a packet received by the DMA adaptor. | ||
200 | * Command length is 6 bytes. | ||
201 | * WRITEPKT sends a packet transferred by the following DMA phase. The length | ||
202 | * of the packet is transferred in command bytes 3 and 4. | ||
203 | * The adaptor automatically replaces the src hw address in an ethernet | ||
204 | * packet by its own hw address. | ||
205 | * Command length is 6 bytes. | ||
206 | * INQUIRY has the same function as the INQUIRY command supported by harddisks | ||
207 | * and other SCSI devices. It lets you detect which device you found | ||
208 | * at a given address. | ||
209 | * Command length is 6 bytes. | ||
210 | * START initializes the DMA adaptor. After this command it is able to send | ||
211 | * and receive packets. There is no status byte returned! | ||
212 | * Command length is 1 byte. | ||
213 | * NUMPKTS gives back the number of received packets waiting in the queue in | ||
214 | * the status byte. | ||
215 | * Command length is 1 byte. | ||
216 | * UNKNOWN3 | ||
217 | * UNKNOWN4 Function of these three commands is unknown. | ||
218 | * UNKNOWN5 The command length of these three commands is 1 byte. | ||
219 | * DESELECT immediately deselects the DMA adaptor. May important with interrupt | ||
220 | * driven operation. | ||
221 | * Command length is 1 byte. | ||
222 | * STOP resets the DMA adaptor. After this command packets can no longer | ||
223 | * be received or transferred. | ||
224 | * Command length is 6 byte. | ||
225 | */ | ||
226 | |||
227 | enum {UNKNOWN1=3, READPKT=8, UNKNOWN2, WRITEPKT=10, INQUIRY=18, START, | ||
228 | NUMPKTS=22, UNKNOWN3, UNKNOWN4, UNKNOWN5, DESELECT, STOP}; | ||
229 | |||
230 | #define READSECTOR READPKT | ||
231 | #define WRITESECTOR WRITEPKT | ||
232 | |||
233 | u_char *inquire8="MV PAM's NET/GK"; | ||
234 | |||
235 | #define DMALOW dma_wd.dma_lo | ||
236 | #define DMAMID dma_wd.dma_md | ||
237 | #define DMAHIGH dma_wd.dma_hi | ||
238 | #define DACCESS dma_wd.fdc_acces_seccount | ||
239 | |||
240 | #define MFP_GPIP mfp.par_dt_reg | ||
241 | |||
242 | /* Some useful functions */ | ||
243 | |||
244 | #define INT (!(MFP_GPIP & 0x20)) | ||
245 | #define DELAY ({MFP_GPIP; MFP_GPIP; MFP_GPIP;}) | ||
246 | #define WRITEMODE(value) \ | ||
247 | ({ u_short dummy = value; \ | ||
248 | __asm__ volatile("movew %0, 0xFFFF8606" : : "d"(dummy)); \ | ||
249 | DELAY; \ | ||
250 | }) | ||
251 | #define WRITEBOTH(value1, value2) \ | ||
252 | ({ u_long dummy = (u_long)(value1)<<16 | (u_short)(value2); \ | ||
253 | __asm__ volatile("movel %0, 0xFFFF8604" : : "d"(dummy)); \ | ||
254 | DELAY; \ | ||
255 | }) | ||
256 | |||
257 | /* Definitions for DMODE */ | ||
258 | |||
259 | #define READ 0x000 | ||
260 | #define WRITE 0x100 | ||
261 | |||
262 | #define DMA_FDC 0x080 | ||
263 | #define DMA_ACSI 0x000 | ||
264 | |||
265 | #define DMA_DISABLE 0x040 | ||
266 | |||
267 | #define SEC_COUNT 0x010 | ||
268 | #define DMA_WINDOW 0x000 | ||
269 | |||
270 | #define REG_ACSI 0x008 | ||
271 | #define REG_FDC 0x000 | ||
272 | |||
273 | #define A1 0x002 | ||
274 | |||
275 | /* Timeout constants */ | ||
276 | |||
277 | #define TIMEOUTCMD HZ/2 /* ca. 500ms */ | ||
278 | #define TIMEOUTDMA HZ /* ca. 1s */ | ||
279 | #define COMMAND_DELAY 500 /* ca. 0.5ms */ | ||
280 | |||
281 | unsigned rw; | ||
282 | int lance_target = -1; | ||
283 | int if_up = 0; | ||
284 | |||
285 | /* The following routines access the ethernet board connected to the | ||
286 | * ACSI port via the st_dma chip. | ||
287 | */ | ||
288 | |||
289 | /* The following lowlevel routines work on physical addresses only and assume | ||
290 | * that eventually needed buffers are | ||
291 | * - completely located in ST RAM | ||
292 | * - are contigous in the physical address space | ||
293 | */ | ||
294 | |||
295 | /* Setup the DMA counter */ | ||
296 | |||
297 | static void | ||
298 | setup_dma (void *address, unsigned rw_flag, int num_blocks) | ||
299 | { | ||
300 | WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI | | ||
301 | A1); | ||
302 | WRITEMODE((unsigned)(rw_flag ^ WRITE) | DMA_FDC | SEC_COUNT | REG_ACSI | | ||
303 | A1); | ||
304 | WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI | | ||
305 | A1); | ||
306 | DMALOW = (unsigned char)((unsigned long)address & 0xFF); | ||
307 | DMAMID = (unsigned char)(((unsigned long)address >> 8) & 0xFF); | ||
308 | DMAHIGH = (unsigned char)(((unsigned long)address >> 16) & 0xFF); | ||
309 | WRITEBOTH((unsigned)num_blocks & 0xFF, | ||
310 | rw_flag | DMA_FDC | DMA_WINDOW | REG_ACSI | A1); | ||
311 | rw = rw_flag; | ||
312 | } | ||
313 | |||
314 | /* Send the first byte of an command block */ | ||
315 | |||
316 | static int | ||
317 | send_first (int target, unsigned char byte) | ||
318 | { | ||
319 | rw = READ; | ||
320 | acsi_delay_end(COMMAND_DELAY); | ||
321 | /* | ||
322 | * wake up ACSI | ||
323 | */ | ||
324 | WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI); | ||
325 | /* | ||
326 | * write command byte | ||
327 | */ | ||
328 | WRITEBOTH((target << 5) | (byte & 0x1F), DMA_FDC | | ||
329 | DMA_WINDOW | REG_ACSI | A1); | ||
330 | return (!acsi_wait_for_IRQ(TIMEOUTCMD)); | ||
331 | } | ||
332 | |||
333 | /* Send the rest of an command block */ | ||
334 | |||
335 | static int | ||
336 | send_1_5 (int lun, unsigned char *command, int dma) | ||
337 | { | ||
338 | int i, j; | ||
339 | |||
340 | for (i=0; i<5; i++) { | ||
341 | WRITEBOTH((!i ? (((lun & 0x7) << 5) | (command[i] & 0x1F)) | ||
342 | : command[i]), | ||
343 | rw | REG_ACSI | DMA_WINDOW | | ||
344 | ((i < 4) ? DMA_FDC | ||
345 | : (dma ? DMA_ACSI | ||
346 | : DMA_FDC)) | A1); | ||
347 | if (i < 4 && (j = !acsi_wait_for_IRQ(TIMEOUTCMD))) | ||
348 | return (j); | ||
349 | } | ||
350 | return (0); | ||
351 | } | ||
352 | |||
353 | /* Read a status byte */ | ||
354 | |||
355 | static int | ||
356 | get_status (void) | ||
357 | { | ||
358 | WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI | A1); | ||
359 | acsi_delay_start(); | ||
360 | return ((int)(DACCESS & 0xFF)); | ||
361 | } | ||
362 | |||
363 | /* Calculate the number of received bytes */ | ||
364 | |||
365 | static int | ||
366 | calc_received (void *start_address) | ||
367 | { | ||
368 | return (int)( | ||
369 | (((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW) | ||
370 | - (unsigned long)start_address); | ||
371 | } | ||
372 | |||
373 | /* The following midlevel routines still work on physical addresses ... */ | ||
374 | |||
375 | /* start() starts the PAM's DMA adaptor */ | ||
376 | |||
377 | static void | ||
378 | start (int target) | ||
379 | { | ||
380 | send_first(target, START); | ||
381 | } | ||
382 | |||
383 | /* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */ | ||
384 | |||
385 | static int | ||
386 | stop (int target) | ||
387 | { | ||
388 | int ret = -1; | ||
389 | unsigned char cmd_buffer[5]; | ||
390 | |||
391 | if (send_first(target, STOP)) | ||
392 | goto bad; | ||
393 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = | ||
394 | cmd_buffer[3] = cmd_buffer[4] = 0; | ||
395 | if (send_1_5(7, cmd_buffer, 0) || | ||
396 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
397 | get_status()) | ||
398 | goto bad; | ||
399 | ret = 0; | ||
400 | bad: | ||
401 | return (ret); | ||
402 | } | ||
403 | |||
404 | /* testpkt() returns the number of received packets waiting in the queue */ | ||
405 | |||
406 | static int | ||
407 | testpkt(int target) | ||
408 | { | ||
409 | int ret = -1; | ||
410 | |||
411 | if (send_first(target, NUMPKTS)) | ||
412 | goto bad; | ||
413 | ret = get_status(); | ||
414 | bad: | ||
415 | return (ret); | ||
416 | } | ||
417 | |||
418 | /* inquiry() returns 0 when PAM's DMA found, -1 when timeout, -2 otherwise */ | ||
419 | /* Please note: The buffer is for internal use only but must be defined! */ | ||
420 | |||
421 | static int | ||
422 | inquiry (int target, unsigned char *buffer) | ||
423 | { | ||
424 | int ret = -1; | ||
425 | unsigned char *vbuffer = phys_to_virt((unsigned long)buffer); | ||
426 | unsigned char cmd_buffer[5]; | ||
427 | |||
428 | if (send_first(target, INQUIRY)) | ||
429 | goto bad; | ||
430 | setup_dma(buffer, READ, 1); | ||
431 | vbuffer[8] = vbuffer[27] = 0; /* Avoid confusion with previous read data */ | ||
432 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; | ||
433 | cmd_buffer[3] = 48; | ||
434 | if (send_1_5(5, cmd_buffer, 1) || | ||
435 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
436 | get_status() || | ||
437 | (calc_received(buffer) < 32)) | ||
438 | goto bad; | ||
439 | dma_cache_maintenance((unsigned long)(buffer+8), 20, 0); | ||
440 | if (memcmp(inquire8, vbuffer+8, 20)) | ||
441 | goto bad; | ||
442 | ret = 0; | ||
443 | bad: | ||
444 | if (!!NET_DEBUG) { | ||
445 | vbuffer[8+20]=0; | ||
446 | printk("inquiry of target %d: %s\n", target, vbuffer+8); | ||
447 | } | ||
448 | return (ret); | ||
449 | } | ||
450 | |||
451 | /* | ||
452 | * read_hw_addr() reads the sector containing the hwaddr and returns | ||
453 | * a pointer to it (virtual address!) or 0 in case of an error | ||
454 | */ | ||
455 | |||
456 | static HADDR | ||
457 | *read_hw_addr(int target, unsigned char *buffer) | ||
458 | { | ||
459 | HADDR *ret = 0; | ||
460 | unsigned char cmd_buffer[5]; | ||
461 | |||
462 | if (send_first(target, READSECTOR)) | ||
463 | goto bad; | ||
464 | setup_dma(buffer, READ, 1); | ||
465 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; | ||
466 | cmd_buffer[3] = 1; | ||
467 | if (send_1_5(5, cmd_buffer, 1) || | ||
468 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
469 | get_status()) | ||
470 | goto bad; | ||
471 | ret = phys_to_virt((unsigned long)&(((DMAHWADDR *)buffer)->hwaddr)); | ||
472 | dma_cache_maintenance((unsigned long)buffer, 512, 0); | ||
473 | bad: | ||
474 | return (ret); | ||
475 | } | ||
476 | |||
477 | static irqreturn_t | ||
478 | pamsnet_intr(int irq, void *data) | ||
479 | { | ||
480 | return IRQ_HANDLED; | ||
481 | } | ||
482 | |||
483 | /* receivepkt() loads a packet to a given buffer and returns its length */ | ||
484 | |||
485 | static int | ||
486 | receivepkt (int target, unsigned char *buffer) | ||
487 | { | ||
488 | int ret = -1; | ||
489 | unsigned char cmd_buffer[5]; | ||
490 | |||
491 | if (send_first(target, READPKT)) | ||
492 | goto bad; | ||
493 | setup_dma(buffer, READ, 3); | ||
494 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; | ||
495 | cmd_buffer[3] = 3; | ||
496 | if (send_1_5(7, cmd_buffer, 1) || | ||
497 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
498 | get_status()) | ||
499 | goto bad; | ||
500 | ret = calc_received(buffer); | ||
501 | bad: | ||
502 | return (ret); | ||
503 | } | ||
504 | |||
505 | /* sendpkt() sends a packet and returns a value of zero when the packet was sent | ||
506 | successfully */ | ||
507 | |||
508 | static int | ||
509 | sendpkt (int target, unsigned char *buffer, int length) | ||
510 | { | ||
511 | int ret = -1; | ||
512 | unsigned char cmd_buffer[5]; | ||
513 | |||
514 | if (send_first(target, WRITEPKT)) | ||
515 | goto bad; | ||
516 | setup_dma(buffer, WRITE, 3); | ||
517 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[4] = 0; | ||
518 | cmd_buffer[2] = length >> 8; | ||
519 | cmd_buffer[3] = length & 0xFF; | ||
520 | if (send_1_5(7, cmd_buffer, 1) || | ||
521 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
522 | get_status()) | ||
523 | goto bad; | ||
524 | ret = 0; | ||
525 | bad: | ||
526 | return (ret); | ||
527 | } | ||
528 | |||
529 | /* The following higher level routines work on virtual addresses and convert them to | ||
530 | * physical addresses when passed to the lowlevel routines. It's up to the higher level | ||
531 | * routines to copy data from Alternate RAM to ST RAM if neccesary! | ||
532 | */ | ||
533 | |||
534 | /* Check for a network adaptor of this type, and return '0' if one exists. | ||
535 | */ | ||
536 | |||
537 | struct net_device * __init pamsnet_probe (int unit) | ||
538 | { | ||
539 | struct net_device *dev; | ||
540 | int i; | ||
541 | HADDR *hwaddr; | ||
542 | int err; | ||
543 | |||
544 | unsigned char station_addr[6]; | ||
545 | static unsigned version_printed; | ||
546 | /* avoid "Probing for..." printed 4 times - the driver is supporting only one adapter now! */ | ||
547 | static int no_more_found; | ||
548 | |||
549 | if (no_more_found) | ||
550 | return ERR_PTR(-ENODEV); | ||
551 | no_more_found = 1; | ||
552 | |||
553 | dev = alloc_etherdev(sizeof(struct net_local)); | ||
554 | if (!dev) | ||
555 | return ERR_PTR(-ENOMEM); | ||
556 | if (unit >= 0) { | ||
557 | sprintf(dev->name, "eth%d", unit); | ||
558 | netdev_boot_setup_check(dev); | ||
559 | } | ||
560 | SET_MODULE_OWNER(dev); | ||
561 | |||
562 | printk("Probing for PAM's Net/GK Adapter...\n"); | ||
563 | |||
564 | /* Allocate the DMA buffer here since we need it for probing! */ | ||
565 | |||
566 | nic_packet = (struct nic_pkt_s *)acsi_buffer; | ||
567 | phys_nic_packet = (unsigned char *)phys_acsi_buffer; | ||
568 | if (pamsnet_debug > 0) { | ||
569 | printk("nic_packet at 0x%p, phys at 0x%p\n", | ||
570 | nic_packet, phys_nic_packet ); | ||
571 | } | ||
572 | |||
573 | stdma_lock(pamsnet_intr, NULL); | ||
574 | DISABLE_IRQ(); | ||
575 | |||
576 | for (i=0; i<8; i++) { | ||
577 | /* Do two inquiries to cover cases with strange equipment on previous ID */ | ||
578 | /* blocking the ACSI bus (like the SLMC804 laser printer controller... */ | ||
579 | inquiry(i, phys_nic_packet); | ||
580 | if (!inquiry(i, phys_nic_packet)) { | ||
581 | lance_target = i; | ||
582 | break; | ||
583 | } | ||
584 | } | ||
585 | |||
586 | if (!!NET_DEBUG) | ||
587 | printk("ID: %d\n",i); | ||
588 | |||
589 | if (lance_target >= 0) { | ||
590 | if (!(hwaddr = read_hw_addr(lance_target, phys_nic_packet))) | ||
591 | lance_target = -1; | ||
592 | else | ||
593 | memcpy (station_addr, hwaddr, ETH_ALEN); | ||
594 | } | ||
595 | |||
596 | ENABLE_IRQ(); | ||
597 | stdma_release(); | ||
598 | |||
599 | if (lance_target < 0) { | ||
600 | printk("No PAM's Net/GK found.\n"); | ||
601 | free_netdev(dev); | ||
602 | return ERR_PTR(-ENODEV); | ||
603 | } | ||
604 | |||
605 | if (pamsnet_debug > 0 && version_printed++ == 0) | ||
606 | printk(version); | ||
607 | |||
608 | printk("%s: %s found on target %01d, eth-addr: %02x:%02x:%02x:%02x:%02x:%02x.\n", | ||
609 | dev->name, "PAM's Net/GK", lance_target, | ||
610 | station_addr[0], station_addr[1], station_addr[2], | ||
611 | station_addr[3], station_addr[4], station_addr[5]); | ||
612 | |||
613 | /* Initialize the device structure. */ | ||
614 | dev->open = pamsnet_open; | ||
615 | dev->stop = pamsnet_close; | ||
616 | dev->hard_start_xmit = pamsnet_send_packet; | ||
617 | dev->get_stats = net_get_stats; | ||
618 | |||
619 | /* Fill in the fields of the device structure with ethernet-generic | ||
620 | * values. This should be in a common file instead of per-driver. | ||
621 | */ | ||
622 | |||
623 | for (i = 0; i < ETH_ALEN; i++) { | ||
624 | #if 0 | ||
625 | dev->broadcast[i] = 0xff; | ||
626 | #endif | ||
627 | dev->dev_addr[i] = station_addr[i]; | ||
628 | } | ||
629 | err = register_netdev(dev); | ||
630 | if (!err) | ||
631 | return dev; | ||
632 | |||
633 | free_netdev(dev); | ||
634 | return ERR_PTR(err); | ||
635 | } | ||
636 | |||
637 | /* Open/initialize the board. This is called (in the current kernel) | ||
638 | sometime after booting when the 'ifconfig' program is run. | ||
639 | |||
640 | This routine should set everything up anew at each open, even | ||
641 | registers that "should" only need to be set once at boot, so that | ||
642 | there is non-reboot way to recover if something goes wrong. | ||
643 | */ | ||
644 | static int | ||
645 | pamsnet_open(struct net_device *dev) | ||
646 | { | ||
647 | struct net_local *lp = netdev_priv(dev); | ||
648 | |||
649 | if (pamsnet_debug > 0) | ||
650 | printk("pamsnet_open\n"); | ||
651 | stdma_lock(pamsnet_intr, NULL); | ||
652 | DISABLE_IRQ(); | ||
653 | |||
654 | /* Reset the hardware here. | ||
655 | */ | ||
656 | if (!if_up) | ||
657 | start(lance_target); | ||
658 | if_up = 1; | ||
659 | lp->open_time = 0; /*jiffies*/ | ||
660 | lp->poll_time = MAX_POLL_TIME; | ||
661 | |||
662 | dev->tbusy = 0; | ||
663 | dev->interrupt = 0; | ||
664 | dev->start = 1; | ||
665 | |||
666 | ENABLE_IRQ(); | ||
667 | stdma_release(); | ||
668 | pamsnet_timer.data = (long)dev; | ||
669 | pamsnet_timer.expires = jiffies + lp->poll_time; | ||
670 | add_timer(&pamsnet_timer); | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static int | ||
675 | pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) | ||
676 | { | ||
677 | struct net_local *lp = netdev_priv(dev); | ||
678 | unsigned long flags; | ||
679 | |||
680 | /* Block a timer-based transmit from overlapping. This could better be | ||
681 | * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. | ||
682 | */ | ||
683 | local_irq_save(flags); | ||
684 | |||
685 | if (stdma_islocked()) { | ||
686 | local_irq_restore(flags); | ||
687 | lp->stats.tx_errors++; | ||
688 | } | ||
689 | else { | ||
690 | int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; | ||
691 | unsigned long buf = virt_to_phys(skb->data); | ||
692 | int stat; | ||
693 | |||
694 | stdma_lock(pamsnet_intr, NULL); | ||
695 | DISABLE_IRQ(); | ||
696 | |||
697 | local_irq_restore(flags); | ||
698 | if( !STRAM_ADDR(buf+length-1) ) { | ||
699 | skb_copy_from_linear_data(skb, nic_packet->buffer, | ||
700 | length); | ||
701 | buf = (unsigned long)phys_nic_packet; | ||
702 | } | ||
703 | |||
704 | dma_cache_maintenance(buf, length, 1); | ||
705 | |||
706 | stat = sendpkt(lance_target, (unsigned char *)buf, length); | ||
707 | ENABLE_IRQ(); | ||
708 | stdma_release(); | ||
709 | |||
710 | dev->trans_start = jiffies; | ||
711 | dev->tbusy = 0; | ||
712 | lp->stats.tx_packets++; | ||
713 | lp->stats.tx_bytes+=length; | ||
714 | } | ||
715 | dev_kfree_skb(skb); | ||
716 | |||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | /* We have a good packet(s), get it/them out of the buffers. | ||
721 | */ | ||
722 | static void | ||
723 | pamsnet_poll_rx(struct net_device *dev) | ||
724 | { | ||
725 | struct net_local *lp = netdev_priv(dev); | ||
726 | int boguscount; | ||
727 | int pkt_len; | ||
728 | struct sk_buff *skb; | ||
729 | unsigned long flags; | ||
730 | |||
731 | local_irq_save(flags); | ||
732 | /* ++roman: Take care at locking the ST-DMA... This must be done with ints | ||
733 | * off, since otherwise an int could slip in between the question and the | ||
734 | * locking itself, and then we'd go to sleep... And locking itself is | ||
735 | * necessary to keep the floppy_change timer from working with ST-DMA | ||
736 | * registers. */ | ||
737 | if (stdma_islocked()) { | ||
738 | local_irq_restore(flags); | ||
739 | return; | ||
740 | } | ||
741 | stdma_lock(pamsnet_intr, NULL); | ||
742 | DISABLE_IRQ(); | ||
743 | local_irq_restore(flags); | ||
744 | |||
745 | boguscount = testpkt(lance_target); | ||
746 | if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; | ||
747 | |||
748 | while(boguscount--) { | ||
749 | pkt_len = receivepkt(lance_target, phys_nic_packet); | ||
750 | |||
751 | if( pkt_len < 60 ) break; | ||
752 | |||
753 | /* Good packet... */ | ||
754 | |||
755 | dma_cache_maintenance((unsigned long)phys_nic_packet, pkt_len, 0); | ||
756 | |||
757 | lp->poll_time = pamsnet_min_poll_time; /* fast poll */ | ||
758 | if( pkt_len >= 60 && pkt_len <= 2048 ) { | ||
759 | if (pkt_len > 1514) | ||
760 | pkt_len = 1514; | ||
761 | |||
762 | /* Malloc up new buffer. | ||
763 | */ | ||
764 | skb = alloc_skb(pkt_len, GFP_ATOMIC); | ||
765 | if (skb == NULL) { | ||
766 | printk("%s: Memory squeeze, dropping packet.\n", | ||
767 | dev->name); | ||
768 | lp->stats.rx_dropped++; | ||
769 | break; | ||
770 | } | ||
771 | skb->len = pkt_len; | ||
772 | skb->dev = dev; | ||
773 | |||
774 | /* 'skb->data' points to the start of sk_buff data area. | ||
775 | */ | ||
776 | skb_copy_to_linear_data(skb, nic_packet->buffer, | ||
777 | pkt_len); | ||
778 | netif_rx(skb); | ||
779 | dev->last_rx = jiffies; | ||
780 | lp->stats.rx_packets++; | ||
781 | lp->stats.rx_bytes+=pkt_len; | ||
782 | } | ||
783 | } | ||
784 | |||
785 | /* If any worth-while packets have been received, dev_rint() | ||
786 | has done a mark_bh(INET_BH) for us and will work on them | ||
787 | when we get to the bottom-half routine. | ||
788 | */ | ||
789 | |||
790 | ENABLE_IRQ(); | ||
791 | stdma_release(); | ||
792 | return; | ||
793 | } | ||
794 | |||
795 | /* pamsnet_tick: called by pamsnet_timer. Reads packets from the adapter, | ||
796 | * passes them to the higher layers and restarts the timer. | ||
797 | */ | ||
798 | static void | ||
799 | pamsnet_tick(unsigned long data) | ||
800 | { | ||
801 | struct net_device *dev = (struct net_device *)data; | ||
802 | struct net_local *lp = netdev_priv(dev); | ||
803 | |||
804 | if( pamsnet_debug > 0 && (lp->open_time++ & 7) == 8 ) | ||
805 | printk("pamsnet_tick: %ld\n", lp->open_time); | ||
806 | |||
807 | pamsnet_poll_rx(dev); | ||
808 | |||
809 | pamsnet_timer.expires = jiffies + lp->poll_time; | ||
810 | add_timer(&pamsnet_timer); | ||
811 | } | ||
812 | |||
813 | /* The inverse routine to pamsnet_open(). | ||
814 | */ | ||
815 | static int | ||
816 | pamsnet_close(struct net_device *dev) | ||
817 | { | ||
818 | struct net_local *lp = netdev_priv(dev); | ||
819 | |||
820 | if (pamsnet_debug > 0) | ||
821 | printk("pamsnet_close, open_time=%ld\n", lp->open_time); | ||
822 | del_timer(&pamsnet_timer); | ||
823 | stdma_lock(pamsnet_intr, NULL); | ||
824 | DISABLE_IRQ(); | ||
825 | |||
826 | if (if_up) | ||
827 | stop(lance_target); | ||
828 | if_up = 0; | ||
829 | |||
830 | lp->open_time = 0; | ||
831 | |||
832 | dev->tbusy = 1; | ||
833 | dev->start = 0; | ||
834 | |||
835 | ENABLE_IRQ(); | ||
836 | stdma_release(); | ||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | /* Get the current statistics. | ||
841 | This may be called with the card open or closed. | ||
842 | */ | ||
843 | static struct net_device_stats *net_get_stats(struct net_device *dev) | ||
844 | { | ||
845 | struct net_local *lp = netdev_priv(dev); | ||
846 | return &lp->stats; | ||
847 | } | ||
848 | |||
849 | |||
850 | #ifdef MODULE | ||
851 | |||
852 | static struct net_device *pam_dev; | ||
853 | |||
854 | int init_module(void) | ||
855 | { | ||
856 | pam_dev = pamsnet_probe(-1); | ||
857 | if (IS_ERR(pam_dev)) | ||
858 | return PTR_ERR(pam_dev); | ||
859 | return 0; | ||
860 | } | ||
861 | |||
862 | void cleanup_module(void) | ||
863 | { | ||
864 | unregister_netdev(pam_dev); | ||
865 | free_netdev(pam_dev); | ||
866 | } | ||
867 | |||
868 | #endif /* MODULE */ | ||
869 | |||
870 | /* Local variables: | ||
871 | * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include | ||
872 | -b m68k-linuxaout -Wall -Wstrict-prototypes -O2 | ||
873 | -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c atari_pamsnet.c" | ||
874 | * version-control: t | ||
875 | * kept-new-versions: 5 | ||
876 | * tab-width: 8 | ||
877 | * End: | ||
878 | */ | ||