1 | /* |
2 | * Linux ARCnet driver - COM90xx chipset (memory-mapped buffers) |
3 | * |
4 | * Written 1994-1999 by Avery Pennarun. |
5 | * Written 1999 by Martin Mares <mj@ucw.cz>. |
6 | * Derived from skeleton.c by Donald Becker. |
7 | * |
8 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) |
9 | * for sponsoring the further development of this driver. |
10 | * |
11 | * ********************** |
12 | * |
13 | * The original copyright of skeleton.c was as follows: |
14 | * |
15 | * skeleton.c Written 1993 by Donald Becker. |
16 | * Copyright 1993 United States Government as represented by the |
17 | * Director, National Security Agency. This software may only be used |
18 | * and distributed according to the terms of the GNU General Public License as |
19 | * modified by SRC, incorporated herein by reference. |
20 | * |
21 | * ********************** |
22 | * |
23 | * For more details, see drivers/net/arcnet.c |
24 | * |
25 | * ********************** |
26 | */ |
27 | |
28 | #define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt |
29 | |
30 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> |
32 | #include <linux/init.h> |
33 | #include <linux/interrupt.h> |
34 | #include <linux/ioport.h> |
35 | #include <linux/delay.h> |
36 | #include <linux/netdevice.h> |
37 | #include <linux/slab.h> |
38 | #include <linux/io.h> |
39 | |
40 | #include "arcdevice.h" |
41 | #include "com9026.h" |
42 | |
43 | /* Define this to speed up the autoprobe by assuming if only one io port and |
44 | * shmem are left in the list at Stage 5, they must correspond to each |
45 | * other. |
46 | * |
47 | * This is undefined by default because it might not always be true, and the |
48 | * extra check makes the autoprobe even more careful. Speed demons can turn |
49 | * it on - I think it should be fine if you only have one ARCnet card |
50 | * installed. |
51 | * |
52 | * If no ARCnet cards are installed, this delay never happens anyway and thus |
53 | * the option has no effect. |
54 | */ |
55 | #undef FAST_PROBE |
56 | |
57 | /* Internal function declarations */ |
58 | static int com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *); |
59 | static void com90xx_command(struct net_device *dev, int command); |
60 | static int com90xx_status(struct net_device *dev); |
61 | static void com90xx_setmask(struct net_device *dev, int mask); |
62 | static int com90xx_reset(struct net_device *dev, int really_reset); |
63 | static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, |
64 | void *buf, int count); |
65 | static void com90xx_copy_from_card(struct net_device *dev, int bufnum, |
66 | int offset, void *buf, int count); |
67 | |
68 | /* Known ARCnet cards */ |
69 | |
70 | static struct net_device *cards[16]; |
71 | static int numcards; |
72 | |
73 | /* Handy defines for ARCnet specific stuff */ |
74 | |
75 | /* The number of low I/O ports used by the card */ |
76 | #define ARCNET_TOTAL_SIZE 16 |
77 | |
78 | /* Amount of I/O memory used by the card */ |
79 | #define BUFFER_SIZE (512) |
80 | #define MIRROR_SIZE (BUFFER_SIZE * 4) |
81 | |
82 | static int com90xx_skip_probe __initdata = 0; |
83 | |
84 | /* Module parameters */ |
85 | |
86 | static int io; /* use the insmod io= irq= shmem= options */ |
87 | static int irq; |
88 | static int shmem; |
89 | static char device[9]; /* use eg. device=arc1 to change name */ |
90 | |
91 | module_param_hw(io, int, ioport, 0); |
92 | module_param_hw(irq, int, irq, 0); |
93 | module_param(shmem, int, 0); |
94 | module_param_string(device, device, sizeof(device), 0); |
95 | |
96 | static void __init com90xx_probe(void) |
97 | { |
98 | int count, status, ioaddr, numprint, airq, openparen = 0; |
99 | unsigned long airqmask; |
100 | int ports[(0x3f0 - 0x200) / 16 + 1] = { 0 }; |
101 | unsigned long *shmems; |
102 | void __iomem **iomem; |
103 | int numports, numshmems, *port; |
104 | u_long *p; |
105 | int index; |
106 | |
107 | if (!io && !irq && !shmem && !*device && com90xx_skip_probe) |
108 | return; |
109 | |
110 | shmems = kzalloc(size: ((0x100000 - 0xa0000) / 0x800) * sizeof(unsigned long), |
111 | GFP_KERNEL); |
112 | if (!shmems) |
113 | return; |
114 | iomem = kzalloc(size: ((0x100000 - 0xa0000) / 0x800) * sizeof(void __iomem *), |
115 | GFP_KERNEL); |
116 | if (!iomem) { |
117 | kfree(objp: shmems); |
118 | return; |
119 | } |
120 | |
121 | if (BUGLVL(D_NORMAL)) |
122 | pr_info("%s\n" , "COM90xx chipset support" ); |
123 | |
124 | /* set up the arrays where we'll store the possible probe addresses */ |
125 | numports = numshmems = 0; |
126 | if (io) |
127 | ports[numports++] = io; |
128 | else |
129 | for (count = 0x200; count <= 0x3f0; count += 16) |
130 | ports[numports++] = count; |
131 | if (shmem) |
132 | shmems[numshmems++] = shmem; |
133 | else |
134 | for (count = 0xA0000; count <= 0xFF800; count += 2048) |
135 | shmems[numshmems++] = count; |
136 | |
137 | /* Stage 1: abandon any reserved ports, or ones with status==0xFF |
138 | * (empty), and reset any others by reading the reset port. |
139 | */ |
140 | numprint = -1; |
141 | for (port = &ports[0]; port - ports < numports; port++) { |
142 | numprint++; |
143 | numprint %= 8; |
144 | if (!numprint) { |
145 | arc_cont(D_INIT, "\n" ); |
146 | arc_cont(D_INIT, "S1: " ); |
147 | } |
148 | arc_cont(D_INIT, "%Xh " , *port); |
149 | |
150 | ioaddr = *port; |
151 | |
152 | if (!request_region(*port, ARCNET_TOTAL_SIZE, |
153 | "arcnet (90xx)" )) { |
154 | arc_cont(D_INIT_REASONS, "(request_region)\n" ); |
155 | arc_cont(D_INIT_REASONS, "S1: " ); |
156 | if (BUGLVL(D_INIT_REASONS)) |
157 | numprint = 0; |
158 | *port-- = ports[--numports]; |
159 | continue; |
160 | } |
161 | if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) { |
162 | arc_cont(D_INIT_REASONS, "(empty)\n" ); |
163 | arc_cont(D_INIT_REASONS, "S1: " ); |
164 | if (BUGLVL(D_INIT_REASONS)) |
165 | numprint = 0; |
166 | release_region(*port, ARCNET_TOTAL_SIZE); |
167 | *port-- = ports[--numports]; |
168 | continue; |
169 | } |
170 | /* begin resetting card */ |
171 | arcnet_inb(ioaddr, COM9026_REG_R_RESET); |
172 | |
173 | arc_cont(D_INIT_REASONS, "\n" ); |
174 | arc_cont(D_INIT_REASONS, "S1: " ); |
175 | if (BUGLVL(D_INIT_REASONS)) |
176 | numprint = 0; |
177 | } |
178 | arc_cont(D_INIT, "\n" ); |
179 | |
180 | if (!numports) { |
181 | arc_cont(D_NORMAL, "S1: No ARCnet cards found.\n" ); |
182 | kfree(objp: shmems); |
183 | kfree(objp: iomem); |
184 | return; |
185 | } |
186 | /* Stage 2: we have now reset any possible ARCnet cards, so we can't |
187 | * do anything until they finish. If D_INIT, print the list of |
188 | * cards that are left. |
189 | */ |
190 | numprint = -1; |
191 | for (port = &ports[0]; port < ports + numports; port++) { |
192 | numprint++; |
193 | numprint %= 8; |
194 | if (!numprint) { |
195 | arc_cont(D_INIT, "\n" ); |
196 | arc_cont(D_INIT, "S2: " ); |
197 | } |
198 | arc_cont(D_INIT, "%Xh " , *port); |
199 | } |
200 | arc_cont(D_INIT, "\n" ); |
201 | mdelay(RESETtime); |
202 | |
203 | /* Stage 3: abandon any shmem addresses that don't have the signature |
204 | * 0xD1 byte in the right place, or are read-only. |
205 | */ |
206 | numprint = -1; |
207 | for (index = 0, p = &shmems[0]; index < numshmems; p++, index++) { |
208 | void __iomem *base; |
209 | |
210 | numprint++; |
211 | numprint %= 8; |
212 | if (!numprint) { |
213 | arc_cont(D_INIT, "\n" ); |
214 | arc_cont(D_INIT, "S3: " ); |
215 | } |
216 | arc_cont(D_INIT, "%lXh " , *p); |
217 | |
218 | if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)" )) { |
219 | arc_cont(D_INIT_REASONS, "(request_mem_region)\n" ); |
220 | arc_cont(D_INIT_REASONS, "Stage 3: " ); |
221 | if (BUGLVL(D_INIT_REASONS)) |
222 | numprint = 0; |
223 | goto out; |
224 | } |
225 | base = ioremap(offset: *p, MIRROR_SIZE); |
226 | if (!base) { |
227 | arc_cont(D_INIT_REASONS, "(ioremap)\n" ); |
228 | arc_cont(D_INIT_REASONS, "Stage 3: " ); |
229 | if (BUGLVL(D_INIT_REASONS)) |
230 | numprint = 0; |
231 | goto out1; |
232 | } |
233 | if (arcnet_readb(base, COM9026_REG_R_STATUS) != TESTvalue) { |
234 | arc_cont(D_INIT_REASONS, "(%02Xh != %02Xh)\n" , |
235 | arcnet_readb(base, COM9026_REG_R_STATUS), |
236 | TESTvalue); |
237 | arc_cont(D_INIT_REASONS, "S3: " ); |
238 | if (BUGLVL(D_INIT_REASONS)) |
239 | numprint = 0; |
240 | goto out2; |
241 | } |
242 | /* By writing 0x42 to the TESTvalue location, we also make |
243 | * sure no "mirror" shmem areas show up - if they occur |
244 | * in another pass through this loop, they will be discarded |
245 | * because *cptr != TESTvalue. |
246 | */ |
247 | arcnet_writeb(0x42, base, COM9026_REG_W_INTMASK); |
248 | if (arcnet_readb(base, COM9026_REG_R_STATUS) != 0x42) { |
249 | arc_cont(D_INIT_REASONS, "(read only)\n" ); |
250 | arc_cont(D_INIT_REASONS, "S3: " ); |
251 | goto out2; |
252 | } |
253 | arc_cont(D_INIT_REASONS, "\n" ); |
254 | arc_cont(D_INIT_REASONS, "S3: " ); |
255 | if (BUGLVL(D_INIT_REASONS)) |
256 | numprint = 0; |
257 | iomem[index] = base; |
258 | continue; |
259 | out2: |
260 | iounmap(addr: base); |
261 | out1: |
262 | release_mem_region(*p, MIRROR_SIZE); |
263 | out: |
264 | *p-- = shmems[--numshmems]; |
265 | index--; |
266 | } |
267 | arc_cont(D_INIT, "\n" ); |
268 | |
269 | if (!numshmems) { |
270 | arc_cont(D_NORMAL, "S3: No ARCnet cards found.\n" ); |
271 | for (port = &ports[0]; port < ports + numports; port++) |
272 | release_region(*port, ARCNET_TOTAL_SIZE); |
273 | kfree(objp: shmems); |
274 | kfree(objp: iomem); |
275 | return; |
276 | } |
277 | /* Stage 4: something of a dummy, to report the shmems that are |
278 | * still possible after stage 3. |
279 | */ |
280 | numprint = -1; |
281 | for (p = &shmems[0]; p < shmems + numshmems; p++) { |
282 | numprint++; |
283 | numprint %= 8; |
284 | if (!numprint) { |
285 | arc_cont(D_INIT, "\n" ); |
286 | arc_cont(D_INIT, "S4: " ); |
287 | } |
288 | arc_cont(D_INIT, "%lXh " , *p); |
289 | } |
290 | arc_cont(D_INIT, "\n" ); |
291 | |
292 | /* Stage 5: for any ports that have the correct status, can disable |
293 | * the RESET flag, and (if no irq is given) generate an autoirq, |
294 | * register an ARCnet device. |
295 | * |
296 | * Currently, we can only register one device per probe, so quit |
297 | * after the first one is found. |
298 | */ |
299 | numprint = -1; |
300 | for (port = &ports[0]; port < ports + numports; port++) { |
301 | int found = 0; |
302 | |
303 | numprint++; |
304 | numprint %= 8; |
305 | if (!numprint) { |
306 | arc_cont(D_INIT, "\n" ); |
307 | arc_cont(D_INIT, "S5: " ); |
308 | } |
309 | arc_cont(D_INIT, "%Xh " , *port); |
310 | |
311 | ioaddr = *port; |
312 | status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS); |
313 | |
314 | if ((status & 0x9D) |
315 | != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { |
316 | arc_cont(D_INIT_REASONS, "(status=%Xh)\n" , status); |
317 | arc_cont(D_INIT_REASONS, "S5: " ); |
318 | if (BUGLVL(D_INIT_REASONS)) |
319 | numprint = 0; |
320 | release_region(*port, ARCNET_TOTAL_SIZE); |
321 | *port-- = ports[--numports]; |
322 | continue; |
323 | } |
324 | arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear, |
325 | ioaddr, COM9026_REG_W_COMMAND); |
326 | status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS); |
327 | if (status & RESETflag) { |
328 | arc_cont(D_INIT_REASONS, " (eternal reset, status=%Xh)\n" , |
329 | status); |
330 | arc_cont(D_INIT_REASONS, "S5: " ); |
331 | if (BUGLVL(D_INIT_REASONS)) |
332 | numprint = 0; |
333 | release_region(*port, ARCNET_TOTAL_SIZE); |
334 | *port-- = ports[--numports]; |
335 | continue; |
336 | } |
337 | /* skip this completely if an IRQ was given, because maybe |
338 | * we're on a machine that locks during autoirq! |
339 | */ |
340 | if (!irq) { |
341 | /* if we do this, we're sure to get an IRQ since the |
342 | * card has just reset and the NORXflag is on until |
343 | * we tell it to start receiving. |
344 | */ |
345 | airqmask = probe_irq_on(); |
346 | arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK); |
347 | udelay(1); |
348 | arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK); |
349 | airq = probe_irq_off(airqmask); |
350 | |
351 | if (airq <= 0) { |
352 | arc_cont(D_INIT_REASONS, "(airq=%d)\n" , airq); |
353 | arc_cont(D_INIT_REASONS, "S5: " ); |
354 | if (BUGLVL(D_INIT_REASONS)) |
355 | numprint = 0; |
356 | release_region(*port, ARCNET_TOTAL_SIZE); |
357 | *port-- = ports[--numports]; |
358 | continue; |
359 | } |
360 | } else { |
361 | airq = irq; |
362 | } |
363 | |
364 | arc_cont(D_INIT, "(%d," , airq); |
365 | openparen = 1; |
366 | |
367 | /* Everything seems okay. But which shmem, if any, puts |
368 | * back its signature byte when the card is reset? |
369 | * |
370 | * If there are multiple cards installed, there might be |
371 | * multiple shmems still in the list. |
372 | */ |
373 | #ifdef FAST_PROBE |
374 | if (numports > 1 || numshmems > 1) { |
375 | arcnet_inb(ioaddr, COM9026_REG_R_RESET); |
376 | mdelay(RESETtime); |
377 | } else { |
378 | /* just one shmem and port, assume they match */ |
379 | arcnet_writeb(TESTvalue, iomem[0], |
380 | COM9026_REG_W_INTMASK); |
381 | } |
382 | #else |
383 | arcnet_inb(ioaddr, COM9026_REG_R_RESET); |
384 | mdelay(RESETtime); |
385 | #endif |
386 | |
387 | for (index = 0; index < numshmems; index++) { |
388 | u_long ptr = shmems[index]; |
389 | void __iomem *base = iomem[index]; |
390 | |
391 | if (arcnet_readb(base, COM9026_REG_R_STATUS) == TESTvalue) { /* found one */ |
392 | arc_cont(D_INIT, "%lXh)\n" , *p); |
393 | openparen = 0; |
394 | |
395 | /* register the card */ |
396 | if (com90xx_found(ioaddr: *port, airq, shmem: ptr, base) == 0) |
397 | found = 1; |
398 | numprint = -1; |
399 | |
400 | /* remove shmem from the list */ |
401 | shmems[index] = shmems[--numshmems]; |
402 | iomem[index] = iomem[numshmems]; |
403 | break; /* go to the next I/O port */ |
404 | } else { |
405 | arc_cont(D_INIT_REASONS, "%Xh-" , |
406 | arcnet_readb(base, COM9026_REG_R_STATUS)); |
407 | } |
408 | } |
409 | |
410 | if (openparen) { |
411 | if (BUGLVL(D_INIT)) |
412 | pr_cont("no matching shmem)\n" ); |
413 | if (BUGLVL(D_INIT_REASONS)) { |
414 | pr_cont("S5: " ); |
415 | numprint = 0; |
416 | } |
417 | } |
418 | if (!found) |
419 | release_region(*port, ARCNET_TOTAL_SIZE); |
420 | *port-- = ports[--numports]; |
421 | } |
422 | |
423 | if (BUGLVL(D_INIT_REASONS)) |
424 | pr_cont("\n" ); |
425 | |
426 | /* Now put back TESTvalue on all leftover shmems. */ |
427 | for (index = 0; index < numshmems; index++) { |
428 | arcnet_writeb(TESTvalue, iomem[index], COM9026_REG_W_INTMASK); |
429 | iounmap(addr: iomem[index]); |
430 | release_mem_region(shmems[index], MIRROR_SIZE); |
431 | } |
432 | kfree(objp: shmems); |
433 | kfree(objp: iomem); |
434 | } |
435 | |
436 | static int __init check_mirror(unsigned long addr, size_t size) |
437 | { |
438 | void __iomem *p; |
439 | int res = -1; |
440 | |
441 | if (!request_mem_region(addr, size, "arcnet (90xx)" )) |
442 | return -1; |
443 | |
444 | p = ioremap(offset: addr, size); |
445 | if (p) { |
446 | if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue) |
447 | res = 1; |
448 | else |
449 | res = 0; |
450 | iounmap(addr: p); |
451 | } |
452 | |
453 | release_mem_region(addr, size); |
454 | return res; |
455 | } |
456 | |
457 | /* Set up the struct net_device associated with this card. Called after |
458 | * probing succeeds. |
459 | */ |
460 | static int __init com90xx_found(int ioaddr, int airq, u_long shmem, |
461 | void __iomem *p) |
462 | { |
463 | struct net_device *dev = NULL; |
464 | struct arcnet_local *lp; |
465 | u_long first_mirror, last_mirror; |
466 | int mirror_size; |
467 | |
468 | /* allocate struct net_device */ |
469 | dev = alloc_arcdev(name: device); |
470 | if (!dev) { |
471 | arc_cont(D_NORMAL, "com90xx: Can't allocate device!\n" ); |
472 | iounmap(addr: p); |
473 | release_mem_region(shmem, MIRROR_SIZE); |
474 | return -ENOMEM; |
475 | } |
476 | lp = netdev_priv(dev); |
477 | /* find the real shared memory start/end points, including mirrors */ |
478 | |
479 | /* guess the actual size of one "memory mirror" - the number of |
480 | * bytes between copies of the shared memory. On most cards, it's |
481 | * 2k (or there are no mirrors at all) but on some, it's 4k. |
482 | */ |
483 | mirror_size = MIRROR_SIZE; |
484 | if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue && |
485 | check_mirror(addr: shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 && |
486 | check_mirror(addr: shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1) |
487 | mirror_size = 2 * MIRROR_SIZE; |
488 | |
489 | first_mirror = shmem - mirror_size; |
490 | while (check_mirror(addr: first_mirror, size: mirror_size) == 1) |
491 | first_mirror -= mirror_size; |
492 | first_mirror += mirror_size; |
493 | |
494 | last_mirror = shmem + mirror_size; |
495 | while (check_mirror(addr: last_mirror, size: mirror_size) == 1) |
496 | last_mirror += mirror_size; |
497 | last_mirror -= mirror_size; |
498 | |
499 | dev->mem_start = first_mirror; |
500 | dev->mem_end = last_mirror + MIRROR_SIZE - 1; |
501 | |
502 | iounmap(addr: p); |
503 | release_mem_region(shmem, MIRROR_SIZE); |
504 | |
505 | if (!request_mem_region(dev->mem_start, |
506 | dev->mem_end - dev->mem_start + 1, |
507 | "arcnet (90xx)" )) |
508 | goto err_free_dev; |
509 | |
510 | /* reserve the irq */ |
511 | if (request_irq(irq: airq, handler: arcnet_interrupt, flags: 0, name: "arcnet (90xx)" , dev)) { |
512 | arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n" , airq); |
513 | goto err_release_mem; |
514 | } |
515 | dev->irq = airq; |
516 | |
517 | /* Initialize the rest of the device structure. */ |
518 | lp->card_name = "COM90xx" ; |
519 | lp->hw.command = com90xx_command; |
520 | lp->hw.status = com90xx_status; |
521 | lp->hw.intmask = com90xx_setmask; |
522 | lp->hw.reset = com90xx_reset; |
523 | lp->hw.owner = THIS_MODULE; |
524 | lp->hw.copy_to_card = com90xx_copy_to_card; |
525 | lp->hw.copy_from_card = com90xx_copy_from_card; |
526 | lp->mem_start = ioremap(offset: dev->mem_start, |
527 | size: dev->mem_end - dev->mem_start + 1); |
528 | if (!lp->mem_start) { |
529 | arc_printk(D_NORMAL, dev, "Can't remap device memory!\n" ); |
530 | goto err_free_irq; |
531 | } |
532 | |
533 | /* get and check the station ID from offset 1 in shmem */ |
534 | arcnet_set_addr(dev, arcnet_readb(lp->mem_start, |
535 | COM9026_REG_R_STATION)); |
536 | |
537 | dev->base_addr = ioaddr; |
538 | |
539 | arc_printk(D_NORMAL, dev, "COM90xx station %02Xh found at %03lXh, IRQ %d, ShMem %lXh (%ld*%xh).\n" , |
540 | dev->dev_addr[0], |
541 | dev->base_addr, dev->irq, dev->mem_start, |
542 | (dev->mem_end - dev->mem_start + 1) / mirror_size, |
543 | mirror_size); |
544 | |
545 | if (register_netdev(dev)) |
546 | goto err_unmap; |
547 | |
548 | cards[numcards++] = dev; |
549 | return 0; |
550 | |
551 | err_unmap: |
552 | iounmap(addr: lp->mem_start); |
553 | err_free_irq: |
554 | free_irq(dev->irq, dev); |
555 | err_release_mem: |
556 | release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); |
557 | err_free_dev: |
558 | free_arcdev(dev); |
559 | return -EIO; |
560 | } |
561 | |
562 | static void com90xx_command(struct net_device *dev, int cmd) |
563 | { |
564 | short ioaddr = dev->base_addr; |
565 | |
566 | arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND); |
567 | } |
568 | |
569 | static int com90xx_status(struct net_device *dev) |
570 | { |
571 | short ioaddr = dev->base_addr; |
572 | |
573 | return arcnet_inb(ioaddr, COM9026_REG_R_STATUS); |
574 | } |
575 | |
576 | static void com90xx_setmask(struct net_device *dev, int mask) |
577 | { |
578 | short ioaddr = dev->base_addr; |
579 | |
580 | arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK); |
581 | } |
582 | |
583 | /* Do a hardware reset on the card, and set up necessary registers. |
584 | * |
585 | * This should be called as little as possible, because it disrupts the |
586 | * token on the network (causes a RECON) and requires a significant delay. |
587 | * |
588 | * However, it does make sure the card is in a defined state. |
589 | */ |
590 | static int com90xx_reset(struct net_device *dev, int really_reset) |
591 | { |
592 | struct arcnet_local *lp = netdev_priv(dev); |
593 | short ioaddr = dev->base_addr; |
594 | |
595 | arc_printk(D_INIT, dev, "Resetting (status=%02Xh)\n" , |
596 | arcnet_inb(ioaddr, COM9026_REG_R_STATUS)); |
597 | |
598 | if (really_reset) { |
599 | /* reset the card */ |
600 | arcnet_inb(ioaddr, COM9026_REG_R_RESET); |
601 | mdelay(RESETtime); |
602 | } |
603 | /* clear flags & end reset */ |
604 | arcnet_outb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND); |
605 | arcnet_outb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND); |
606 | |
607 | #if 0 |
608 | /* don't do this until we verify that it doesn't hurt older cards! */ |
609 | arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) | ENABLE16flag, |
610 | ioaddr, COM9026_REG_RW_CONFIG); |
611 | #endif |
612 | |
613 | /* verify that the ARCnet signature byte is present */ |
614 | if (arcnet_readb(lp->mem_start, COM9026_REG_R_STATUS) != TESTvalue) { |
615 | if (really_reset) |
616 | arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n" ); |
617 | return 1; |
618 | } |
619 | /* enable extended (512-byte) packets */ |
620 | arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND); |
621 | |
622 | /* clean out all the memory to make debugging make more sense :) */ |
623 | if (BUGLVL(D_DURING)) |
624 | memset_io(lp->mem_start, 0x42, 2048); |
625 | |
626 | /* done! return success. */ |
627 | return 0; |
628 | } |
629 | |
630 | static void com90xx_copy_to_card(struct net_device *dev, int bufnum, |
631 | int offset, void *buf, int count) |
632 | { |
633 | struct arcnet_local *lp = netdev_priv(dev); |
634 | void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; |
635 | |
636 | TIME(dev, "memcpy_toio" , count, memcpy_toio(memaddr, buf, count)); |
637 | } |
638 | |
639 | static void com90xx_copy_from_card(struct net_device *dev, int bufnum, |
640 | int offset, void *buf, int count) |
641 | { |
642 | struct arcnet_local *lp = netdev_priv(dev); |
643 | void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; |
644 | |
645 | TIME(dev, "memcpy_fromio" , count, memcpy_fromio(buf, memaddr, count)); |
646 | } |
647 | |
648 | MODULE_DESCRIPTION("ARCnet COM90xx normal chipset driver" ); |
649 | MODULE_LICENSE("GPL" ); |
650 | |
651 | static int __init com90xx_init(void) |
652 | { |
653 | if (irq == 2) |
654 | irq = 9; |
655 | com90xx_probe(); |
656 | if (!numcards) |
657 | return -EIO; |
658 | return 0; |
659 | } |
660 | |
661 | static void __exit com90xx_exit(void) |
662 | { |
663 | struct net_device *dev; |
664 | struct arcnet_local *lp; |
665 | int count; |
666 | |
667 | for (count = 0; count < numcards; count++) { |
668 | dev = cards[count]; |
669 | lp = netdev_priv(dev); |
670 | |
671 | unregister_netdev(dev); |
672 | free_irq(dev->irq, dev); |
673 | iounmap(addr: lp->mem_start); |
674 | release_region(dev->base_addr, ARCNET_TOTAL_SIZE); |
675 | release_mem_region(dev->mem_start, |
676 | dev->mem_end - dev->mem_start + 1); |
677 | free_arcdev(dev); |
678 | } |
679 | } |
680 | |
681 | module_init(com90xx_init); |
682 | module_exit(com90xx_exit); |
683 | |
684 | #ifndef MODULE |
685 | static int __init com90xx_setup(char *s) |
686 | { |
687 | int ints[8]; |
688 | |
689 | s = get_options(str: s, nints: 8, ints); |
690 | if (!ints[0] && !*s) { |
691 | pr_notice("Disabled\n" ); |
692 | return 1; |
693 | } |
694 | |
695 | switch (ints[0]) { |
696 | default: /* ERROR */ |
697 | pr_err("Too many arguments\n" ); |
698 | fallthrough; |
699 | case 3: /* Mem address */ |
700 | shmem = ints[3]; |
701 | fallthrough; |
702 | case 2: /* IRQ */ |
703 | irq = ints[2]; |
704 | fallthrough; |
705 | case 1: /* IO address */ |
706 | io = ints[1]; |
707 | } |
708 | |
709 | if (*s) |
710 | snprintf(buf: device, size: sizeof(device), fmt: "%s" , s); |
711 | |
712 | return 1; |
713 | } |
714 | |
715 | __setup("com90xx=" , com90xx_setup); |
716 | #endif |
717 | |