1 /*
2 * Linux ARCnet driver - COM20020 chipset support
3 *
4 * Written 1997 by David Woodhouse.
5 * Written 1994-1999 by Avery Pennarun.
6 * Written 1999 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/module.h>
29 #include <linux/kernel.h>
30 #include <linux/types.h>
31 #include <linux/ioport.h>
32 #include <linux/slab.h>
33 #include <linux/errno.h>
34 #include <linux/delay.h>
35 #include <linux/netdevice.h>
36 #include <linux/init.h>
37 #include <linux/arcdevice.h>
38 #include <linux/com20020.h>
39
40 #include <asm/io.h>
41
42 #define VERSION "arcnet: COM20020 chipset support (by David Woodhouse et al.)\n"
43
44 static char *clockrates[] =
45 {"10 Mb/s", "Reserved", "5 Mb/s",
46 "2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s",
47 "156.25 Kb/s", "Reserved", "Reserved", "Reserved"};
48
49 static void com20020_command(struct net_device *dev, int command);
50 static int com20020_status(struct net_device *dev);
51 static void com20020_setmask(struct net_device *dev, int mask);
52 static int com20020_reset(struct net_device *dev, int really_reset);
53 static void com20020_openclose(struct net_device *dev, bool open);
54 static void com20020_copy_to_card(struct net_device *dev, int bufnum,
55 int offset, void *buf, int count);
56 static void com20020_copy_from_card(struct net_device *dev, int bufnum,
57 int offset, void *buf, int count);
58 static void com20020_set_mc_list(struct net_device *dev);
59
60
com20020_copy_from_card(struct net_device * dev,int bufnum,int offset,void * buf,int count)61 static void com20020_copy_from_card(struct net_device *dev, int bufnum,
62 int offset, void *buf, int count)
63 {
64 int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset;
65
66 /* set up the address register */
67 outb((ofs >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
68 outb(ofs & 0xff, _ADDR_LO);
69
70 /* copy the data */
71 TIME("insb", count, insb(_MEMDATA, buf, count));
72 }
73
74
com20020_copy_to_card(struct net_device * dev,int bufnum,int offset,void * buf,int count)75 static void com20020_copy_to_card(struct net_device *dev, int bufnum,
76 int offset, void *buf, int count)
77 {
78 int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset;
79
80 /* set up the address register */
81 outb((ofs >> 8) | AUTOINCflag, _ADDR_HI);
82 outb(ofs & 0xff, _ADDR_LO);
83
84 /* copy the data */
85 TIME("outsb", count, outsb(_MEMDATA, buf, count));
86 }
87
88
89 /* Reset the card and check some basic stuff during the detection stage. */
com20020_check(struct net_device * dev)90 int __devinit com20020_check(struct net_device *dev)
91 {
92 int ioaddr = dev->base_addr, status;
93 struct arcnet_local *lp = dev->priv;
94
95 ARCRESET0;
96 mdelay(RESETtime);
97
98 lp->setup = lp->clockm ? 0 : (lp->clockp << 1);
99 lp->setup2 = (lp->clockm << 4) | 8;
100
101 /* Enable P1Mode for backplane mode */
102 lp->setup = lp->setup | P1MODE;
103
104 SET_SUBADR(SUB_SETUP1);
105 outb(lp->setup, _XREG);
106
107 if (lp->card_flags & ARC_CAN_10MBIT)
108 {
109 SET_SUBADR(SUB_SETUP2);
110 outb(lp->setup2, _XREG);
111
112 /* must now write the magic "restart operation" command */
113 mdelay(1);
114 outb(0x18, _COMMAND);
115 }
116
117 lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2);
118 /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */
119 SETCONF;
120 outb(0x42, ioaddr + 7);
121
122 status = ASTATUS();
123
124 if ((status & 0x99) != (NORXflag | TXFREEflag | RESETflag)) {
125 BUGMSG(D_NORMAL, "status invalid (%Xh).\n", status);
126 return -ENODEV;
127 }
128 BUGMSG(D_INIT_REASONS, "status after reset: %X\n", status);
129
130 /* Enable TX */
131 outb(0x39, _CONFIG);
132 outb(inb(ioaddr + 8), ioaddr + 7);
133
134 ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
135
136 status = ASTATUS();
137 BUGMSG(D_INIT_REASONS, "status after reset acknowledged: %X\n",
138 status);
139
140 /* Read first location of memory */
141 outb(0 | RDDATAflag | AUTOINCflag, _ADDR_HI);
142 outb(0, _ADDR_LO);
143
144 if ((status = inb(_MEMDATA)) != TESTvalue) {
145 BUGMSG(D_NORMAL, "Signature byte not found (%02Xh != D1h).\n",
146 status);
147 return -ENODEV;
148 }
149 return 0;
150 }
151
152 /* Set up the struct net_device associated with this card. Called after
153 * probing succeeds.
154 */
com20020_found(struct net_device * dev,int shared)155 int __devinit com20020_found(struct net_device *dev, int shared)
156 {
157 struct arcnet_local *lp;
158 int ioaddr = dev->base_addr;
159
160 /* Initialize the rest of the device structure. */
161
162 lp = (struct arcnet_local *) dev->priv;
163
164 lp->hw.command = com20020_command;
165 lp->hw.status = com20020_status;
166 lp->hw.intmask = com20020_setmask;
167 lp->hw.reset = com20020_reset;
168 lp->hw.open_close = com20020_openclose;
169 lp->hw.copy_to_card = com20020_copy_to_card;
170 lp->hw.copy_from_card = com20020_copy_from_card;
171
172 dev->set_multicast_list = com20020_set_mc_list;
173
174 /* Fill in the fields of the device structure with generic
175 * values.
176 */
177 arcdev_setup(dev);
178
179 if (!dev->dev_addr[0])
180 dev->dev_addr[0] = inb(ioaddr + 8); /* FIXME: do this some other way! */
181
182 SET_SUBADR(SUB_SETUP1);
183 outb(lp->setup, _XREG);
184
185 if (lp->card_flags & ARC_CAN_10MBIT)
186 {
187 SET_SUBADR(SUB_SETUP2);
188 outb(lp->setup2, _XREG);
189
190 /* must now write the magic "restart operation" command */
191 mdelay(1);
192 outb(0x18, _COMMAND);
193 }
194
195
196 lp->config = 0x20 | (lp->timeout << 3) | (lp->backplane << 2) | 1;
197 /* Default 0x38 + register: Node ID */
198 SETCONF;
199 outb(dev->dev_addr[0], _XREG);
200
201 /* reserve the irq */
202 if (request_irq(dev->irq, &arcnet_interrupt, shared,
203 "arcnet (COM20020)", dev)) {
204 BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
205 return -ENODEV;
206 }
207 /* reserve the I/O region */
208 if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) {
209 free_irq(dev->irq, dev);
210 return -EBUSY;
211 }
212 dev->base_addr = ioaddr;
213
214 BUGMSG(D_NORMAL, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
215 lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq);
216
217 if (lp->backplane)
218 BUGMSG(D_NORMAL, "Using backplane mode.\n");
219
220 if (lp->timeout != 3)
221 BUGMSG(D_NORMAL, "Using extended timeout value of %d.\n", lp->timeout);
222
223 BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n",
224 lp->setup >> 1,
225 clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]);
226
227 if (!dev->init && register_netdev(dev)) {
228 free_irq(dev->irq, dev);
229 release_region(ioaddr, ARCNET_TOTAL_SIZE);
230 return -EIO;
231 }
232 return 0;
233 }
234
235
236 /*
237 * Do a hardware reset on the card, and set up necessary registers.
238 *
239 * This should be called as little as possible, because it disrupts the
240 * token on the network (causes a RECON) and requires a significant delay.
241 *
242 * However, it does make sure the card is in a defined state.
243 */
com20020_reset(struct net_device * dev,int really_reset)244 static int com20020_reset(struct net_device *dev, int really_reset)
245 {
246 struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
247 short ioaddr = dev->base_addr;
248 u_char inbyte;
249
250 BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n",
251 dev->name, ASTATUS());
252
253 lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2);
254 /* power-up defaults */
255 SETCONF;
256
257 if (really_reset) {
258 /* reset the card */
259 ARCRESET;
260 mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */
261 }
262 /* clear flags & end reset */
263 ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
264
265 /* verify that the ARCnet signature byte is present */
266
267 com20020_copy_from_card(dev, 0, 0, &inbyte, 1);
268 if (inbyte != TESTvalue) {
269 BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
270 return 1;
271 }
272 /* enable extended (512-byte) packets */
273 ACOMMAND(CONFIGcmd | EXTconf);
274
275 /* done! return success. */
276 return 0;
277 }
278
279
com20020_setmask(struct net_device * dev,int mask)280 static void com20020_setmask(struct net_device *dev, int mask)
281 {
282 short ioaddr = dev->base_addr;
283 AINTMASK(mask);
284 }
285
286
com20020_command(struct net_device * dev,int cmd)287 static void com20020_command(struct net_device *dev, int cmd)
288 {
289 short ioaddr = dev->base_addr;
290 ACOMMAND(cmd);
291 }
292
293
com20020_status(struct net_device * dev)294 static int com20020_status(struct net_device *dev)
295 {
296 short ioaddr = dev->base_addr;
297 return ASTATUS();
298 }
299
300
com20020_openclose(struct net_device * dev,bool open)301 static void com20020_openclose(struct net_device *dev, bool open)
302 {
303 struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
304 int ioaddr = dev->base_addr;
305
306 if (open)
307 MOD_INC_USE_COUNT;
308 else {
309 /* disable transmitter */
310 lp->config &= ~TXENcfg;
311 SETCONF;
312 MOD_DEC_USE_COUNT;
313 }
314 lp->hw.open_close_ll(dev, open);
315 }
316
317
318 /* Set or clear the multicast filter for this adaptor.
319 * num_addrs == -1 Promiscuous mode, receive all packets
320 * num_addrs == 0 Normal mode, clear multicast list
321 * num_addrs > 0 Multicast mode, receive normal and MC packets, and do
322 * best-effort filtering.
323 * FIXME - do multicast stuff, not just promiscuous.
324 */
com20020_set_mc_list(struct net_device * dev)325 static void com20020_set_mc_list(struct net_device *dev)
326 {
327 struct arcnet_local *lp = dev->priv;
328 int ioaddr = dev->base_addr;
329
330 if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */
331 if (!(lp->setup & PROMISCset))
332 BUGMSG(D_NORMAL, "Setting promiscuous flag...\n");
333 SET_SUBADR(SUB_SETUP1);
334 lp->setup |= PROMISCset;
335 outb(lp->setup, _XREG);
336 } else
337 /* Disable promiscuous mode, use normal mode */
338 {
339 if ((lp->setup & PROMISCset))
340 BUGMSG(D_NORMAL, "Resetting promiscuous flag...\n");
341 SET_SUBADR(SUB_SETUP1);
342 lp->setup &= ~PROMISCset;
343 outb(lp->setup, _XREG);
344 }
345 }
346
com20020_remove(struct net_device * dev)347 void __devexit com20020_remove(struct net_device *dev)
348 {
349 unregister_netdev(dev);
350 free_irq(dev->irq, dev);
351 release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
352 kfree(dev->priv);
353 kfree(dev);
354 }
355
356 #ifdef MODULE
357
358 EXPORT_SYMBOL(com20020_check);
359 EXPORT_SYMBOL(com20020_found);
360 EXPORT_SYMBOL(com20020_remove);
361
362 MODULE_LICENSE("GPL");
363
init_module(void)364 int init_module(void)
365 {
366 BUGLVL(D_NORMAL) printk(VERSION);
367 return 0;
368 }
369
cleanup_module(void)370 void cleanup_module(void)
371 {
372 }
373
374 #endif /* MODULE */
375