com20020-pci.c 7.6 KB

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