Staging: ti-st: update TODO
[sfrench/cifs-2.6.git] / drivers / net / arcnet / com90io.c
1 /*
2  * Linux ARCnet driver - COM90xx chipset (IO-mapped buffers)
3  * 
4  * Written 1997 by David Woodhouse.
5  * Written 1994-1999 by Avery Pennarun.
6  * Written 1999-2000 by Martin Mares <mj@ucw.cz>.
7  * Derived from skeleton.c by Donald Becker.
8  *
9  * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
10  *  for sponsoring the further development of this driver.
11  *
12  * **********************
13  *
14  * The original copyright of skeleton.c was as follows:
15  *
16  * skeleton.c Written 1993 by Donald Becker.
17  * Copyright 1993 United States Government as represented by the
18  * Director, National Security Agency.  This software may only be used
19  * and distributed according to the terms of the GNU General Public License as
20  * modified by SRC, incorporated herein by reference.
21  *
22  * **********************
23  *
24  * For more details, see drivers/net/arcnet.c
25  *
26  * **********************
27  */
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <linux/moduleparam.h>
31 #include <linux/ioport.h>
32 #include <linux/delay.h>
33 #include <linux/netdevice.h>
34 #include <linux/bootmem.h>
35 #include <linux/init.h>
36 #include <asm/io.h>
37 #include <linux/arcdevice.h>
38
39
40 #define VERSION "arcnet: COM90xx IO-mapped mode support (by David Woodhouse et el.)\n"
41
42
43 /* Internal function declarations */
44
45 static int com90io_found(struct net_device *dev);
46 static void com90io_command(struct net_device *dev, int command);
47 static int com90io_status(struct net_device *dev);
48 static void com90io_setmask(struct net_device *dev, int mask);
49 static int com90io_reset(struct net_device *dev, int really_reset);
50 static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset,
51                                  void *buf, int count);
52 static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset,
53                                    void *buf, int count);
54
55
56 /* Handy defines for ARCnet specific stuff */
57
58 /* The number of low I/O ports used by the card. */
59 #define ARCNET_TOTAL_SIZE 16
60
61 /* COM 9026 controller chip --> ARCnet register addresses */
62 #define _INTMASK (ioaddr+0)     /* writable */
63 #define _STATUS  (ioaddr+0)     /* readable */
64 #define _COMMAND (ioaddr+1)     /* writable, returns random vals on read (?) */
65 #define _RESET  (ioaddr+8)      /* software reset (on read) */
66 #define _MEMDATA  (ioaddr+12)   /* Data port for IO-mapped memory */
67 #define _ADDR_HI  (ioaddr+15)   /* Control registers for said */
68 #define _ADDR_LO  (ioaddr+14)
69 #define _CONFIG  (ioaddr+2)     /* Configuration register */
70
71 #undef ASTATUS
72 #undef ACOMMAND
73 #undef AINTMASK
74
75 #define ASTATUS()       inb(_STATUS)
76 #define ACOMMAND(cmd) outb((cmd),_COMMAND)
77 #define AINTMASK(msk)   outb((msk),_INTMASK)
78 #define SETCONF()       outb((lp->config),_CONFIG)
79
80
81 /****************************************************************************
82  *                                                                          *
83  * IO-mapped operation routines                                             *
84  *                                                                          *
85  ****************************************************************************/
86
87 #undef ONE_AT_A_TIME_TX
88 #undef ONE_AT_A_TIME_RX
89
90 static u_char get_buffer_byte(struct net_device *dev, unsigned offset)
91 {
92         int ioaddr = dev->base_addr;
93
94         outb(offset >> 8, _ADDR_HI);
95         outb(offset & 0xff, _ADDR_LO);
96
97         return inb(_MEMDATA);
98 }
99
100 #ifdef ONE_AT_A_TIME_TX
101 static void put_buffer_byte(struct net_device *dev, unsigned offset, u_char datum)
102 {
103         int ioaddr = dev->base_addr;
104
105         outb(offset >> 8, _ADDR_HI);
106         outb(offset & 0xff, _ADDR_LO);
107
108         outb(datum, _MEMDATA);
109 }
110
111 #endif
112
113
114 static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest)
115 {
116         int ioaddr = dev->base_addr;
117
118         outb((offset >> 8) | AUTOINCflag, _ADDR_HI);
119         outb(offset & 0xff, _ADDR_LO);
120
121         while (length--)
122 #ifdef ONE_AT_A_TIME_RX
123                 *(dest++) = get_buffer_byte(dev, offset++);
124 #else
125                 *(dest++) = inb(_MEMDATA);
126 #endif
127 }
128
129 static void put_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest)
130 {
131         int ioaddr = dev->base_addr;
132
133         outb((offset >> 8) | AUTOINCflag, _ADDR_HI);
134         outb(offset & 0xff, _ADDR_LO);
135
136         while (length--)
137 #ifdef ONE_AT_A_TIME_TX
138                 put_buffer_byte(dev, offset++, *(dest++));
139 #else
140                 outb(*(dest++), _MEMDATA);
141 #endif
142 }
143
144 /*
145  * We cannot probe for an IO mapped card either, although we can check that
146  * it's where we were told it was, and even autoirq
147  */
148 static int __init com90io_probe(struct net_device *dev)
149 {
150         int ioaddr = dev->base_addr, status;
151         unsigned long airqmask;
152
153         BUGLVL(D_NORMAL) printk(VERSION);
154         BUGLVL(D_NORMAL) printk("E-mail me if you actually test this driver, please!\n");
155
156         if (!ioaddr) {
157                 BUGMSG(D_NORMAL, "No autoprobe for IO mapped cards; you "
158                        "must specify the base address!\n");
159                 return -ENODEV;
160         }
161         if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) {
162                 BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n",
163                        ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
164                 return -ENXIO;
165         }
166         if (ASTATUS() == 0xFF) {
167                 BUGMSG(D_INIT_REASONS, "IO address %x empty\n", ioaddr);
168                 goto err_out;
169         }
170         inb(_RESET);
171         mdelay(RESETtime);
172
173         status = ASTATUS();
174
175         if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
176                 BUGMSG(D_INIT_REASONS, "Status invalid (%Xh).\n", status);
177                 goto err_out;
178         }
179         BUGMSG(D_INIT_REASONS, "Status after reset: %X\n", status);
180
181         ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
182
183         BUGMSG(D_INIT_REASONS, "Status after reset acknowledged: %X\n", status);
184
185         status = ASTATUS();
186
187         if (status & RESETflag) {
188                 BUGMSG(D_INIT_REASONS, "Eternal reset (status=%Xh)\n", status);
189                 goto err_out;
190         }
191         outb((0x16 | IOMAPflag) & ~ENABLE16flag, _CONFIG);
192
193         /* Read first loc'n of memory */
194
195         outb(AUTOINCflag, _ADDR_HI);
196         outb(0, _ADDR_LO);
197
198         if ((status = inb(_MEMDATA)) != 0xd1) {
199                 BUGMSG(D_INIT_REASONS, "Signature byte not found"
200                        " (%Xh instead).\n", status);
201                 goto err_out;
202         }
203         if (!dev->irq) {
204                 /*
205                  * if we do this, we're sure to get an IRQ since the
206                  * card has just reset and the NORXflag is on until
207                  * we tell it to start receiving.
208                  */
209
210                 airqmask = probe_irq_on();
211                 outb(NORXflag, _INTMASK);
212                 udelay(1);
213                 outb(0, _INTMASK);
214                 dev->irq = probe_irq_off(airqmask);
215
216                 if (dev->irq <= 0) {
217                         BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed\n");
218                         goto err_out;
219                 }
220         }
221         release_region(ioaddr, ARCNET_TOTAL_SIZE); /* end of probing */
222         return com90io_found(dev);
223
224 err_out:
225         release_region(ioaddr, ARCNET_TOTAL_SIZE);
226         return -ENODEV;
227 }
228
229
230 /* Set up the struct net_device associated with this card.  Called after
231  * probing succeeds.
232  */
233 static int __init com90io_found(struct net_device *dev)
234 {
235         struct arcnet_local *lp;
236         int ioaddr = dev->base_addr;
237         int err;
238
239         /* Reserve the irq */
240         if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (COM90xx-IO)", dev)) {
241                 BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
242                 return -ENODEV;
243         }
244         /* Reserve the I/O region */
245         if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) {
246                 free_irq(dev->irq, dev);
247                 return -EBUSY;
248         }
249
250         lp = netdev_priv(dev);
251         lp->card_name = "COM90xx I/O";
252         lp->hw.command = com90io_command;
253         lp->hw.status = com90io_status;
254         lp->hw.intmask = com90io_setmask;
255         lp->hw.reset = com90io_reset;
256         lp->hw.owner = THIS_MODULE;
257         lp->hw.copy_to_card = com90io_copy_to_card;
258         lp->hw.copy_from_card = com90io_copy_from_card;
259
260         lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag;
261         SETCONF();
262
263         /* get and check the station ID from offset 1 in shmem */
264
265         dev->dev_addr[0] = get_buffer_byte(dev, 1);
266
267         err = register_netdev(dev);
268         if (err) {
269                 outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);
270                 free_irq(dev->irq, dev);
271                 release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
272                 return err;
273         }
274
275         BUGMSG(D_NORMAL, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n",
276                dev->dev_addr[0], dev->base_addr, dev->irq);
277
278         return 0;
279 }
280
281
282 /*
283  * Do a hardware reset on the card, and set up necessary registers.
284  *
285  * This should be called as little as possible, because it disrupts the
286  * token on the network (causes a RECON) and requires a significant delay.
287  *
288  * However, it does make sure the card is in a defined state.
289  */
290 static int com90io_reset(struct net_device *dev, int really_reset)
291 {
292         struct arcnet_local *lp = netdev_priv(dev);
293         short ioaddr = dev->base_addr;
294
295         BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
296
297         if (really_reset) {
298                 /* reset the card */
299                 inb(_RESET);
300                 mdelay(RESETtime);
301         }
302         /* Set the thing to IO-mapped, 8-bit  mode */
303         lp->config = (0x1C | IOMAPflag) & ~ENABLE16flag;
304         SETCONF();
305
306         ACOMMAND(CFLAGScmd | RESETclear);       /* clear flags & end reset */
307         ACOMMAND(CFLAGScmd | CONFIGclear);
308
309         /* verify that the ARCnet signature byte is present */
310         if (get_buffer_byte(dev, 0) != TESTvalue) {
311                 BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
312                 return 1;
313         }
314         /* enable extended (512-byte) packets */
315         ACOMMAND(CONFIGcmd | EXTconf);
316
317         /* done!  return success. */
318         return 0;
319 }
320
321
322 static void com90io_command(struct net_device *dev, int cmd)
323 {
324         short ioaddr = dev->base_addr;
325
326         ACOMMAND(cmd);
327 }
328
329
330 static int com90io_status(struct net_device *dev)
331 {
332         short ioaddr = dev->base_addr;
333
334         return ASTATUS();
335 }
336
337
338 static void com90io_setmask(struct net_device *dev, int mask)
339 {
340         short ioaddr = dev->base_addr;
341
342         AINTMASK(mask);
343 }
344
345 static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset,
346                                  void *buf, int count)
347 {
348         TIME("put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf));
349 }
350
351
352 static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset,
353                                    void *buf, int count)
354 {
355         TIME("get_whole_buffer", count, get_whole_buffer(dev, bufnum * 512 + offset, count, buf));
356 }
357
358 static int io;                  /* use the insmod io= irq= shmem= options */
359 static int irq;
360 static char device[9];          /* use eg. device=arc1 to change name */
361
362 module_param(io, int, 0);
363 module_param(irq, int, 0);
364 module_param_string(device, device, sizeof(device), 0);
365 MODULE_LICENSE("GPL");
366
367 #ifndef MODULE
368 static int __init com90io_setup(char *s)
369 {
370         int ints[4];
371         s = get_options(s, 4, ints);
372         if (!ints[0])
373                 return 0;
374         switch (ints[0]) {
375         default:                /* ERROR */
376                 printk("com90io: Too many arguments.\n");
377         case 2:         /* IRQ */
378                 irq = ints[2];
379         case 1:         /* IO address */
380                 io = ints[1];
381         }
382         if (*s)
383                 snprintf(device, sizeof(device), "%s", s);
384         return 1;
385 }
386 __setup("com90io=", com90io_setup);
387 #endif
388
389 static struct net_device *my_dev;
390
391 static int __init com90io_init(void)
392 {
393         struct net_device *dev;
394         int err;
395
396         dev = alloc_arcdev(device);
397         if (!dev)
398                 return -ENOMEM;
399
400         dev->base_addr = io;
401         dev->irq = irq;
402         if (dev->irq == 2)
403                 dev->irq = 9;
404
405         err = com90io_probe(dev);
406
407         if (err) {
408                 free_netdev(dev);
409                 return err;
410         }
411
412         my_dev = dev;
413         return 0;
414 }
415
416 static void __exit com90io_exit(void)
417 {
418         struct net_device *dev = my_dev;
419         int ioaddr = dev->base_addr;
420
421         unregister_netdev(dev);
422
423         /* Set the thing back to MMAP mode, in case the old driver is loaded later */
424         outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);
425
426         free_irq(dev->irq, dev);
427         release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
428         free_netdev(dev);
429 }
430
431 module_init(com90io_init)
432 module_exit(com90io_exit)