• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/net/arcnet/
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
45static int com90io_found(struct net_device *dev);
46static void com90io_command(struct net_device *dev, int command);
47static int com90io_status(struct net_device *dev);
48static void com90io_setmask(struct net_device *dev, int mask);
49static int com90io_reset(struct net_device *dev, int really_reset);
50static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset,
51				 void *buf, int count);
52static 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
90static 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
101static 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
114static 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
129static 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 */
148static 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 ((int)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
224err_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 */
233static 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 */
290static 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
322static void com90io_command(struct net_device *dev, int cmd)
323{
324	short ioaddr = dev->base_addr;
325
326	ACOMMAND(cmd);
327}
328
329
330static int com90io_status(struct net_device *dev)
331{
332	short ioaddr = dev->base_addr;
333
334	return ASTATUS();
335}
336
337
338static void com90io_setmask(struct net_device *dev, int mask)
339{
340	short ioaddr = dev->base_addr;
341
342	AINTMASK(mask);
343}
344
345static 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
352static 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
358static int io;			/* use the insmod io= irq= shmem= options */
359static int irq;
360static char device[9];		/* use eg. device=arc1 to change name */
361
362module_param(io, int, 0);
363module_param(irq, int, 0);
364module_param_string(device, device, sizeof(device), 0);
365MODULE_LICENSE("GPL");
366
367#ifndef MODULE
368static 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
389static struct net_device *my_dev;
390
391static 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
416static 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
431module_init(com90io_init)
432module_exit(com90io_exit)
433