com20020-pci.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  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 = {
  180. .name = "EAE PLX-PCI",
  181. .devcount = 2,
  182. .chan_map_tbl = {
  183. { 2, 0x00, 0x08 },
  184. { 2, 0x08, 0x08 }
  185. },
  186. .flags = ARC_CAN_10MBIT,
  187. };
  188. static const struct pci_device_id com20020pci_id_table[] = {
  189. {
  190. 0x1571, 0xa001,
  191. PCI_ANY_ID, PCI_ANY_ID,
  192. 0, 0,
  193. 0,
  194. },
  195. {
  196. 0x1571, 0xa002,
  197. PCI_ANY_ID, PCI_ANY_ID,
  198. 0, 0,
  199. 0,
  200. },
  201. {
  202. 0x1571, 0xa003,
  203. PCI_ANY_ID, PCI_ANY_ID,
  204. 0, 0,
  205. 0
  206. },
  207. {
  208. 0x1571, 0xa004,
  209. PCI_ANY_ID, PCI_ANY_ID,
  210. 0, 0,
  211. 0,
  212. },
  213. {
  214. 0x1571, 0xa005,
  215. PCI_ANY_ID, PCI_ANY_ID,
  216. 0, 0,
  217. 0
  218. },
  219. {
  220. 0x1571, 0xa006,
  221. PCI_ANY_ID, PCI_ANY_ID,
  222. 0, 0,
  223. 0
  224. },
  225. {
  226. 0x1571, 0xa007,
  227. PCI_ANY_ID, PCI_ANY_ID,
  228. 0, 0,
  229. 0
  230. },
  231. {
  232. 0x1571, 0xa008,
  233. PCI_ANY_ID, PCI_ANY_ID,
  234. 0, 0,
  235. 0
  236. },
  237. {
  238. 0x1571, 0xa009,
  239. PCI_ANY_ID, PCI_ANY_ID,
  240. 0, 0,
  241. (kernel_ulong_t)&card_info_5mbit
  242. },
  243. {
  244. 0x1571, 0xa00a,
  245. PCI_ANY_ID, PCI_ANY_ID,
  246. 0, 0,
  247. (kernel_ulong_t)&card_info_5mbit
  248. },
  249. {
  250. 0x1571, 0xa00b,
  251. PCI_ANY_ID, PCI_ANY_ID,
  252. 0, 0,
  253. (kernel_ulong_t)&card_info_5mbit
  254. },
  255. {
  256. 0x1571, 0xa00c,
  257. PCI_ANY_ID, PCI_ANY_ID,
  258. 0, 0,
  259. (kernel_ulong_t)&card_info_5mbit
  260. },
  261. {
  262. 0x1571, 0xa00d,
  263. PCI_ANY_ID, PCI_ANY_ID,
  264. 0, 0,
  265. (kernel_ulong_t)&card_info_5mbit
  266. },
  267. {
  268. 0x1571, 0xa00e,
  269. PCI_ANY_ID, PCI_ANY_ID,
  270. 0, 0,
  271. (kernel_ulong_t)&card_info_5mbit
  272. },
  273. {
  274. 0x1571, 0xa201,
  275. PCI_ANY_ID, PCI_ANY_ID,
  276. 0, 0,
  277. (kernel_ulong_t)&card_info_10mbit
  278. },
  279. {
  280. 0x1571, 0xa202,
  281. PCI_ANY_ID, PCI_ANY_ID,
  282. 0, 0,
  283. (kernel_ulong_t)&card_info_10mbit
  284. },
  285. {
  286. 0x1571, 0xa203,
  287. PCI_ANY_ID, PCI_ANY_ID,
  288. 0, 0,
  289. (kernel_ulong_t)&card_info_10mbit
  290. },
  291. {
  292. 0x1571, 0xa204,
  293. PCI_ANY_ID, PCI_ANY_ID,
  294. 0, 0,
  295. (kernel_ulong_t)&card_info_10mbit
  296. },
  297. {
  298. 0x1571, 0xa205,
  299. PCI_ANY_ID, PCI_ANY_ID,
  300. 0, 0,
  301. (kernel_ulong_t)&card_info_10mbit
  302. },
  303. {
  304. 0x1571, 0xa206,
  305. PCI_ANY_ID, PCI_ANY_ID,
  306. 0, 0,
  307. (kernel_ulong_t)&card_info_10mbit
  308. },
  309. {
  310. 0x10B5, 0x9030,
  311. 0x10B5, 0x2978,
  312. 0, 0,
  313. (kernel_ulong_t)&card_info_sohard
  314. },
  315. {
  316. 0x10B5, 0x9050,
  317. 0x10B5, 0x2273,
  318. 0, 0,
  319. (kernel_ulong_t)&card_info_sohard
  320. },
  321. {
  322. 0x10B5, 0x9050,
  323. 0x10B5, 0x3292,
  324. 0, 0,
  325. (kernel_ulong_t)&card_info_eae
  326. },
  327. {
  328. 0x14BA, 0x6000,
  329. PCI_ANY_ID, PCI_ANY_ID,
  330. 0, 0,
  331. (kernel_ulong_t)&card_info_10mbit
  332. },
  333. {
  334. 0x10B5, 0x2200,
  335. PCI_ANY_ID, PCI_ANY_ID,
  336. 0, 0,
  337. (kernel_ulong_t)&card_info_10mbit
  338. },
  339. { 0, }
  340. };
  341. MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
  342. static struct pci_driver com20020pci_driver = {
  343. .name = "com20020",
  344. .id_table = com20020pci_id_table,
  345. .probe = com20020pci_probe,
  346. .remove = com20020pci_remove,
  347. };
  348. static int __init com20020pci_init(void)
  349. {
  350. BUGLVL(D_NORMAL) printk(VERSION);
  351. return pci_register_driver(&com20020pci_driver);
  352. }
  353. static void __exit com20020pci_cleanup(void)
  354. {
  355. pci_unregister_driver(&com20020pci_driver);
  356. }
  357. module_init(com20020pci_init)
  358. module_exit(com20020pci_cleanup)