com20020-pci.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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. #include <asm/io.h>
  43. #define VERSION "arcnet: COM20020 PCI support\n"
  44. /* Module parameters */
  45. static int node;
  46. static char device[9]; /* use eg. device="arc1" to change name */
  47. static int timeout = 3;
  48. static int backplane;
  49. static int clockp;
  50. static int clockm;
  51. module_param(node, int, 0);
  52. module_param_string(device, device, sizeof(device), 0);
  53. module_param(timeout, int, 0);
  54. module_param(backplane, int, 0);
  55. module_param(clockp, int, 0);
  56. module_param(clockm, int, 0);
  57. MODULE_LICENSE("GPL");
  58. static void com20020pci_remove(struct pci_dev *pdev);
  59. static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  60. {
  61. struct com20020_pci_card_info *ci;
  62. struct net_device *dev;
  63. struct arcnet_local *lp;
  64. struct com20020_priv *priv;
  65. int i, ioaddr, ret;
  66. struct resource *r;
  67. if (pci_enable_device(pdev))
  68. return -EIO;
  69. priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv),
  70. GFP_KERNEL);
  71. if (!priv)
  72. return -ENOMEM;
  73. ci = (struct com20020_pci_card_info *)id->driver_data;
  74. priv->ci = ci;
  75. INIT_LIST_HEAD(&priv->list_dev);
  76. for (i = 0; i < ci->devcount; i++) {
  77. struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
  78. struct com20020_dev *card;
  79. dev = alloc_arcdev(device);
  80. if (!dev) {
  81. ret = -ENOMEM;
  82. goto out_port;
  83. }
  84. dev->netdev_ops = &com20020_netdev_ops;
  85. lp = netdev_priv(dev);
  86. BUGMSG(D_NORMAL, "%s Controls\n", ci->name);
  87. ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
  88. r = devm_request_region(&pdev->dev, ioaddr, cm->size,
  89. "com20020-pci");
  90. if (!r) {
  91. pr_err("IO region %xh-%xh already allocated.\n",
  92. ioaddr, ioaddr + cm->size - 1);
  93. ret = -EBUSY;
  94. goto out_port;
  95. }
  96. /* Dummy access after Reset
  97. * ARCNET controller needs
  98. * this access to detect bustype
  99. */
  100. outb(0x00, ioaddr + 1);
  101. inb(ioaddr + 1);
  102. dev->base_addr = ioaddr;
  103. dev->dev_addr[0] = node;
  104. dev->irq = pdev->irq;
  105. lp->card_name = "PCI COM20020";
  106. lp->card_flags = ci->flags;
  107. lp->backplane = backplane;
  108. lp->clockp = clockp & 7;
  109. lp->clockm = clockm & 3;
  110. lp->timeout = timeout;
  111. lp->hw.owner = THIS_MODULE;
  112. if (ASTATUS() == 0xFF) {
  113. pr_err("IO address %Xh is empty!\n", ioaddr);
  114. ret = -EIO;
  115. goto out_port;
  116. }
  117. if (com20020_check(dev)) {
  118. ret = -EIO;
  119. goto out_port;
  120. }
  121. card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
  122. GFP_KERNEL);
  123. if (!card) {
  124. pr_err("%s out of memory!\n", __func__);
  125. return -ENOMEM;
  126. }
  127. card->index = i;
  128. card->pci_priv = priv;
  129. card->dev = dev;
  130. dev_set_drvdata(&dev->dev, card);
  131. ret = com20020_found(dev, IRQF_SHARED);
  132. if (ret)
  133. goto out_port;
  134. list_add(&card->list, &priv->list_dev);
  135. }
  136. pci_set_drvdata(pdev, priv);
  137. return 0;
  138. out_port:
  139. com20020pci_remove(pdev);
  140. return ret;
  141. }
  142. static void com20020pci_remove(struct pci_dev *pdev)
  143. {
  144. struct com20020_dev *card, *tmpcard;
  145. struct com20020_priv *priv;
  146. priv = pci_get_drvdata(pdev);
  147. list_for_each_entry_safe(card, tmpcard, &priv->list_dev, list) {
  148. struct net_device *dev = card->dev;
  149. unregister_netdev(dev);
  150. free_irq(dev->irq, dev);
  151. free_netdev(dev);
  152. }
  153. }
  154. static struct com20020_pci_card_info card_info_10mbit = {
  155. .name = "ARC-PCI",
  156. .devcount = 1,
  157. .chan_map_tbl = {
  158. { 2, 0x00, 0x08 },
  159. },
  160. .flags = ARC_CAN_10MBIT,
  161. };
  162. static struct com20020_pci_card_info card_info_5mbit = {
  163. .name = "ARC-PCI",
  164. .devcount = 1,
  165. .chan_map_tbl = {
  166. { 2, 0x00, 0x08 },
  167. },
  168. .flags = ARC_IS_5MBIT,
  169. };
  170. static struct com20020_pci_card_info card_info_sohard = {
  171. .name = "PLX-PCI",
  172. .devcount = 1,
  173. /* SOHARD needs PCI base addr 4 */
  174. .chan_map_tbl = {
  175. {4, 0x00, 0x08},
  176. },
  177. .flags = ARC_CAN_10MBIT,
  178. };
  179. static struct com20020_pci_card_info card_info_eae_arc1 = {
  180. .name = "EAE PLX-PCI ARC1",
  181. .devcount = 1,
  182. .chan_map_tbl = {
  183. { 2, 0x00, 0x08 },
  184. },
  185. .flags = ARC_CAN_10MBIT,
  186. };
  187. static struct com20020_pci_card_info card_info_eae_ma1 = {
  188. .name = "EAE PLX-PCI MA1",
  189. .devcount = 2,
  190. .chan_map_tbl = {
  191. { 2, 0x00, 0x08 },
  192. { 2, 0x08, 0x08 }
  193. },
  194. .flags = ARC_CAN_10MBIT,
  195. };
  196. static const struct pci_device_id com20020pci_id_table[] = {
  197. {
  198. 0x1571, 0xa001,
  199. PCI_ANY_ID, PCI_ANY_ID,
  200. 0, 0,
  201. 0,
  202. },
  203. {
  204. 0x1571, 0xa002,
  205. PCI_ANY_ID, PCI_ANY_ID,
  206. 0, 0,
  207. 0,
  208. },
  209. {
  210. 0x1571, 0xa003,
  211. PCI_ANY_ID, PCI_ANY_ID,
  212. 0, 0,
  213. 0
  214. },
  215. {
  216. 0x1571, 0xa004,
  217. PCI_ANY_ID, PCI_ANY_ID,
  218. 0, 0,
  219. 0,
  220. },
  221. {
  222. 0x1571, 0xa005,
  223. PCI_ANY_ID, PCI_ANY_ID,
  224. 0, 0,
  225. 0
  226. },
  227. {
  228. 0x1571, 0xa006,
  229. PCI_ANY_ID, PCI_ANY_ID,
  230. 0, 0,
  231. 0
  232. },
  233. {
  234. 0x1571, 0xa007,
  235. PCI_ANY_ID, PCI_ANY_ID,
  236. 0, 0,
  237. 0
  238. },
  239. {
  240. 0x1571, 0xa008,
  241. PCI_ANY_ID, PCI_ANY_ID,
  242. 0, 0,
  243. 0
  244. },
  245. {
  246. 0x1571, 0xa009,
  247. PCI_ANY_ID, PCI_ANY_ID,
  248. 0, 0,
  249. (kernel_ulong_t)&card_info_5mbit
  250. },
  251. {
  252. 0x1571, 0xa00a,
  253. PCI_ANY_ID, PCI_ANY_ID,
  254. 0, 0,
  255. (kernel_ulong_t)&card_info_5mbit
  256. },
  257. {
  258. 0x1571, 0xa00b,
  259. PCI_ANY_ID, PCI_ANY_ID,
  260. 0, 0,
  261. (kernel_ulong_t)&card_info_5mbit
  262. },
  263. {
  264. 0x1571, 0xa00c,
  265. PCI_ANY_ID, PCI_ANY_ID,
  266. 0, 0,
  267. (kernel_ulong_t)&card_info_5mbit
  268. },
  269. {
  270. 0x1571, 0xa00d,
  271. PCI_ANY_ID, PCI_ANY_ID,
  272. 0, 0,
  273. (kernel_ulong_t)&card_info_5mbit
  274. },
  275. {
  276. 0x1571, 0xa00e,
  277. PCI_ANY_ID, PCI_ANY_ID,
  278. 0, 0,
  279. (kernel_ulong_t)&card_info_5mbit
  280. },
  281. {
  282. 0x1571, 0xa201,
  283. PCI_ANY_ID, PCI_ANY_ID,
  284. 0, 0,
  285. (kernel_ulong_t)&card_info_10mbit
  286. },
  287. {
  288. 0x1571, 0xa202,
  289. PCI_ANY_ID, PCI_ANY_ID,
  290. 0, 0,
  291. (kernel_ulong_t)&card_info_10mbit
  292. },
  293. {
  294. 0x1571, 0xa203,
  295. PCI_ANY_ID, PCI_ANY_ID,
  296. 0, 0,
  297. (kernel_ulong_t)&card_info_10mbit
  298. },
  299. {
  300. 0x1571, 0xa204,
  301. PCI_ANY_ID, PCI_ANY_ID,
  302. 0, 0,
  303. (kernel_ulong_t)&card_info_10mbit
  304. },
  305. {
  306. 0x1571, 0xa205,
  307. PCI_ANY_ID, PCI_ANY_ID,
  308. 0, 0,
  309. (kernel_ulong_t)&card_info_10mbit
  310. },
  311. {
  312. 0x1571, 0xa206,
  313. PCI_ANY_ID, PCI_ANY_ID,
  314. 0, 0,
  315. (kernel_ulong_t)&card_info_10mbit
  316. },
  317. {
  318. 0x10B5, 0x9030,
  319. 0x10B5, 0x2978,
  320. 0, 0,
  321. (kernel_ulong_t)&card_info_sohard
  322. },
  323. {
  324. 0x10B5, 0x9050,
  325. 0x10B5, 0x2273,
  326. 0, 0,
  327. (kernel_ulong_t)&card_info_sohard
  328. },
  329. {
  330. 0x10B5, 0x9050,
  331. 0x10B5, 0x3263,
  332. 0, 0,
  333. (kernel_ulong_t)&card_info_eae_arc1
  334. },
  335. {
  336. 0x10B5, 0x9050,
  337. 0x10B5, 0x3292,
  338. 0, 0,
  339. (kernel_ulong_t)&card_info_eae_ma1
  340. },
  341. {
  342. 0x14BA, 0x6000,
  343. PCI_ANY_ID, PCI_ANY_ID,
  344. 0, 0,
  345. (kernel_ulong_t)&card_info_10mbit
  346. },
  347. {
  348. 0x10B5, 0x2200,
  349. PCI_ANY_ID, PCI_ANY_ID,
  350. 0, 0,
  351. (kernel_ulong_t)&card_info_10mbit
  352. },
  353. { 0, }
  354. };
  355. MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
  356. static struct pci_driver com20020pci_driver = {
  357. .name = "com20020",
  358. .id_table = com20020pci_id_table,
  359. .probe = com20020pci_probe,
  360. .remove = com20020pci_remove,
  361. };
  362. static int __init com20020pci_init(void)
  363. {
  364. BUGLVL(D_NORMAL) printk(VERSION);
  365. return pci_register_driver(&com20020pci_driver);
  366. }
  367. static void __exit com20020pci_cleanup(void)
  368. {
  369. pci_unregister_driver(&com20020pci_driver);
  370. }
  371. module_init(com20020pci_init)
  372. module_exit(com20020pci_cleanup)