mISDNinfineon.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * mISDNinfineon.c
  4. * Support for cards based on following Infineon ISDN chipsets
  5. * - ISAC + HSCX
  6. * - IPAC and IPAC-X
  7. * - ISAC-SX + HSCX
  8. *
  9. * Supported cards:
  10. * - Dialogic Diva 2.0
  11. * - Dialogic Diva 2.0U
  12. * - Dialogic Diva 2.01
  13. * - Dialogic Diva 2.02
  14. * - Sedlbauer Speedwin
  15. * - HST Saphir3
  16. * - Develo (former ELSA) Microlink PCI (Quickstep 1000)
  17. * - Develo (former ELSA) Quickstep 3000
  18. * - Berkom Scitel BRIX Quadro
  19. * - Dr.Neuhaus (Sagem) Niccy
  20. *
  21. * Author Karsten Keil <[email protected]>
  22. *
  23. * Copyright 2009 by Karsten Keil <[email protected]>
  24. */
  25. #include <linux/interrupt.h>
  26. #include <linux/module.h>
  27. #include <linux/pci.h>
  28. #include <linux/delay.h>
  29. #include <linux/mISDNhw.h>
  30. #include <linux/slab.h>
  31. #include "ipac.h"
  32. #define INFINEON_REV "1.0"
  33. static int inf_cnt;
  34. static u32 debug;
  35. static u32 irqloops = 4;
  36. enum inf_types {
  37. INF_NONE,
  38. INF_DIVA20,
  39. INF_DIVA20U,
  40. INF_DIVA201,
  41. INF_DIVA202,
  42. INF_SPEEDWIN,
  43. INF_SAPHIR3,
  44. INF_QS1000,
  45. INF_QS3000,
  46. INF_NICCY,
  47. INF_SCT_1,
  48. INF_SCT_2,
  49. INF_SCT_3,
  50. INF_SCT_4,
  51. INF_GAZEL_R685,
  52. INF_GAZEL_R753
  53. };
  54. enum addr_mode {
  55. AM_NONE = 0,
  56. AM_IO,
  57. AM_MEMIO,
  58. AM_IND_IO,
  59. };
  60. struct inf_cinfo {
  61. enum inf_types typ;
  62. const char *full;
  63. const char *name;
  64. enum addr_mode cfg_mode;
  65. enum addr_mode addr_mode;
  66. u8 cfg_bar;
  67. u8 addr_bar;
  68. void *irqfunc;
  69. };
  70. struct _ioaddr {
  71. enum addr_mode mode;
  72. union {
  73. void __iomem *p;
  74. struct _ioport io;
  75. } a;
  76. };
  77. struct _iohandle {
  78. enum addr_mode mode;
  79. resource_size_t size;
  80. resource_size_t start;
  81. void __iomem *p;
  82. };
  83. struct inf_hw {
  84. struct list_head list;
  85. struct pci_dev *pdev;
  86. const struct inf_cinfo *ci;
  87. char name[MISDN_MAX_IDLEN];
  88. u32 irq;
  89. u32 irqcnt;
  90. struct _iohandle cfg;
  91. struct _iohandle addr;
  92. struct _ioaddr isac;
  93. struct _ioaddr hscx;
  94. spinlock_t lock; /* HW access lock */
  95. struct ipac_hw ipac;
  96. struct inf_hw *sc[3]; /* slave cards */
  97. };
  98. #define PCI_SUBVENDOR_HST_SAPHIR3 0x52
  99. #define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53
  100. #define PCI_SUB_ID_SEDLBAUER 0x01
  101. static struct pci_device_id infineon_ids[] = {
  102. { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20), INF_DIVA20 },
  103. { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20_U), INF_DIVA20U },
  104. { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA201), INF_DIVA201 },
  105. { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA202), INF_DIVA202 },
  106. { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
  107. PCI_SUBVENDOR_SEDLBAUER_PCI, PCI_SUB_ID_SEDLBAUER, 0, 0,
  108. INF_SPEEDWIN },
  109. { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
  110. PCI_SUBVENDOR_HST_SAPHIR3, PCI_SUB_ID_SEDLBAUER, 0, 0, INF_SAPHIR3 },
  111. { PCI_VDEVICE(ELSA, PCI_DEVICE_ID_ELSA_MICROLINK), INF_QS1000 },
  112. { PCI_VDEVICE(ELSA, PCI_DEVICE_ID_ELSA_QS3000), INF_QS3000 },
  113. { PCI_VDEVICE(SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY), INF_NICCY },
  114. { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
  115. PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO, 0, 0,
  116. INF_SCT_1 },
  117. { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_R685), INF_GAZEL_R685 },
  118. { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_R753), INF_GAZEL_R753 },
  119. { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO), INF_GAZEL_R753 },
  120. { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_OLITEC), INF_GAZEL_R753 },
  121. { }
  122. };
  123. MODULE_DEVICE_TABLE(pci, infineon_ids);
  124. /* PCI interface specific defines */
  125. /* Diva 2.0/2.0U */
  126. #define DIVA_HSCX_PORT 0x00
  127. #define DIVA_HSCX_ALE 0x04
  128. #define DIVA_ISAC_PORT 0x08
  129. #define DIVA_ISAC_ALE 0x0C
  130. #define DIVA_PCI_CTRL 0x10
  131. /* DIVA_PCI_CTRL bits */
  132. #define DIVA_IRQ_BIT 0x01
  133. #define DIVA_RESET_BIT 0x08
  134. #define DIVA_EEPROM_CLK 0x40
  135. #define DIVA_LED_A 0x10
  136. #define DIVA_LED_B 0x20
  137. #define DIVA_IRQ_CLR 0x80
  138. /* Diva 2.01/2.02 */
  139. /* Siemens PITA */
  140. #define PITA_ICR_REG 0x00
  141. #define PITA_INT0_STATUS 0x02
  142. #define PITA_MISC_REG 0x1c
  143. #define PITA_PARA_SOFTRESET 0x01000000
  144. #define PITA_SER_SOFTRESET 0x02000000
  145. #define PITA_PARA_MPX_MODE 0x04000000
  146. #define PITA_INT0_ENABLE 0x00020000
  147. /* TIGER 100 Registers */
  148. #define TIGER_RESET_ADDR 0x00
  149. #define TIGER_EXTERN_RESET 0x01
  150. #define TIGER_AUX_CTRL 0x02
  151. #define TIGER_AUX_DATA 0x03
  152. #define TIGER_AUX_IRQMASK 0x05
  153. #define TIGER_AUX_STATUS 0x07
  154. /* Tiger AUX BITs */
  155. #define TIGER_IOMASK 0xdd /* 1 and 5 are inputs */
  156. #define TIGER_IRQ_BIT 0x02
  157. #define TIGER_IPAC_ALE 0xC0
  158. #define TIGER_IPAC_PORT 0xC8
  159. /* ELSA (now Develo) PCI cards */
  160. #define ELSA_IRQ_ADDR 0x4c
  161. #define ELSA_IRQ_MASK 0x04
  162. #define QS1000_IRQ_OFF 0x01
  163. #define QS3000_IRQ_OFF 0x03
  164. #define QS1000_IRQ_ON 0x41
  165. #define QS3000_IRQ_ON 0x43
  166. /* Dr Neuhaus/Sagem Niccy */
  167. #define NICCY_ISAC_PORT 0x00
  168. #define NICCY_HSCX_PORT 0x01
  169. #define NICCY_ISAC_ALE 0x02
  170. #define NICCY_HSCX_ALE 0x03
  171. #define NICCY_IRQ_CTRL_REG 0x38
  172. #define NICCY_IRQ_ENABLE 0x001f00
  173. #define NICCY_IRQ_DISABLE 0xff0000
  174. #define NICCY_IRQ_BIT 0x800000
  175. /* Scitel PLX */
  176. #define SCT_PLX_IRQ_ADDR 0x4c
  177. #define SCT_PLX_RESET_ADDR 0x50
  178. #define SCT_PLX_IRQ_ENABLE 0x41
  179. #define SCT_PLX_RESET_BIT 0x04
  180. /* Gazel */
  181. #define GAZEL_IPAC_DATA_PORT 0x04
  182. /* Gazel PLX */
  183. #define GAZEL_CNTRL 0x50
  184. #define GAZEL_RESET 0x04
  185. #define GAZEL_RESET_9050 0x40000000
  186. #define GAZEL_INCSR 0x4C
  187. #define GAZEL_ISAC_EN 0x08
  188. #define GAZEL_INT_ISAC 0x20
  189. #define GAZEL_HSCX_EN 0x01
  190. #define GAZEL_INT_HSCX 0x04
  191. #define GAZEL_PCI_EN 0x40
  192. #define GAZEL_IPAC_EN 0x03
  193. static LIST_HEAD(Cards);
  194. static DEFINE_RWLOCK(card_lock); /* protect Cards */
  195. static void
  196. _set_debug(struct inf_hw *card)
  197. {
  198. card->ipac.isac.dch.debug = debug;
  199. card->ipac.hscx[0].bch.debug = debug;
  200. card->ipac.hscx[1].bch.debug = debug;
  201. }
  202. static int
  203. set_debug(const char *val, const struct kernel_param *kp)
  204. {
  205. int ret;
  206. struct inf_hw *card;
  207. ret = param_set_uint(val, kp);
  208. if (!ret) {
  209. read_lock(&card_lock);
  210. list_for_each_entry(card, &Cards, list)
  211. _set_debug(card);
  212. read_unlock(&card_lock);
  213. }
  214. return ret;
  215. }
  216. MODULE_AUTHOR("Karsten Keil");
  217. MODULE_LICENSE("GPL v2");
  218. MODULE_VERSION(INFINEON_REV);
  219. module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
  220. MODULE_PARM_DESC(debug, "infineon debug mask");
  221. module_param(irqloops, uint, S_IRUGO | S_IWUSR);
  222. MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)");
  223. /* Interface functions */
  224. IOFUNC_IO(ISAC, inf_hw, isac.a.io)
  225. IOFUNC_IO(IPAC, inf_hw, hscx.a.io)
  226. IOFUNC_IND(ISAC, inf_hw, isac.a.io)
  227. IOFUNC_IND(IPAC, inf_hw, hscx.a.io)
  228. IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p)
  229. IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p)
  230. static irqreturn_t
  231. diva_irq(int intno, void *dev_id)
  232. {
  233. struct inf_hw *hw = dev_id;
  234. u8 val;
  235. spin_lock(&hw->lock);
  236. val = inb((u32)hw->cfg.start + DIVA_PCI_CTRL);
  237. if (!(val & DIVA_IRQ_BIT)) { /* for us or shared ? */
  238. spin_unlock(&hw->lock);
  239. return IRQ_NONE; /* shared */
  240. }
  241. hw->irqcnt++;
  242. mISDNipac_irq(&hw->ipac, irqloops);
  243. spin_unlock(&hw->lock);
  244. return IRQ_HANDLED;
  245. }
  246. static irqreturn_t
  247. diva20x_irq(int intno, void *dev_id)
  248. {
  249. struct inf_hw *hw = dev_id;
  250. u8 val;
  251. spin_lock(&hw->lock);
  252. val = readb(hw->cfg.p);
  253. if (!(val & PITA_INT0_STATUS)) { /* for us or shared ? */
  254. spin_unlock(&hw->lock);
  255. return IRQ_NONE; /* shared */
  256. }
  257. hw->irqcnt++;
  258. mISDNipac_irq(&hw->ipac, irqloops);
  259. writeb(PITA_INT0_STATUS, hw->cfg.p); /* ACK PITA INT0 */
  260. spin_unlock(&hw->lock);
  261. return IRQ_HANDLED;
  262. }
  263. static irqreturn_t
  264. tiger_irq(int intno, void *dev_id)
  265. {
  266. struct inf_hw *hw = dev_id;
  267. u8 val;
  268. spin_lock(&hw->lock);
  269. val = inb((u32)hw->cfg.start + TIGER_AUX_STATUS);
  270. if (val & TIGER_IRQ_BIT) { /* for us or shared ? */
  271. spin_unlock(&hw->lock);
  272. return IRQ_NONE; /* shared */
  273. }
  274. hw->irqcnt++;
  275. mISDNipac_irq(&hw->ipac, irqloops);
  276. spin_unlock(&hw->lock);
  277. return IRQ_HANDLED;
  278. }
  279. static irqreturn_t
  280. elsa_irq(int intno, void *dev_id)
  281. {
  282. struct inf_hw *hw = dev_id;
  283. u8 val;
  284. spin_lock(&hw->lock);
  285. val = inb((u32)hw->cfg.start + ELSA_IRQ_ADDR);
  286. if (!(val & ELSA_IRQ_MASK)) {
  287. spin_unlock(&hw->lock);
  288. return IRQ_NONE; /* shared */
  289. }
  290. hw->irqcnt++;
  291. mISDNipac_irq(&hw->ipac, irqloops);
  292. spin_unlock(&hw->lock);
  293. return IRQ_HANDLED;
  294. }
  295. static irqreturn_t
  296. niccy_irq(int intno, void *dev_id)
  297. {
  298. struct inf_hw *hw = dev_id;
  299. u32 val;
  300. spin_lock(&hw->lock);
  301. val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
  302. if (!(val & NICCY_IRQ_BIT)) { /* for us or shared ? */
  303. spin_unlock(&hw->lock);
  304. return IRQ_NONE; /* shared */
  305. }
  306. outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
  307. hw->irqcnt++;
  308. mISDNipac_irq(&hw->ipac, irqloops);
  309. spin_unlock(&hw->lock);
  310. return IRQ_HANDLED;
  311. }
  312. static irqreturn_t
  313. gazel_irq(int intno, void *dev_id)
  314. {
  315. struct inf_hw *hw = dev_id;
  316. irqreturn_t ret;
  317. spin_lock(&hw->lock);
  318. ret = mISDNipac_irq(&hw->ipac, irqloops);
  319. spin_unlock(&hw->lock);
  320. return ret;
  321. }
  322. static irqreturn_t
  323. ipac_irq(int intno, void *dev_id)
  324. {
  325. struct inf_hw *hw = dev_id;
  326. u8 val;
  327. spin_lock(&hw->lock);
  328. val = hw->ipac.read_reg(hw, IPAC_ISTA);
  329. if (!(val & 0x3f)) {
  330. spin_unlock(&hw->lock);
  331. return IRQ_NONE; /* shared */
  332. }
  333. hw->irqcnt++;
  334. mISDNipac_irq(&hw->ipac, irqloops);
  335. spin_unlock(&hw->lock);
  336. return IRQ_HANDLED;
  337. }
  338. static void
  339. enable_hwirq(struct inf_hw *hw)
  340. {
  341. u16 w;
  342. u32 val;
  343. switch (hw->ci->typ) {
  344. case INF_DIVA201:
  345. case INF_DIVA202:
  346. writel(PITA_INT0_ENABLE, hw->cfg.p);
  347. break;
  348. case INF_SPEEDWIN:
  349. case INF_SAPHIR3:
  350. outb(TIGER_IRQ_BIT, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
  351. break;
  352. case INF_QS1000:
  353. outb(QS1000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
  354. break;
  355. case INF_QS3000:
  356. outb(QS3000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
  357. break;
  358. case INF_NICCY:
  359. val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
  360. val |= NICCY_IRQ_ENABLE;
  361. outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
  362. break;
  363. case INF_SCT_1:
  364. w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
  365. w |= SCT_PLX_IRQ_ENABLE;
  366. outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
  367. break;
  368. case INF_GAZEL_R685:
  369. outb(GAZEL_ISAC_EN + GAZEL_HSCX_EN + GAZEL_PCI_EN,
  370. (u32)hw->cfg.start + GAZEL_INCSR);
  371. break;
  372. case INF_GAZEL_R753:
  373. outb(GAZEL_IPAC_EN + GAZEL_PCI_EN,
  374. (u32)hw->cfg.start + GAZEL_INCSR);
  375. break;
  376. default:
  377. break;
  378. }
  379. }
  380. static void
  381. disable_hwirq(struct inf_hw *hw)
  382. {
  383. u16 w;
  384. u32 val;
  385. switch (hw->ci->typ) {
  386. case INF_DIVA201:
  387. case INF_DIVA202:
  388. writel(0, hw->cfg.p);
  389. break;
  390. case INF_SPEEDWIN:
  391. case INF_SAPHIR3:
  392. outb(0, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
  393. break;
  394. case INF_QS1000:
  395. outb(QS1000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
  396. break;
  397. case INF_QS3000:
  398. outb(QS3000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
  399. break;
  400. case INF_NICCY:
  401. val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
  402. val &= NICCY_IRQ_DISABLE;
  403. outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
  404. break;
  405. case INF_SCT_1:
  406. w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
  407. w &= (~SCT_PLX_IRQ_ENABLE);
  408. outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
  409. break;
  410. case INF_GAZEL_R685:
  411. case INF_GAZEL_R753:
  412. outb(0, (u32)hw->cfg.start + GAZEL_INCSR);
  413. break;
  414. default:
  415. break;
  416. }
  417. }
  418. static void
  419. ipac_chip_reset(struct inf_hw *hw)
  420. {
  421. hw->ipac.write_reg(hw, IPAC_POTA2, 0x20);
  422. mdelay(5);
  423. hw->ipac.write_reg(hw, IPAC_POTA2, 0x00);
  424. mdelay(5);
  425. hw->ipac.write_reg(hw, IPAC_CONF, hw->ipac.conf);
  426. hw->ipac.write_reg(hw, IPAC_MASK, 0xc0);
  427. }
  428. static void
  429. reset_inf(struct inf_hw *hw)
  430. {
  431. u16 w;
  432. u32 val;
  433. if (debug & DEBUG_HW)
  434. pr_notice("%s: resetting card\n", hw->name);
  435. switch (hw->ci->typ) {
  436. case INF_DIVA20:
  437. case INF_DIVA20U:
  438. outb(0, (u32)hw->cfg.start + DIVA_PCI_CTRL);
  439. mdelay(10);
  440. outb(DIVA_RESET_BIT, (u32)hw->cfg.start + DIVA_PCI_CTRL);
  441. mdelay(10);
  442. /* Workaround PCI9060 */
  443. outb(9, (u32)hw->cfg.start + 0x69);
  444. outb(DIVA_RESET_BIT | DIVA_LED_A,
  445. (u32)hw->cfg.start + DIVA_PCI_CTRL);
  446. break;
  447. case INF_DIVA201:
  448. writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
  449. hw->cfg.p + PITA_MISC_REG);
  450. mdelay(1);
  451. writel(PITA_PARA_MPX_MODE, hw->cfg.p + PITA_MISC_REG);
  452. mdelay(10);
  453. break;
  454. case INF_DIVA202:
  455. writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
  456. hw->cfg.p + PITA_MISC_REG);
  457. mdelay(1);
  458. writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET,
  459. hw->cfg.p + PITA_MISC_REG);
  460. mdelay(10);
  461. break;
  462. case INF_SPEEDWIN:
  463. case INF_SAPHIR3:
  464. ipac_chip_reset(hw);
  465. hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
  466. hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
  467. hw->ipac.write_reg(hw, IPAC_PCFG, 0x12);
  468. break;
  469. case INF_QS1000:
  470. case INF_QS3000:
  471. ipac_chip_reset(hw);
  472. hw->ipac.write_reg(hw, IPAC_ACFG, 0x00);
  473. hw->ipac.write_reg(hw, IPAC_AOE, 0x3c);
  474. hw->ipac.write_reg(hw, IPAC_ATX, 0xff);
  475. break;
  476. case INF_NICCY:
  477. break;
  478. case INF_SCT_1:
  479. w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
  480. w &= (~SCT_PLX_RESET_BIT);
  481. outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
  482. mdelay(10);
  483. w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
  484. w |= SCT_PLX_RESET_BIT;
  485. outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
  486. mdelay(10);
  487. break;
  488. case INF_GAZEL_R685:
  489. val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
  490. val |= (GAZEL_RESET_9050 + GAZEL_RESET);
  491. outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
  492. val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
  493. mdelay(4);
  494. outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
  495. mdelay(10);
  496. hw->ipac.isac.adf2 = 0x87;
  497. hw->ipac.hscx[0].slot = 0x1f;
  498. hw->ipac.hscx[1].slot = 0x23;
  499. break;
  500. case INF_GAZEL_R753:
  501. val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
  502. val |= (GAZEL_RESET_9050 + GAZEL_RESET);
  503. outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
  504. val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
  505. mdelay(4);
  506. outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
  507. mdelay(10);
  508. ipac_chip_reset(hw);
  509. hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
  510. hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
  511. hw->ipac.conf = 0x01; /* IOM off */
  512. break;
  513. default:
  514. return;
  515. }
  516. enable_hwirq(hw);
  517. }
  518. static int
  519. inf_ctrl(struct inf_hw *hw, u32 cmd, u_long arg)
  520. {
  521. int ret = 0;
  522. switch (cmd) {
  523. case HW_RESET_REQ:
  524. reset_inf(hw);
  525. break;
  526. default:
  527. pr_info("%s: %s unknown command %x %lx\n",
  528. hw->name, __func__, cmd, arg);
  529. ret = -EINVAL;
  530. break;
  531. }
  532. return ret;
  533. }
  534. static int
  535. init_irq(struct inf_hw *hw)
  536. {
  537. int ret, cnt = 3;
  538. u_long flags;
  539. if (!hw->ci->irqfunc)
  540. return -EINVAL;
  541. ret = request_irq(hw->irq, hw->ci->irqfunc, IRQF_SHARED, hw->name, hw);
  542. if (ret) {
  543. pr_info("%s: couldn't get interrupt %d\n", hw->name, hw->irq);
  544. return ret;
  545. }
  546. while (cnt--) {
  547. spin_lock_irqsave(&hw->lock, flags);
  548. reset_inf(hw);
  549. ret = hw->ipac.init(&hw->ipac);
  550. if (ret) {
  551. spin_unlock_irqrestore(&hw->lock, flags);
  552. pr_info("%s: ISAC init failed with %d\n",
  553. hw->name, ret);
  554. break;
  555. }
  556. spin_unlock_irqrestore(&hw->lock, flags);
  557. msleep_interruptible(10);
  558. if (debug & DEBUG_HW)
  559. pr_notice("%s: IRQ %d count %d\n", hw->name,
  560. hw->irq, hw->irqcnt);
  561. if (!hw->irqcnt) {
  562. pr_info("%s: IRQ(%d) got no requests during init %d\n",
  563. hw->name, hw->irq, 3 - cnt);
  564. } else
  565. return 0;
  566. }
  567. free_irq(hw->irq, hw);
  568. return -EIO;
  569. }
  570. static void
  571. release_io(struct inf_hw *hw)
  572. {
  573. if (hw->cfg.mode) {
  574. if (hw->cfg.mode == AM_MEMIO) {
  575. release_mem_region(hw->cfg.start, hw->cfg.size);
  576. if (hw->cfg.p)
  577. iounmap(hw->cfg.p);
  578. } else
  579. release_region(hw->cfg.start, hw->cfg.size);
  580. hw->cfg.mode = AM_NONE;
  581. }
  582. if (hw->addr.mode) {
  583. if (hw->addr.mode == AM_MEMIO) {
  584. release_mem_region(hw->addr.start, hw->addr.size);
  585. if (hw->addr.p)
  586. iounmap(hw->addr.p);
  587. } else
  588. release_region(hw->addr.start, hw->addr.size);
  589. hw->addr.mode = AM_NONE;
  590. }
  591. }
  592. static int
  593. setup_io(struct inf_hw *hw)
  594. {
  595. int err = 0;
  596. if (hw->ci->cfg_mode) {
  597. hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar);
  598. hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar);
  599. if (hw->ci->cfg_mode == AM_MEMIO) {
  600. if (!request_mem_region(hw->cfg.start, hw->cfg.size,
  601. hw->name))
  602. err = -EBUSY;
  603. } else {
  604. if (!request_region(hw->cfg.start, hw->cfg.size,
  605. hw->name))
  606. err = -EBUSY;
  607. }
  608. if (err) {
  609. pr_info("mISDN: %s config port %lx (%lu bytes)"
  610. "already in use\n", hw->name,
  611. (ulong)hw->cfg.start, (ulong)hw->cfg.size);
  612. return err;
  613. }
  614. hw->cfg.mode = hw->ci->cfg_mode;
  615. if (hw->ci->cfg_mode == AM_MEMIO) {
  616. hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
  617. if (!hw->cfg.p)
  618. return -ENOMEM;
  619. }
  620. if (debug & DEBUG_HW)
  621. pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
  622. hw->name, (ulong)hw->cfg.start,
  623. (ulong)hw->cfg.size, hw->ci->cfg_mode);
  624. }
  625. if (hw->ci->addr_mode) {
  626. hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar);
  627. hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar);
  628. if (hw->ci->addr_mode == AM_MEMIO) {
  629. if (!request_mem_region(hw->addr.start, hw->addr.size,
  630. hw->name))
  631. err = -EBUSY;
  632. } else {
  633. if (!request_region(hw->addr.start, hw->addr.size,
  634. hw->name))
  635. err = -EBUSY;
  636. }
  637. if (err) {
  638. pr_info("mISDN: %s address port %lx (%lu bytes)"
  639. "already in use\n", hw->name,
  640. (ulong)hw->addr.start, (ulong)hw->addr.size);
  641. return err;
  642. }
  643. hw->addr.mode = hw->ci->addr_mode;
  644. if (hw->ci->addr_mode == AM_MEMIO) {
  645. hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
  646. if (!hw->addr.p)
  647. return -ENOMEM;
  648. }
  649. if (debug & DEBUG_HW)
  650. pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
  651. hw->name, (ulong)hw->addr.start,
  652. (ulong)hw->addr.size, hw->ci->addr_mode);
  653. }
  654. switch (hw->ci->typ) {
  655. case INF_DIVA20:
  656. case INF_DIVA20U:
  657. hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
  658. hw->isac.mode = hw->cfg.mode;
  659. hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE;
  660. hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT;
  661. hw->hscx.mode = hw->cfg.mode;
  662. hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE;
  663. hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT;
  664. break;
  665. case INF_DIVA201:
  666. hw->ipac.type = IPAC_TYPE_IPAC;
  667. hw->ipac.isac.off = 0x80;
  668. hw->isac.mode = hw->addr.mode;
  669. hw->isac.a.p = hw->addr.p;
  670. hw->hscx.mode = hw->addr.mode;
  671. hw->hscx.a.p = hw->addr.p;
  672. break;
  673. case INF_DIVA202:
  674. hw->ipac.type = IPAC_TYPE_IPACX;
  675. hw->isac.mode = hw->addr.mode;
  676. hw->isac.a.p = hw->addr.p;
  677. hw->hscx.mode = hw->addr.mode;
  678. hw->hscx.a.p = hw->addr.p;
  679. break;
  680. case INF_SPEEDWIN:
  681. case INF_SAPHIR3:
  682. hw->ipac.type = IPAC_TYPE_IPAC;
  683. hw->ipac.isac.off = 0x80;
  684. hw->isac.mode = hw->cfg.mode;
  685. hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
  686. hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
  687. hw->hscx.mode = hw->cfg.mode;
  688. hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
  689. hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
  690. outb(0xff, (ulong)hw->cfg.start);
  691. mdelay(1);
  692. outb(0x00, (ulong)hw->cfg.start);
  693. mdelay(1);
  694. outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL);
  695. break;
  696. case INF_QS1000:
  697. case INF_QS3000:
  698. hw->ipac.type = IPAC_TYPE_IPAC;
  699. hw->ipac.isac.off = 0x80;
  700. hw->isac.a.io.ale = (u32)hw->addr.start;
  701. hw->isac.a.io.port = (u32)hw->addr.start + 1;
  702. hw->isac.mode = hw->addr.mode;
  703. hw->hscx.a.io.ale = (u32)hw->addr.start;
  704. hw->hscx.a.io.port = (u32)hw->addr.start + 1;
  705. hw->hscx.mode = hw->addr.mode;
  706. break;
  707. case INF_NICCY:
  708. hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
  709. hw->isac.mode = hw->addr.mode;
  710. hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE;
  711. hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT;
  712. hw->hscx.mode = hw->addr.mode;
  713. hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE;
  714. hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT;
  715. break;
  716. case INF_SCT_1:
  717. hw->ipac.type = IPAC_TYPE_IPAC;
  718. hw->ipac.isac.off = 0x80;
  719. hw->isac.a.io.ale = (u32)hw->addr.start;
  720. hw->isac.a.io.port = hw->isac.a.io.ale + 4;
  721. hw->isac.mode = hw->addr.mode;
  722. hw->hscx.a.io.ale = hw->isac.a.io.ale;
  723. hw->hscx.a.io.port = hw->isac.a.io.port;
  724. hw->hscx.mode = hw->addr.mode;
  725. break;
  726. case INF_SCT_2:
  727. hw->ipac.type = IPAC_TYPE_IPAC;
  728. hw->ipac.isac.off = 0x80;
  729. hw->isac.a.io.ale = (u32)hw->addr.start + 0x08;
  730. hw->isac.a.io.port = hw->isac.a.io.ale + 4;
  731. hw->isac.mode = hw->addr.mode;
  732. hw->hscx.a.io.ale = hw->isac.a.io.ale;
  733. hw->hscx.a.io.port = hw->isac.a.io.port;
  734. hw->hscx.mode = hw->addr.mode;
  735. break;
  736. case INF_SCT_3:
  737. hw->ipac.type = IPAC_TYPE_IPAC;
  738. hw->ipac.isac.off = 0x80;
  739. hw->isac.a.io.ale = (u32)hw->addr.start + 0x10;
  740. hw->isac.a.io.port = hw->isac.a.io.ale + 4;
  741. hw->isac.mode = hw->addr.mode;
  742. hw->hscx.a.io.ale = hw->isac.a.io.ale;
  743. hw->hscx.a.io.port = hw->isac.a.io.port;
  744. hw->hscx.mode = hw->addr.mode;
  745. break;
  746. case INF_SCT_4:
  747. hw->ipac.type = IPAC_TYPE_IPAC;
  748. hw->ipac.isac.off = 0x80;
  749. hw->isac.a.io.ale = (u32)hw->addr.start + 0x20;
  750. hw->isac.a.io.port = hw->isac.a.io.ale + 4;
  751. hw->isac.mode = hw->addr.mode;
  752. hw->hscx.a.io.ale = hw->isac.a.io.ale;
  753. hw->hscx.a.io.port = hw->isac.a.io.port;
  754. hw->hscx.mode = hw->addr.mode;
  755. break;
  756. case INF_GAZEL_R685:
  757. hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
  758. hw->ipac.isac.off = 0x80;
  759. hw->isac.mode = hw->addr.mode;
  760. hw->isac.a.io.port = (u32)hw->addr.start;
  761. hw->hscx.mode = hw->addr.mode;
  762. hw->hscx.a.io.port = hw->isac.a.io.port;
  763. break;
  764. case INF_GAZEL_R753:
  765. hw->ipac.type = IPAC_TYPE_IPAC;
  766. hw->ipac.isac.off = 0x80;
  767. hw->isac.mode = hw->addr.mode;
  768. hw->isac.a.io.ale = (u32)hw->addr.start;
  769. hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT;
  770. hw->hscx.mode = hw->addr.mode;
  771. hw->hscx.a.io.ale = hw->isac.a.io.ale;
  772. hw->hscx.a.io.port = hw->isac.a.io.port;
  773. break;
  774. default:
  775. return -EINVAL;
  776. }
  777. switch (hw->isac.mode) {
  778. case AM_MEMIO:
  779. ASSIGN_FUNC_IPAC(MIO, hw->ipac);
  780. break;
  781. case AM_IND_IO:
  782. ASSIGN_FUNC_IPAC(IND, hw->ipac);
  783. break;
  784. case AM_IO:
  785. ASSIGN_FUNC_IPAC(IO, hw->ipac);
  786. break;
  787. default:
  788. return -EINVAL;
  789. }
  790. return 0;
  791. }
  792. static void
  793. release_card(struct inf_hw *card) {
  794. ulong flags;
  795. int i;
  796. spin_lock_irqsave(&card->lock, flags);
  797. disable_hwirq(card);
  798. spin_unlock_irqrestore(&card->lock, flags);
  799. card->ipac.isac.release(&card->ipac.isac);
  800. free_irq(card->irq, card);
  801. mISDN_unregister_device(&card->ipac.isac.dch.dev);
  802. release_io(card);
  803. write_lock_irqsave(&card_lock, flags);
  804. list_del(&card->list);
  805. write_unlock_irqrestore(&card_lock, flags);
  806. switch (card->ci->typ) {
  807. case INF_SCT_2:
  808. case INF_SCT_3:
  809. case INF_SCT_4:
  810. break;
  811. case INF_SCT_1:
  812. for (i = 0; i < 3; i++) {
  813. if (card->sc[i])
  814. release_card(card->sc[i]);
  815. card->sc[i] = NULL;
  816. }
  817. fallthrough;
  818. default:
  819. pci_disable_device(card->pdev);
  820. pci_set_drvdata(card->pdev, NULL);
  821. break;
  822. }
  823. kfree(card);
  824. inf_cnt--;
  825. }
  826. static int
  827. setup_instance(struct inf_hw *card)
  828. {
  829. int err;
  830. ulong flags;
  831. snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name,
  832. inf_cnt + 1);
  833. write_lock_irqsave(&card_lock, flags);
  834. list_add_tail(&card->list, &Cards);
  835. write_unlock_irqrestore(&card_lock, flags);
  836. _set_debug(card);
  837. card->ipac.isac.name = card->name;
  838. card->ipac.name = card->name;
  839. card->ipac.owner = THIS_MODULE;
  840. spin_lock_init(&card->lock);
  841. card->ipac.isac.hwlock = &card->lock;
  842. card->ipac.hwlock = &card->lock;
  843. card->ipac.ctrl = (void *)&inf_ctrl;
  844. err = setup_io(card);
  845. if (err)
  846. goto error_setup;
  847. card->ipac.isac.dch.dev.Bprotocols =
  848. mISDNipac_init(&card->ipac, card);
  849. if (card->ipac.isac.dch.dev.Bprotocols == 0)
  850. goto error_setup;
  851. err = mISDN_register_device(&card->ipac.isac.dch.dev,
  852. &card->pdev->dev, card->name);
  853. if (err)
  854. goto error;
  855. err = init_irq(card);
  856. if (!err) {
  857. inf_cnt++;
  858. pr_notice("Infineon %d cards installed\n", inf_cnt);
  859. return 0;
  860. }
  861. mISDN_unregister_device(&card->ipac.isac.dch.dev);
  862. error:
  863. card->ipac.release(&card->ipac);
  864. error_setup:
  865. release_io(card);
  866. write_lock_irqsave(&card_lock, flags);
  867. list_del(&card->list);
  868. write_unlock_irqrestore(&card_lock, flags);
  869. return err;
  870. }
  871. static const struct inf_cinfo inf_card_info[] = {
  872. {
  873. INF_DIVA20,
  874. "Dialogic Diva 2.0",
  875. "diva20",
  876. AM_IND_IO, AM_NONE, 2, 0,
  877. &diva_irq
  878. },
  879. {
  880. INF_DIVA20U,
  881. "Dialogic Diva 2.0U",
  882. "diva20U",
  883. AM_IND_IO, AM_NONE, 2, 0,
  884. &diva_irq
  885. },
  886. {
  887. INF_DIVA201,
  888. "Dialogic Diva 2.01",
  889. "diva201",
  890. AM_MEMIO, AM_MEMIO, 0, 1,
  891. &diva20x_irq
  892. },
  893. {
  894. INF_DIVA202,
  895. "Dialogic Diva 2.02",
  896. "diva202",
  897. AM_MEMIO, AM_MEMIO, 0, 1,
  898. &diva20x_irq
  899. },
  900. {
  901. INF_SPEEDWIN,
  902. "Sedlbauer SpeedWin PCI",
  903. "speedwin",
  904. AM_IND_IO, AM_NONE, 0, 0,
  905. &tiger_irq
  906. },
  907. {
  908. INF_SAPHIR3,
  909. "HST Saphir 3",
  910. "saphir",
  911. AM_IND_IO, AM_NONE, 0, 0,
  912. &tiger_irq
  913. },
  914. {
  915. INF_QS1000,
  916. "Develo Microlink PCI",
  917. "qs1000",
  918. AM_IO, AM_IND_IO, 1, 3,
  919. &elsa_irq
  920. },
  921. {
  922. INF_QS3000,
  923. "Develo QuickStep 3000",
  924. "qs3000",
  925. AM_IO, AM_IND_IO, 1, 3,
  926. &elsa_irq
  927. },
  928. {
  929. INF_NICCY,
  930. "Sagem NICCY",
  931. "niccy",
  932. AM_IO, AM_IND_IO, 0, 1,
  933. &niccy_irq
  934. },
  935. {
  936. INF_SCT_1,
  937. "SciTel Quadro",
  938. "p1_scitel",
  939. AM_IO, AM_IND_IO, 1, 5,
  940. &ipac_irq
  941. },
  942. {
  943. INF_SCT_2,
  944. "SciTel Quadro",
  945. "p2_scitel",
  946. AM_NONE, AM_IND_IO, 0, 4,
  947. &ipac_irq
  948. },
  949. {
  950. INF_SCT_3,
  951. "SciTel Quadro",
  952. "p3_scitel",
  953. AM_NONE, AM_IND_IO, 0, 3,
  954. &ipac_irq
  955. },
  956. {
  957. INF_SCT_4,
  958. "SciTel Quadro",
  959. "p4_scitel",
  960. AM_NONE, AM_IND_IO, 0, 2,
  961. &ipac_irq
  962. },
  963. {
  964. INF_GAZEL_R685,
  965. "Gazel R685",
  966. "gazel685",
  967. AM_IO, AM_IO, 1, 2,
  968. &gazel_irq
  969. },
  970. {
  971. INF_GAZEL_R753,
  972. "Gazel R753",
  973. "gazel753",
  974. AM_IO, AM_IND_IO, 1, 2,
  975. &ipac_irq
  976. },
  977. {
  978. INF_NONE,
  979. }
  980. };
  981. static const struct inf_cinfo *
  982. get_card_info(enum inf_types typ)
  983. {
  984. const struct inf_cinfo *ci = inf_card_info;
  985. while (ci->typ != INF_NONE) {
  986. if (ci->typ == typ)
  987. return ci;
  988. ci++;
  989. }
  990. return NULL;
  991. }
  992. static int
  993. inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  994. {
  995. int err = -ENOMEM;
  996. struct inf_hw *card;
  997. card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
  998. if (!card) {
  999. pr_info("No memory for Infineon ISDN card\n");
  1000. return err;
  1001. }
  1002. card->pdev = pdev;
  1003. err = pci_enable_device(pdev);
  1004. if (err) {
  1005. kfree(card);
  1006. return err;
  1007. }
  1008. card->ci = get_card_info(ent->driver_data);
  1009. if (!card->ci) {
  1010. pr_info("mISDN: do not have information about adapter at %s\n",
  1011. pci_name(pdev));
  1012. kfree(card);
  1013. pci_disable_device(pdev);
  1014. return -EINVAL;
  1015. } else
  1016. pr_notice("mISDN: found adapter %s at %s\n",
  1017. card->ci->full, pci_name(pdev));
  1018. card->irq = pdev->irq;
  1019. pci_set_drvdata(pdev, card);
  1020. err = setup_instance(card);
  1021. if (err) {
  1022. pci_disable_device(pdev);
  1023. kfree(card);
  1024. pci_set_drvdata(pdev, NULL);
  1025. } else if (ent->driver_data == INF_SCT_1) {
  1026. int i;
  1027. struct inf_hw *sc;
  1028. for (i = 1; i < 4; i++) {
  1029. sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
  1030. if (!sc) {
  1031. release_card(card);
  1032. pci_disable_device(pdev);
  1033. return -ENOMEM;
  1034. }
  1035. sc->irq = card->irq;
  1036. sc->pdev = card->pdev;
  1037. sc->ci = card->ci + i;
  1038. err = setup_instance(sc);
  1039. if (err) {
  1040. pci_disable_device(pdev);
  1041. kfree(sc);
  1042. release_card(card);
  1043. break;
  1044. } else
  1045. card->sc[i - 1] = sc;
  1046. }
  1047. }
  1048. return err;
  1049. }
  1050. static void
  1051. inf_remove(struct pci_dev *pdev)
  1052. {
  1053. struct inf_hw *card = pci_get_drvdata(pdev);
  1054. if (card)
  1055. release_card(card);
  1056. else
  1057. pr_debug("%s: drvdata already removed\n", __func__);
  1058. }
  1059. static struct pci_driver infineon_driver = {
  1060. .name = "ISDN Infineon pci",
  1061. .probe = inf_probe,
  1062. .remove = inf_remove,
  1063. .id_table = infineon_ids,
  1064. };
  1065. static int __init
  1066. infineon_init(void)
  1067. {
  1068. int err;
  1069. pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV);
  1070. err = pci_register_driver(&infineon_driver);
  1071. return err;
  1072. }
  1073. static void __exit
  1074. infineon_cleanup(void)
  1075. {
  1076. pci_unregister_driver(&infineon_driver);
  1077. }
  1078. module_init(infineon_init);
  1079. module_exit(infineon_cleanup);