b1pci.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /* $Id: b1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
  2. *
  3. * Module for AVM B1 PCI-card.
  4. *
  5. * Copyright 1999 by Carsten Paeth <calle@calle.de>
  6. *
  7. * This software may be used and distributed according to the terms
  8. * of the GNU General Public License, incorporated herein by reference.
  9. *
  10. */
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <linux/skbuff.h>
  14. #include <linux/delay.h>
  15. #include <linux/mm.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/ioport.h>
  18. #include <linux/pci.h>
  19. #include <linux/capi.h>
  20. #include <asm/io.h>
  21. #include <linux/init.h>
  22. #include <linux/isdn/capicmd.h>
  23. #include <linux/isdn/capiutil.h>
  24. #include <linux/isdn/capilli.h>
  25. #include "avmcard.h"
  26. /* ------------------------------------------------------------- */
  27. static char *revision = "$Revision: 1.1.2.2 $";
  28. /* ------------------------------------------------------------- */
  29. static struct pci_device_id b1pci_pci_tbl[] = {
  30. { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID },
  31. { } /* Terminating entry */
  32. };
  33. MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl);
  34. MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 PCI card");
  35. MODULE_AUTHOR("Carsten Paeth");
  36. MODULE_LICENSE("GPL");
  37. /* ------------------------------------------------------------- */
  38. static char *b1pci_procinfo(struct capi_ctr *ctrl)
  39. {
  40. avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
  41. if (!cinfo)
  42. return "";
  43. sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
  44. cinfo->cardname[0] ? cinfo->cardname : "-",
  45. cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
  46. cinfo->card ? cinfo->card->port : 0x0,
  47. cinfo->card ? cinfo->card->irq : 0,
  48. cinfo->card ? cinfo->card->revision : 0
  49. );
  50. return cinfo->infobuf;
  51. }
  52. /* ------------------------------------------------------------- */
  53. static int b1pci_probe(struct capicardparams *p, struct pci_dev *pdev)
  54. {
  55. avmcard *card;
  56. avmctrl_info *cinfo;
  57. int retval;
  58. card = b1_alloc_card(1);
  59. if (!card) {
  60. printk(KERN_WARNING "b1pci: no memory.\n");
  61. retval = -ENOMEM;
  62. goto err;
  63. }
  64. cinfo = card->ctrlinfo;
  65. sprintf(card->name, "b1pci-%x", p->port);
  66. card->port = p->port;
  67. card->irq = p->irq;
  68. card->cardtype = avm_b1pci;
  69. if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
  70. printk(KERN_WARNING "b1pci: ports 0x%03x-0x%03x in use.\n",
  71. card->port, card->port + AVMB1_PORTLEN);
  72. retval = -EBUSY;
  73. goto err_free;
  74. }
  75. b1_reset(card->port);
  76. retval = b1_detect(card->port, card->cardtype);
  77. if (retval) {
  78. printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n",
  79. card->port, retval);
  80. retval = -ENODEV;
  81. goto err_release_region;
  82. }
  83. b1_reset(card->port);
  84. b1_getrevision(card);
  85. retval = request_irq(card->irq, b1_interrupt, IRQF_SHARED, card->name, card);
  86. if (retval) {
  87. printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq);
  88. retval = -EBUSY;
  89. goto err_release_region;
  90. }
  91. cinfo->capi_ctrl.driver_name = "b1pci";
  92. cinfo->capi_ctrl.driverdata = cinfo;
  93. cinfo->capi_ctrl.register_appl = b1_register_appl;
  94. cinfo->capi_ctrl.release_appl = b1_release_appl;
  95. cinfo->capi_ctrl.send_message = b1_send_message;
  96. cinfo->capi_ctrl.load_firmware = b1_load_firmware;
  97. cinfo->capi_ctrl.reset_ctr = b1_reset_ctr;
  98. cinfo->capi_ctrl.procinfo = b1pci_procinfo;
  99. cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops;
  100. strcpy(cinfo->capi_ctrl.name, card->name);
  101. cinfo->capi_ctrl.owner = THIS_MODULE;
  102. retval = attach_capi_ctr(&cinfo->capi_ctrl);
  103. if (retval) {
  104. printk(KERN_ERR "b1pci: attach controller failed.\n");
  105. goto err_free_irq;
  106. }
  107. if (card->revision >= 4) {
  108. printk(KERN_INFO "b1pci: AVM B1 PCI V4 at i/o %#x, irq %d, revision %d (no dma)\n",
  109. card->port, card->irq, card->revision);
  110. } else {
  111. printk(KERN_INFO "b1pci: AVM B1 PCI at i/o %#x, irq %d, revision %d\n",
  112. card->port, card->irq, card->revision);
  113. }
  114. pci_set_drvdata(pdev, card);
  115. return 0;
  116. err_free_irq:
  117. free_irq(card->irq, card);
  118. err_release_region:
  119. release_region(card->port, AVMB1_PORTLEN);
  120. err_free:
  121. b1_free_card(card);
  122. err:
  123. return retval;
  124. }
  125. static void b1pci_remove(struct pci_dev *pdev)
  126. {
  127. avmcard *card = pci_get_drvdata(pdev);
  128. avmctrl_info *cinfo = card->ctrlinfo;
  129. unsigned int port = card->port;
  130. b1_reset(port);
  131. b1_reset(port);
  132. detach_capi_ctr(&cinfo->capi_ctrl);
  133. free_irq(card->irq, card);
  134. release_region(card->port, AVMB1_PORTLEN);
  135. b1_free_card(card);
  136. }
  137. #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
  138. /* ------------------------------------------------------------- */
  139. static char *b1pciv4_procinfo(struct capi_ctr *ctrl)
  140. {
  141. avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
  142. if (!cinfo)
  143. return "";
  144. sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx r%d",
  145. cinfo->cardname[0] ? cinfo->cardname : "-",
  146. cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
  147. cinfo->card ? cinfo->card->port : 0x0,
  148. cinfo->card ? cinfo->card->irq : 0,
  149. cinfo->card ? cinfo->card->membase : 0,
  150. cinfo->card ? cinfo->card->revision : 0
  151. );
  152. return cinfo->infobuf;
  153. }
  154. /* ------------------------------------------------------------- */
  155. static int b1pciv4_probe(struct capicardparams *p, struct pci_dev *pdev)
  156. {
  157. avmcard *card;
  158. avmctrl_info *cinfo;
  159. int retval;
  160. card = b1_alloc_card(1);
  161. if (!card) {
  162. printk(KERN_WARNING "b1pci: no memory.\n");
  163. retval = -ENOMEM;
  164. goto err;
  165. }
  166. card->dma = avmcard_dma_alloc("b1pci", pdev, 2048 + 128, 2048 + 128);
  167. if (!card->dma) {
  168. printk(KERN_WARNING "b1pci: dma alloc.\n");
  169. retval = -ENOMEM;
  170. goto err_free;
  171. }
  172. cinfo = card->ctrlinfo;
  173. sprintf(card->name, "b1pciv4-%x", p->port);
  174. card->port = p->port;
  175. card->irq = p->irq;
  176. card->membase = p->membase;
  177. card->cardtype = avm_b1pci;
  178. if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
  179. printk(KERN_WARNING "b1pci: ports 0x%03x-0x%03x in use.\n",
  180. card->port, card->port + AVMB1_PORTLEN);
  181. retval = -EBUSY;
  182. goto err_free_dma;
  183. }
  184. card->mbase = ioremap(card->membase, 64);
  185. if (!card->mbase) {
  186. printk(KERN_NOTICE "b1pci: can't remap memory at 0x%lx\n",
  187. card->membase);
  188. retval = -ENOMEM;
  189. goto err_release_region;
  190. }
  191. b1dma_reset(card);
  192. retval = b1pciv4_detect(card);
  193. if (retval) {
  194. printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n",
  195. card->port, retval);
  196. retval = -ENODEV;
  197. goto err_unmap;
  198. }
  199. b1dma_reset(card);
  200. b1_getrevision(card);
  201. retval = request_irq(card->irq, b1dma_interrupt, IRQF_SHARED, card->name, card);
  202. if (retval) {
  203. printk(KERN_ERR "b1pci: unable to get IRQ %d.\n",
  204. card->irq);
  205. retval = -EBUSY;
  206. goto err_unmap;
  207. }
  208. cinfo->capi_ctrl.owner = THIS_MODULE;
  209. cinfo->capi_ctrl.driver_name = "b1pciv4";
  210. cinfo->capi_ctrl.driverdata = cinfo;
  211. cinfo->capi_ctrl.register_appl = b1dma_register_appl;
  212. cinfo->capi_ctrl.release_appl = b1dma_release_appl;
  213. cinfo->capi_ctrl.send_message = b1dma_send_message;
  214. cinfo->capi_ctrl.load_firmware = b1dma_load_firmware;
  215. cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr;
  216. cinfo->capi_ctrl.procinfo = b1pciv4_procinfo;
  217. cinfo->capi_ctrl.proc_fops = &b1dmactl_proc_fops;
  218. strcpy(cinfo->capi_ctrl.name, card->name);
  219. retval = attach_capi_ctr(&cinfo->capi_ctrl);
  220. if (retval) {
  221. printk(KERN_ERR "b1pci: attach controller failed.\n");
  222. goto err_free_irq;
  223. }
  224. card->cardnr = cinfo->capi_ctrl.cnr;
  225. printk(KERN_INFO "b1pci: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n",
  226. card->port, card->irq, card->membase, card->revision);
  227. pci_set_drvdata(pdev, card);
  228. return 0;
  229. err_free_irq:
  230. free_irq(card->irq, card);
  231. err_unmap:
  232. iounmap(card->mbase);
  233. err_release_region:
  234. release_region(card->port, AVMB1_PORTLEN);
  235. err_free_dma:
  236. avmcard_dma_free(card->dma);
  237. err_free:
  238. b1_free_card(card);
  239. err:
  240. return retval;
  241. }
  242. static void b1pciv4_remove(struct pci_dev *pdev)
  243. {
  244. avmcard *card = pci_get_drvdata(pdev);
  245. avmctrl_info *cinfo = card->ctrlinfo;
  246. b1dma_reset(card);
  247. detach_capi_ctr(&cinfo->capi_ctrl);
  248. free_irq(card->irq, card);
  249. iounmap(card->mbase);
  250. release_region(card->port, AVMB1_PORTLEN);
  251. avmcard_dma_free(card->dma);
  252. b1_free_card(card);
  253. }
  254. #endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */
  255. static int b1pci_pci_probe(struct pci_dev *pdev,
  256. const struct pci_device_id *ent)
  257. {
  258. struct capicardparams param;
  259. int retval;
  260. if (pci_enable_device(pdev) < 0) {
  261. printk(KERN_ERR "b1pci: failed to enable AVM-B1\n");
  262. return -ENODEV;
  263. }
  264. param.irq = pdev->irq;
  265. if (pci_resource_start(pdev, 2)) { /* B1 PCI V4 */
  266. #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
  267. pci_set_master(pdev);
  268. #endif
  269. param.membase = pci_resource_start(pdev, 0);
  270. param.port = pci_resource_start(pdev, 2);
  271. printk(KERN_INFO "b1pci: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
  272. param.port, param.irq, param.membase);
  273. #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
  274. retval = b1pciv4_probe(&param, pdev);
  275. #else
  276. retval = b1pci_probe(&param, pdev);
  277. #endif
  278. if (retval != 0) {
  279. printk(KERN_ERR "b1pci: no AVM-B1 V4 at i/o %#x, irq %d, mem %#x detected\n",
  280. param.port, param.irq, param.membase);
  281. }
  282. } else {
  283. param.membase = 0;
  284. param.port = pci_resource_start(pdev, 1);
  285. printk(KERN_INFO "b1pci: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
  286. param.port, param.irq);
  287. retval = b1pci_probe(&param, pdev);
  288. if (retval != 0) {
  289. printk(KERN_ERR "b1pci: no AVM-B1 at i/o %#x, irq %d detected\n",
  290. param.port, param.irq);
  291. }
  292. }
  293. return retval;
  294. }
  295. static void b1pci_pci_remove(struct pci_dev *pdev)
  296. {
  297. #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
  298. avmcard *card = pci_get_drvdata(pdev);
  299. if (card->dma)
  300. b1pciv4_remove(pdev);
  301. else
  302. b1pci_remove(pdev);
  303. #else
  304. b1pci_remove(pdev);
  305. #endif
  306. }
  307. static struct pci_driver b1pci_pci_driver = {
  308. .name = "b1pci",
  309. .id_table = b1pci_pci_tbl,
  310. .probe = b1pci_pci_probe,
  311. .remove = b1pci_pci_remove,
  312. };
  313. static struct capi_driver capi_driver_b1pci = {
  314. .name = "b1pci",
  315. .revision = "1.0",
  316. };
  317. #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
  318. static struct capi_driver capi_driver_b1pciv4 = {
  319. .name = "b1pciv4",
  320. .revision = "1.0",
  321. };
  322. #endif
  323. static int __init b1pci_init(void)
  324. {
  325. char *p;
  326. char rev[32];
  327. int err;
  328. if ((p = strchr(revision, ':')) != NULL && p[1]) {
  329. strlcpy(rev, p + 2, 32);
  330. if ((p = strchr(rev, '$')) != NULL && p > rev)
  331. *(p - 1) = 0;
  332. } else
  333. strcpy(rev, "1.0");
  334. err = pci_register_driver(&b1pci_pci_driver);
  335. if (!err) {
  336. strlcpy(capi_driver_b1pci.revision, rev, 32);
  337. register_capi_driver(&capi_driver_b1pci);
  338. #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
  339. strlcpy(capi_driver_b1pciv4.revision, rev, 32);
  340. register_capi_driver(&capi_driver_b1pciv4);
  341. #endif
  342. printk(KERN_INFO "b1pci: revision %s\n", rev);
  343. }
  344. return err;
  345. }
  346. static void __exit b1pci_exit(void)
  347. {
  348. unregister_capi_driver(&capi_driver_b1pci);
  349. #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
  350. unregister_capi_driver(&capi_driver_b1pciv4);
  351. #endif
  352. pci_unregister_driver(&b1pci_pci_driver);
  353. }
  354. module_init(b1pci_init);
  355. module_exit(b1pci_exit);