xref: /OK3568_Linux_fs/kernel/drivers/net/arcnet/arc-rimi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Linux ARCnet driver - "RIM I" (entirely mem-mapped) cards
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Written 1994-1999 by Avery Pennarun.
5*4882a593Smuzhiyun  * Written 1999-2000 by Martin Mares <mj@ucw.cz>.
6*4882a593Smuzhiyun  * Derived from skeleton.c by Donald Becker.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
9*4882a593Smuzhiyun  *  for sponsoring the further development of this driver.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * **********************
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * The original copyright of skeleton.c was as follows:
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * skeleton.c Written 1993 by Donald Becker.
16*4882a593Smuzhiyun  * Copyright 1993 United States Government as represented by the
17*4882a593Smuzhiyun  * Director, National Security Agency.  This software may only be used
18*4882a593Smuzhiyun  * and distributed according to the terms of the GNU General Public License as
19*4882a593Smuzhiyun  * modified by SRC, incorporated herein by reference.
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * **********************
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  * For more details, see drivers/net/arcnet.c
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * **********************
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include <linux/kernel.h>
31*4882a593Smuzhiyun #include <linux/module.h>
32*4882a593Smuzhiyun #include <linux/moduleparam.h>
33*4882a593Smuzhiyun #include <linux/ioport.h>
34*4882a593Smuzhiyun #include <linux/delay.h>
35*4882a593Smuzhiyun #include <linux/netdevice.h>
36*4882a593Smuzhiyun #include <linux/memblock.h>
37*4882a593Smuzhiyun #include <linux/init.h>
38*4882a593Smuzhiyun #include <linux/interrupt.h>
39*4882a593Smuzhiyun #include <linux/io.h>
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #include "arcdevice.h"
42*4882a593Smuzhiyun #include "com9026.h"
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun /* Internal function declarations */
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun static int arcrimi_probe(struct net_device *dev);
47*4882a593Smuzhiyun static int arcrimi_found(struct net_device *dev);
48*4882a593Smuzhiyun static void arcrimi_command(struct net_device *dev, int command);
49*4882a593Smuzhiyun static int arcrimi_status(struct net_device *dev);
50*4882a593Smuzhiyun static void arcrimi_setmask(struct net_device *dev, int mask);
51*4882a593Smuzhiyun static int arcrimi_reset(struct net_device *dev, int really_reset);
52*4882a593Smuzhiyun static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
53*4882a593Smuzhiyun 				 void *buf, int count);
54*4882a593Smuzhiyun static void arcrimi_copy_from_card(struct net_device *dev, int bufnum,
55*4882a593Smuzhiyun 				   int offset, void *buf, int count);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /* Handy defines for ARCnet specific stuff */
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun /* Amount of I/O memory used by the card */
60*4882a593Smuzhiyun #define BUFFER_SIZE	(512)
61*4882a593Smuzhiyun #define MIRROR_SIZE	(BUFFER_SIZE * 4)
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun /* We cannot probe for a RIM I card; one reason is I don't know how to reset
64*4882a593Smuzhiyun  * them.  In fact, we can't even get their node ID automatically.  So, we
65*4882a593Smuzhiyun  * need to be passed a specific shmem address, IRQ, and node ID.
66*4882a593Smuzhiyun  */
arcrimi_probe(struct net_device * dev)67*4882a593Smuzhiyun static int __init arcrimi_probe(struct net_device *dev)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun 	if (BUGLVL(D_NORMAL)) {
70*4882a593Smuzhiyun 		pr_info("%s\n", "RIM I (entirely mem-mapped) support");
71*4882a593Smuzhiyun 		pr_info("E-mail me if you actually test the RIM I driver, please!\n");
72*4882a593Smuzhiyun 		pr_info("Given: node %02Xh, shmem %lXh, irq %d\n",
73*4882a593Smuzhiyun 			dev->dev_addr[0], dev->mem_start, dev->irq);
74*4882a593Smuzhiyun 	}
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	if (dev->mem_start <= 0 || dev->irq <= 0) {
77*4882a593Smuzhiyun 		if (BUGLVL(D_NORMAL))
78*4882a593Smuzhiyun 			pr_err("No autoprobe for RIM I; you must specify the shmem and irq!\n");
79*4882a593Smuzhiyun 		return -ENODEV;
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun 	if (dev->dev_addr[0] == 0) {
82*4882a593Smuzhiyun 		if (BUGLVL(D_NORMAL))
83*4882a593Smuzhiyun 			pr_err("You need to specify your card's station ID!\n");
84*4882a593Smuzhiyun 		return -ENODEV;
85*4882a593Smuzhiyun 	}
86*4882a593Smuzhiyun 	/* Grab the memory region at mem_start for MIRROR_SIZE bytes.
87*4882a593Smuzhiyun 	 * Later in arcrimi_found() the real size will be determined
88*4882a593Smuzhiyun 	 * and this reserve will be released and the correct size
89*4882a593Smuzhiyun 	 * will be taken.
90*4882a593Smuzhiyun 	 */
91*4882a593Smuzhiyun 	if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) {
92*4882a593Smuzhiyun 		if (BUGLVL(D_NORMAL))
93*4882a593Smuzhiyun 			pr_notice("Card memory already allocated\n");
94*4882a593Smuzhiyun 		return -ENODEV;
95*4882a593Smuzhiyun 	}
96*4882a593Smuzhiyun 	return arcrimi_found(dev);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
check_mirror(unsigned long addr,size_t size)99*4882a593Smuzhiyun static int check_mirror(unsigned long addr, size_t size)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	void __iomem *p;
102*4882a593Smuzhiyun 	int res = -1;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	if (!request_mem_region(addr, size, "arcnet (90xx)"))
105*4882a593Smuzhiyun 		return -1;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	p = ioremap(addr, size);
108*4882a593Smuzhiyun 	if (p) {
109*4882a593Smuzhiyun 		if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue)
110*4882a593Smuzhiyun 			res = 1;
111*4882a593Smuzhiyun 		else
112*4882a593Smuzhiyun 			res = 0;
113*4882a593Smuzhiyun 		iounmap(p);
114*4882a593Smuzhiyun 	}
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	release_mem_region(addr, size);
117*4882a593Smuzhiyun 	return res;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun /* Set up the struct net_device associated with this card.
121*4882a593Smuzhiyun  * Called after probing succeeds.
122*4882a593Smuzhiyun  */
arcrimi_found(struct net_device * dev)123*4882a593Smuzhiyun static int __init arcrimi_found(struct net_device *dev)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	struct arcnet_local *lp;
126*4882a593Smuzhiyun 	unsigned long first_mirror, last_mirror, shmem;
127*4882a593Smuzhiyun 	void __iomem *p;
128*4882a593Smuzhiyun 	int mirror_size;
129*4882a593Smuzhiyun 	int err;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	p = ioremap(dev->mem_start, MIRROR_SIZE);
132*4882a593Smuzhiyun 	if (!p) {
133*4882a593Smuzhiyun 		release_mem_region(dev->mem_start, MIRROR_SIZE);
134*4882a593Smuzhiyun 		arc_printk(D_NORMAL, dev, "Can't ioremap\n");
135*4882a593Smuzhiyun 		return -ENODEV;
136*4882a593Smuzhiyun 	}
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	/* reserve the irq */
139*4882a593Smuzhiyun 	if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (RIM I)", dev)) {
140*4882a593Smuzhiyun 		iounmap(p);
141*4882a593Smuzhiyun 		release_mem_region(dev->mem_start, MIRROR_SIZE);
142*4882a593Smuzhiyun 		arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
143*4882a593Smuzhiyun 		return -ENODEV;
144*4882a593Smuzhiyun 	}
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	shmem = dev->mem_start;
147*4882a593Smuzhiyun 	arcnet_writeb(TESTvalue, p, COM9026_REG_W_INTMASK);
148*4882a593Smuzhiyun 	arcnet_writeb(TESTvalue, p, COM9026_REG_W_COMMAND);
149*4882a593Smuzhiyun 					/* actually the station/node ID */
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	/* find the real shared memory start/end points, including mirrors */
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	/* guess the actual size of one "memory mirror" - the number of
154*4882a593Smuzhiyun 	 * bytes between copies of the shared memory.  On most cards, it's
155*4882a593Smuzhiyun 	 * 2k (or there are no mirrors at all) but on some, it's 4k.
156*4882a593Smuzhiyun 	 */
157*4882a593Smuzhiyun 	mirror_size = MIRROR_SIZE;
158*4882a593Smuzhiyun 	if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue &&
159*4882a593Smuzhiyun 	    check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 &&
160*4882a593Smuzhiyun 	    check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1)
161*4882a593Smuzhiyun 		mirror_size = 2 * MIRROR_SIZE;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	first_mirror = shmem - mirror_size;
164*4882a593Smuzhiyun 	while (check_mirror(first_mirror, mirror_size) == 1)
165*4882a593Smuzhiyun 		first_mirror -= mirror_size;
166*4882a593Smuzhiyun 	first_mirror += mirror_size;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	last_mirror = shmem + mirror_size;
169*4882a593Smuzhiyun 	while (check_mirror(last_mirror, mirror_size) == 1)
170*4882a593Smuzhiyun 		last_mirror += mirror_size;
171*4882a593Smuzhiyun 	last_mirror -= mirror_size;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	dev->mem_start = first_mirror;
174*4882a593Smuzhiyun 	dev->mem_end = last_mirror + MIRROR_SIZE - 1;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	/* initialize the rest of the device structure. */
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	lp = netdev_priv(dev);
179*4882a593Smuzhiyun 	lp->card_name = "RIM I";
180*4882a593Smuzhiyun 	lp->hw.command = arcrimi_command;
181*4882a593Smuzhiyun 	lp->hw.status = arcrimi_status;
182*4882a593Smuzhiyun 	lp->hw.intmask = arcrimi_setmask;
183*4882a593Smuzhiyun 	lp->hw.reset = arcrimi_reset;
184*4882a593Smuzhiyun 	lp->hw.owner = THIS_MODULE;
185*4882a593Smuzhiyun 	lp->hw.copy_to_card = arcrimi_copy_to_card;
186*4882a593Smuzhiyun 	lp->hw.copy_from_card = arcrimi_copy_from_card;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/* re-reserve the memory region - arcrimi_probe() alloced this reqion
189*4882a593Smuzhiyun 	 * but didn't know the real size.  Free that region and then re-get
190*4882a593Smuzhiyun 	 * with the correct size.  There is a VERY slim chance this could
191*4882a593Smuzhiyun 	 * fail.
192*4882a593Smuzhiyun 	 */
193*4882a593Smuzhiyun 	iounmap(p);
194*4882a593Smuzhiyun 	release_mem_region(shmem, MIRROR_SIZE);
195*4882a593Smuzhiyun 	if (!request_mem_region(dev->mem_start,
196*4882a593Smuzhiyun 				dev->mem_end - dev->mem_start + 1,
197*4882a593Smuzhiyun 				"arcnet (90xx)")) {
198*4882a593Smuzhiyun 		arc_printk(D_NORMAL, dev, "Card memory already allocated\n");
199*4882a593Smuzhiyun 		goto err_free_irq;
200*4882a593Smuzhiyun 	}
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	lp->mem_start = ioremap(dev->mem_start,
203*4882a593Smuzhiyun 				dev->mem_end - dev->mem_start + 1);
204*4882a593Smuzhiyun 	if (!lp->mem_start) {
205*4882a593Smuzhiyun 		arc_printk(D_NORMAL, dev, "Can't remap device memory!\n");
206*4882a593Smuzhiyun 		goto err_release_mem;
207*4882a593Smuzhiyun 	}
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	/* get and check the station ID from offset 1 in shmem */
210*4882a593Smuzhiyun 	dev->dev_addr[0] = arcnet_readb(lp->mem_start, COM9026_REG_R_STATION);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	arc_printk(D_NORMAL, dev, "ARCnet RIM I: station %02Xh found at IRQ %d, ShMem %lXh (%ld*%d bytes)\n",
213*4882a593Smuzhiyun 		   dev->dev_addr[0],
214*4882a593Smuzhiyun 		   dev->irq, dev->mem_start,
215*4882a593Smuzhiyun 		   (dev->mem_end - dev->mem_start + 1) / mirror_size,
216*4882a593Smuzhiyun 		   mirror_size);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	err = register_netdev(dev);
219*4882a593Smuzhiyun 	if (err)
220*4882a593Smuzhiyun 		goto err_unmap;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	return 0;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun err_unmap:
225*4882a593Smuzhiyun 	iounmap(lp->mem_start);
226*4882a593Smuzhiyun err_release_mem:
227*4882a593Smuzhiyun 	release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
228*4882a593Smuzhiyun err_free_irq:
229*4882a593Smuzhiyun 	free_irq(dev->irq, dev);
230*4882a593Smuzhiyun 	return -EIO;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun /* Do a hardware reset on the card, and set up necessary registers.
234*4882a593Smuzhiyun  *
235*4882a593Smuzhiyun  * This should be called as little as possible, because it disrupts the
236*4882a593Smuzhiyun  * token on the network (causes a RECON) and requires a significant delay.
237*4882a593Smuzhiyun  *
238*4882a593Smuzhiyun  * However, it does make sure the card is in a defined state.
239*4882a593Smuzhiyun  */
arcrimi_reset(struct net_device * dev,int really_reset)240*4882a593Smuzhiyun static int arcrimi_reset(struct net_device *dev, int really_reset)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	struct arcnet_local *lp = netdev_priv(dev);
243*4882a593Smuzhiyun 	void __iomem *ioaddr = lp->mem_start + 0x800;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n",
246*4882a593Smuzhiyun 		   dev->name, arcnet_readb(ioaddr, COM9026_REG_R_STATUS));
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (really_reset) {
249*4882a593Smuzhiyun 		arcnet_writeb(TESTvalue, ioaddr, -0x800);	/* fake reset */
250*4882a593Smuzhiyun 		return 0;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 	/* clear flags & end reset */
253*4882a593Smuzhiyun 	arcnet_writeb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND);
254*4882a593Smuzhiyun 	arcnet_writeb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND);
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	/* enable extended (512-byte) packets */
257*4882a593Smuzhiyun 	arcnet_writeb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	/* done!  return success. */
260*4882a593Smuzhiyun 	return 0;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
arcrimi_setmask(struct net_device * dev,int mask)263*4882a593Smuzhiyun static void arcrimi_setmask(struct net_device *dev, int mask)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun 	struct arcnet_local *lp = netdev_priv(dev);
266*4882a593Smuzhiyun 	void __iomem *ioaddr = lp->mem_start + 0x800;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	arcnet_writeb(mask, ioaddr, COM9026_REG_W_INTMASK);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
arcrimi_status(struct net_device * dev)271*4882a593Smuzhiyun static int arcrimi_status(struct net_device *dev)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun 	struct arcnet_local *lp = netdev_priv(dev);
274*4882a593Smuzhiyun 	void __iomem *ioaddr = lp->mem_start + 0x800;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	return arcnet_readb(ioaddr, COM9026_REG_R_STATUS);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
arcrimi_command(struct net_device * dev,int cmd)279*4882a593Smuzhiyun static void arcrimi_command(struct net_device *dev, int cmd)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	struct arcnet_local *lp = netdev_priv(dev);
282*4882a593Smuzhiyun 	void __iomem *ioaddr = lp->mem_start + 0x800;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	arcnet_writeb(cmd, ioaddr, COM9026_REG_W_COMMAND);
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun 
arcrimi_copy_to_card(struct net_device * dev,int bufnum,int offset,void * buf,int count)287*4882a593Smuzhiyun static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
288*4882a593Smuzhiyun 				 void *buf, int count)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun 	struct arcnet_local *lp = netdev_priv(dev);
291*4882a593Smuzhiyun 	void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count));
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun 
arcrimi_copy_from_card(struct net_device * dev,int bufnum,int offset,void * buf,int count)296*4882a593Smuzhiyun static void arcrimi_copy_from_card(struct net_device *dev, int bufnum,
297*4882a593Smuzhiyun 				   int offset, void *buf, int count)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun 	struct arcnet_local *lp = netdev_priv(dev);
300*4882a593Smuzhiyun 	void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun static int node;
306*4882a593Smuzhiyun static int io;			/* use the insmod io= irq= node= options */
307*4882a593Smuzhiyun static int irq;
308*4882a593Smuzhiyun static char device[9];		/* use eg. device=arc1 to change name */
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun module_param(node, int, 0);
311*4882a593Smuzhiyun module_param(io, int, 0);
312*4882a593Smuzhiyun module_param(irq, int, 0);
313*4882a593Smuzhiyun module_param_string(device, device, sizeof(device), 0);
314*4882a593Smuzhiyun MODULE_LICENSE("GPL");
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun static struct net_device *my_dev;
317*4882a593Smuzhiyun 
arc_rimi_init(void)318*4882a593Smuzhiyun static int __init arc_rimi_init(void)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	struct net_device *dev;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	dev = alloc_arcdev(device);
323*4882a593Smuzhiyun 	if (!dev)
324*4882a593Smuzhiyun 		return -ENOMEM;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	if (node && node != 0xff)
327*4882a593Smuzhiyun 		dev->dev_addr[0] = node;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	dev->mem_start = io;
330*4882a593Smuzhiyun 	dev->irq = irq;
331*4882a593Smuzhiyun 	if (dev->irq == 2)
332*4882a593Smuzhiyun 		dev->irq = 9;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	if (arcrimi_probe(dev)) {
335*4882a593Smuzhiyun 		free_arcdev(dev);
336*4882a593Smuzhiyun 		return -EIO;
337*4882a593Smuzhiyun 	}
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	my_dev = dev;
340*4882a593Smuzhiyun 	return 0;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun 
arc_rimi_exit(void)343*4882a593Smuzhiyun static void __exit arc_rimi_exit(void)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun 	struct net_device *dev = my_dev;
346*4882a593Smuzhiyun 	struct arcnet_local *lp = netdev_priv(dev);
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	unregister_netdev(dev);
349*4882a593Smuzhiyun 	iounmap(lp->mem_start);
350*4882a593Smuzhiyun 	release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
351*4882a593Smuzhiyun 	free_irq(dev->irq, dev);
352*4882a593Smuzhiyun 	free_arcdev(dev);
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun #ifndef MODULE
arcrimi_setup(char * s)356*4882a593Smuzhiyun static int __init arcrimi_setup(char *s)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 	int ints[8];
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	s = get_options(s, 8, ints);
361*4882a593Smuzhiyun 	if (!ints[0])
362*4882a593Smuzhiyun 		return 1;
363*4882a593Smuzhiyun 	switch (ints[0]) {
364*4882a593Smuzhiyun 	default:		/* ERROR */
365*4882a593Smuzhiyun 		pr_err("Too many arguments\n");
366*4882a593Smuzhiyun 		fallthrough;
367*4882a593Smuzhiyun 	case 3:		/* Node ID */
368*4882a593Smuzhiyun 		node = ints[3];
369*4882a593Smuzhiyun 		fallthrough;
370*4882a593Smuzhiyun 	case 2:		/* IRQ */
371*4882a593Smuzhiyun 		irq = ints[2];
372*4882a593Smuzhiyun 		fallthrough;
373*4882a593Smuzhiyun 	case 1:		/* IO address */
374*4882a593Smuzhiyun 		io = ints[1];
375*4882a593Smuzhiyun 	}
376*4882a593Smuzhiyun 	if (*s)
377*4882a593Smuzhiyun 		snprintf(device, sizeof(device), "%s", s);
378*4882a593Smuzhiyun 	return 1;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun __setup("arcrimi=", arcrimi_setup);
381*4882a593Smuzhiyun #endif				/* MODULE */
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun module_init(arc_rimi_init)
384*4882a593Smuzhiyun module_exit(arc_rimi_exit)
385