1 /*
2  * Linux ARCnet driver - COM20020 PCI support
3  * Contemporary Controls PCI20 and SOHARD SH-ARC PCI
4  *
5  * Written 1994-1999 by Avery Pennarun,
6  *    based on an ISA version by David Woodhouse.
7  * Written 1999-2000 by Martin Mares <mj@ucw.cz>.
8  * Derived from skeleton.c by Donald Becker.
9  *
10  * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
11  *  for sponsoring the further development of this driver.
12  *
13  * **********************
14  *
15  * The original copyright of skeleton.c was as follows:
16  *
17  * skeleton.c Written 1993 by Donald Becker.
18  * Copyright 1993 United States Government as represented by the
19  * Director, National Security Agency.  This software may only be used
20  * and distributed according to the terms of the GNU General Public License as
21  * modified by SRC, incorporated herein by reference.
22  *
23  * **********************
24  *
25  * For more details, see drivers/net/arcnet.c
26  *
27  * **********************
28  */
29 #include <linux/module.h>
30 #include <linux/moduleparam.h>
31 #include <linux/kernel.h>
32 #include <linux/types.h>
33 #include <linux/ioport.h>
34 #include <linux/errno.h>
35 #include <linux/netdevice.h>
36 #include <linux/init.h>
37 #include <linux/interrupt.h>
38 #include <linux/pci.h>
39 #include <linux/arcdevice.h>
40 #include <linux/com20020.h>
41 #include <linux/list.h>
42 
43 #include <asm/io.h>
44 
45 
46 #define VERSION "arcnet: COM20020 PCI support\n"
47 
48 /* Module parameters */
49 
50 static int node;
51 static char device[9];		/* use eg. device="arc1" to change name */
52 static int timeout = 3;
53 static int backplane;
54 static int clockp;
55 static int clockm;
56 
57 module_param(node, int, 0);
58 module_param_string(device, device, sizeof(device), 0);
59 module_param(timeout, int, 0);
60 module_param(backplane, int, 0);
61 module_param(clockp, int, 0);
62 module_param(clockm, int, 0);
63 MODULE_LICENSE("GPL");
64 
65 static void com20020pci_remove(struct pci_dev *pdev);
66 
67 static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
68 {
69 	struct com20020_pci_card_info *ci;
70 	struct net_device *dev;
71 	struct arcnet_local *lp;
72 	struct com20020_priv *priv;
73 	int i, ioaddr, ret;
74 	struct resource *r;
75 
76 	if (pci_enable_device(pdev))
77 		return -EIO;
78 
79 	priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv),
80 			    GFP_KERNEL);
81 	if (!priv)
82 		return -ENOMEM;
83 
84 	ci = (struct com20020_pci_card_info *)id->driver_data;
85 	priv->ci = ci;
86 
87 	INIT_LIST_HEAD(&priv->list_dev);
88 
89 
90 	for (i = 0; i < ci->devcount; i++) {
91 		struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
92 		struct com20020_dev *card;
93 
94 		dev = alloc_arcdev(device);
95 		if (!dev) {
96 			ret = -ENOMEM;
97 			goto out_port;
98 		}
99 
100 		dev->netdev_ops = &com20020_netdev_ops;
101 
102 		lp = netdev_priv(dev);
103 
104 		BUGMSG(D_NORMAL, "%s Controls\n", ci->name);
105 		ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
106 
107 		r = devm_request_region(&pdev->dev, ioaddr, cm->size,
108 					"com20020-pci");
109 		if (!r) {
110 			pr_err("IO region %xh-%xh already allocated.\n",
111 			       ioaddr, ioaddr + cm->size - 1);
112 			ret = -EBUSY;
113 			goto out_port;
114 		}
115 
116 		/* Dummy access after Reset
117 		 * ARCNET controller needs
118 		 * this access to detect bustype
119 		 */
120 		outb(0x00, ioaddr + 1);
121 		inb(ioaddr + 1);
122 
123 		dev->base_addr = ioaddr;
124 		dev->dev_addr[0] = node;
125 		dev->irq = pdev->irq;
126 		lp->card_name = "PCI COM20020";
127 		lp->card_flags = ci->flags;
128 		lp->backplane = backplane;
129 		lp->clockp = clockp & 7;
130 		lp->clockm = clockm & 3;
131 		lp->timeout = timeout;
132 		lp->hw.owner = THIS_MODULE;
133 
134 		if (ASTATUS() == 0xFF) {
135 			pr_err("IO address %Xh is empty!\n", ioaddr);
136 			ret = -EIO;
137 			goto out_port;
138 		}
139 		if (com20020_check(dev)) {
140 			ret = -EIO;
141 			goto out_port;
142 		}
143 
144 		card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
145 				    GFP_KERNEL);
146 		if (!card) {
147 			pr_err("%s out of memory!\n", __func__);
148 			return -ENOMEM;
149 		}
150 
151 		card->index = i;
152 		card->pci_priv = priv;
153 		card->dev = dev;
154 
155 		dev_set_drvdata(&dev->dev, card);
156 
157 		ret = com20020_found(dev, IRQF_SHARED);
158 		if (ret)
159 			goto out_port;
160 
161 		list_add(&card->list, &priv->list_dev);
162 	}
163 
164 	pci_set_drvdata(pdev, priv);
165 
166 	return 0;
167 
168 out_port:
169 	com20020pci_remove(pdev);
170 	return ret;
171 }
172 
173 static void com20020pci_remove(struct pci_dev *pdev)
174 {
175 	struct com20020_dev *card, *tmpcard;
176 	struct com20020_priv *priv;
177 
178 	priv = pci_get_drvdata(pdev);
179 
180 	list_for_each_entry_safe(card, tmpcard, &priv->list_dev, list) {
181 		struct net_device *dev = card->dev;
182 
183 		unregister_netdev(dev);
184 		free_irq(dev->irq, dev);
185 		free_netdev(dev);
186 	}
187 }
188 
189 static struct com20020_pci_card_info card_info_10mbit = {
190 	.name = "ARC-PCI",
191 	.devcount = 1,
192 	.chan_map_tbl = {
193 		{ 2, 0x00, 0x08 },
194 	},
195 	.flags = ARC_CAN_10MBIT,
196 };
197 
198 static struct com20020_pci_card_info card_info_5mbit = {
199 	.name = "ARC-PCI",
200 	.devcount = 1,
201 	.chan_map_tbl = {
202 		{ 2, 0x00, 0x08 },
203 	},
204 	.flags = ARC_IS_5MBIT,
205 };
206 
207 static struct com20020_pci_card_info card_info_sohard = {
208 	.name = "PLX-PCI",
209 	.devcount = 1,
210 	/* SOHARD needs PCI base addr 4 */
211 	.chan_map_tbl = {
212 		{4, 0x00, 0x08},
213 	},
214 	.flags = ARC_CAN_10MBIT,
215 };
216 
217 static struct com20020_pci_card_info card_info_eae_arc1 = {
218 	.name = "EAE PLX-PCI ARC1",
219 	.devcount = 1,
220 	.chan_map_tbl = {
221 		{ 2, 0x00, 0x08 },
222 	},
223 	.flags = ARC_CAN_10MBIT,
224 };
225 
226 static struct com20020_pci_card_info card_info_eae_ma1 = {
227 	.name = "EAE PLX-PCI MA1",
228 	.devcount = 2,
229 	.chan_map_tbl = {
230 		{ 2, 0x00, 0x08 },
231 		{ 2, 0x08, 0x08 }
232 	},
233 	.flags = ARC_CAN_10MBIT,
234 };
235 
236 static const struct pci_device_id com20020pci_id_table[] = {
237 	{
238 		0x1571, 0xa001,
239 		PCI_ANY_ID, PCI_ANY_ID,
240 		0, 0,
241 		0,
242 	},
243 	{
244 		0x1571, 0xa002,
245 		PCI_ANY_ID, PCI_ANY_ID,
246 		0, 0,
247 		0,
248 	},
249 	{
250 		0x1571, 0xa003,
251 		PCI_ANY_ID, PCI_ANY_ID,
252 		0, 0,
253 		0
254 	},
255 	{
256 		0x1571, 0xa004,
257 		PCI_ANY_ID, PCI_ANY_ID,
258 		0, 0,
259 		0,
260 	},
261 	{
262 		0x1571, 0xa005,
263 		PCI_ANY_ID, PCI_ANY_ID,
264 		0, 0,
265 		0
266 	},
267 	{
268 		0x1571, 0xa006,
269 		PCI_ANY_ID, PCI_ANY_ID,
270 		0, 0,
271 		0
272 	},
273 	{
274 		0x1571, 0xa007,
275 		PCI_ANY_ID, PCI_ANY_ID,
276 		0, 0,
277 		0
278 	},
279 	{
280 		0x1571, 0xa008,
281 		PCI_ANY_ID, PCI_ANY_ID,
282 		0, 0,
283 		0
284 	},
285 	{
286 		0x1571, 0xa009,
287 		PCI_ANY_ID, PCI_ANY_ID,
288 		0, 0,
289 		(kernel_ulong_t)&card_info_5mbit
290 	},
291 	{
292 		0x1571, 0xa00a,
293 		PCI_ANY_ID, PCI_ANY_ID,
294 		0, 0,
295 		(kernel_ulong_t)&card_info_5mbit
296 	},
297 	{
298 		0x1571, 0xa00b,
299 		PCI_ANY_ID, PCI_ANY_ID,
300 		0, 0,
301 		(kernel_ulong_t)&card_info_5mbit
302 	},
303 	{
304 		0x1571, 0xa00c,
305 		PCI_ANY_ID, PCI_ANY_ID,
306 		0, 0,
307 		(kernel_ulong_t)&card_info_5mbit
308 	},
309 	{
310 		0x1571, 0xa00d,
311 		PCI_ANY_ID, PCI_ANY_ID,
312 		0, 0,
313 		(kernel_ulong_t)&card_info_5mbit
314 	},
315 	{
316 		0x1571, 0xa00e,
317 		PCI_ANY_ID, PCI_ANY_ID,
318 		0, 0,
319 		(kernel_ulong_t)&card_info_5mbit
320 	},
321 	{
322 		0x1571, 0xa201,
323 		PCI_ANY_ID, PCI_ANY_ID,
324 		0, 0,
325 		(kernel_ulong_t)&card_info_10mbit
326 	},
327 	{
328 		0x1571, 0xa202,
329 		PCI_ANY_ID, PCI_ANY_ID,
330 		0, 0,
331 		(kernel_ulong_t)&card_info_10mbit
332 	},
333 	{
334 		0x1571, 0xa203,
335 		PCI_ANY_ID, PCI_ANY_ID,
336 		0, 0,
337 		(kernel_ulong_t)&card_info_10mbit
338 	},
339 	{
340 		0x1571, 0xa204,
341 		PCI_ANY_ID, PCI_ANY_ID,
342 		0, 0,
343 		(kernel_ulong_t)&card_info_10mbit
344 	},
345 	{
346 		0x1571, 0xa205,
347 		PCI_ANY_ID, PCI_ANY_ID,
348 		0, 0,
349 		(kernel_ulong_t)&card_info_10mbit
350 	},
351 	{
352 		0x1571, 0xa206,
353 		PCI_ANY_ID, PCI_ANY_ID,
354 		0, 0,
355 		(kernel_ulong_t)&card_info_10mbit
356 	},
357 	{
358 		0x10B5, 0x9030,
359 		0x10B5, 0x2978,
360 		0, 0,
361 		(kernel_ulong_t)&card_info_sohard
362 	},
363 	{
364 		0x10B5, 0x9050,
365 		0x10B5, 0x2273,
366 		0, 0,
367 		(kernel_ulong_t)&card_info_sohard
368 	},
369 	{
370 		0x10B5, 0x9050,
371 		0x10B5, 0x3263,
372 		0, 0,
373 		(kernel_ulong_t)&card_info_eae_arc1
374 	},
375 	{
376 		0x10B5, 0x9050,
377 		0x10B5, 0x3292,
378 		0, 0,
379 		(kernel_ulong_t)&card_info_eae_ma1
380 	},
381 	{
382 		0x14BA, 0x6000,
383 		PCI_ANY_ID, PCI_ANY_ID,
384 		0, 0,
385 		(kernel_ulong_t)&card_info_10mbit
386 	},
387 	{
388 		0x10B5, 0x2200,
389 		PCI_ANY_ID, PCI_ANY_ID,
390 		0, 0,
391 		(kernel_ulong_t)&card_info_10mbit
392 	},
393 	{ 0, }
394 };
395 
396 MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
397 
398 static struct pci_driver com20020pci_driver = {
399 	.name		= "com20020",
400 	.id_table	= com20020pci_id_table,
401 	.probe		= com20020pci_probe,
402 	.remove		= com20020pci_remove,
403 };
404 
405 static int __init com20020pci_init(void)
406 {
407 	BUGLVL(D_NORMAL) printk(VERSION);
408 	return pci_register_driver(&com20020pci_driver);
409 }
410 
411 static void __exit com20020pci_cleanup(void)
412 {
413 	pci_unregister_driver(&com20020pci_driver);
414 }
415 
416 module_init(com20020pci_init)
417 module_exit(com20020pci_cleanup)
418