hfcscard.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /* $Id: hfcscard.c,v 1.10.2.4 2004/01/14 16:04:48 keil Exp $
  2. *
  3. * low level stuff for hfcs based cards (Teles3c, ACER P10)
  4. *
  5. * Author Karsten Keil
  6. * Copyright by Karsten Keil <keil@isdn4linux.de>
  7. *
  8. * This software may be used and distributed according to the terms
  9. * of the GNU General Public License, incorporated herein by reference.
  10. *
  11. */
  12. #include <linux/init.h>
  13. #include <linux/isapnp.h>
  14. #include "hisax.h"
  15. #include "hfc_2bds0.h"
  16. #include "isdnl1.h"
  17. static const char *hfcs_revision = "$Revision: 1.10.2.4 $";
  18. static irqreturn_t
  19. hfcs_interrupt(int intno, void *dev_id)
  20. {
  21. struct IsdnCardState *cs = dev_id;
  22. u_char val, stat;
  23. u_long flags;
  24. spin_lock_irqsave(&cs->lock, flags);
  25. if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) &
  26. (stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
  27. val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
  28. if (cs->debug & L1_DEB_ISAC)
  29. debugl1(cs, "HFCS: stat(%02x) s1(%02x)", stat, val);
  30. hfc2bds0_interrupt(cs, val);
  31. } else {
  32. if (cs->debug & L1_DEB_ISAC)
  33. debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat);
  34. }
  35. spin_unlock_irqrestore(&cs->lock, flags);
  36. return IRQ_HANDLED;
  37. }
  38. static void
  39. hfcs_Timer(struct IsdnCardState *cs)
  40. {
  41. cs->hw.hfcD.timer.expires = jiffies + 75;
  42. /* WD RESET */
  43. /* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
  44. add_timer(&cs->hw.hfcD.timer);
  45. */
  46. }
  47. static void
  48. release_io_hfcs(struct IsdnCardState *cs)
  49. {
  50. release2bds0(cs);
  51. del_timer(&cs->hw.hfcD.timer);
  52. if (cs->hw.hfcD.addr)
  53. release_region(cs->hw.hfcD.addr, 2);
  54. }
  55. static void
  56. reset_hfcs(struct IsdnCardState *cs)
  57. {
  58. printk(KERN_INFO "HFCS: resetting card\n");
  59. cs->hw.hfcD.cirm = HFCD_RESET;
  60. if (cs->typ == ISDN_CTYPE_TELES3C)
  61. cs->hw.hfcD.cirm |= HFCD_MEM8K;
  62. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */
  63. mdelay(10);
  64. cs->hw.hfcD.cirm = 0;
  65. if (cs->typ == ISDN_CTYPE_TELES3C)
  66. cs->hw.hfcD.cirm |= HFCD_MEM8K;
  67. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */
  68. mdelay(10);
  69. if (cs->typ == ISDN_CTYPE_TELES3C)
  70. cs->hw.hfcD.cirm |= HFCD_INTB;
  71. else if (cs->typ == ISDN_CTYPE_ACERP10)
  72. cs->hw.hfcD.cirm |= HFCD_INTA;
  73. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);
  74. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e);
  75. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */
  76. cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER;
  77. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
  78. cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE;
  79. cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS |
  80. HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC |
  81. HFCD_INTS_DREC | HFCD_INTS_L1STATE;
  82. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1);
  83. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2);
  84. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */
  85. udelay(10);
  86. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */
  87. cs->hw.hfcD.mst_m = HFCD_MASTER;
  88. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */
  89. cs->hw.hfcD.sctrl = 0;
  90. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl);
  91. }
  92. static int
  93. hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  94. {
  95. u_long flags;
  96. int delay;
  97. if (cs->debug & L1_DEB_ISAC)
  98. debugl1(cs, "HFCS: card_msg %x", mt);
  99. switch (mt) {
  100. case CARD_RESET:
  101. spin_lock_irqsave(&cs->lock, flags);
  102. reset_hfcs(cs);
  103. spin_unlock_irqrestore(&cs->lock, flags);
  104. return (0);
  105. case CARD_RELEASE:
  106. release_io_hfcs(cs);
  107. return (0);
  108. case CARD_INIT:
  109. delay = (75 * HZ) / 100 + 1;
  110. mod_timer(&cs->hw.hfcD.timer, jiffies + delay);
  111. spin_lock_irqsave(&cs->lock, flags);
  112. reset_hfcs(cs);
  113. init2bds0(cs);
  114. spin_unlock_irqrestore(&cs->lock, flags);
  115. delay = (80 * HZ) / 1000 + 1;
  116. msleep(80);
  117. spin_lock_irqsave(&cs->lock, flags);
  118. cs->hw.hfcD.ctmt |= HFCD_TIM800;
  119. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
  120. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
  121. spin_unlock_irqrestore(&cs->lock, flags);
  122. return (0);
  123. case CARD_TEST:
  124. return (0);
  125. }
  126. return (0);
  127. }
  128. #ifdef __ISAPNP__
  129. static struct isapnp_device_id hfc_ids[] = {
  130. { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
  131. ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
  132. (unsigned long) "Acer P10" },
  133. { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
  134. ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
  135. (unsigned long) "Billion 2" },
  136. { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
  137. ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
  138. (unsigned long) "Billion 1" },
  139. { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
  140. ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
  141. (unsigned long) "IStar PnP" },
  142. { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
  143. ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
  144. (unsigned long) "Teles 16.3c" },
  145. { ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
  146. ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
  147. (unsigned long) "Tornado Tipa C" },
  148. { ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
  149. ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
  150. (unsigned long) "Genius Speed Surfer" },
  151. { 0, }
  152. };
  153. static struct isapnp_device_id *ipid = &hfc_ids[0];
  154. static struct pnp_card *pnp_c = NULL;
  155. #endif
  156. int setup_hfcs(struct IsdnCard *card)
  157. {
  158. struct IsdnCardState *cs = card->cs;
  159. char tmp[64];
  160. strcpy(tmp, hfcs_revision);
  161. printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
  162. #ifdef __ISAPNP__
  163. if (!card->para[1] && isapnp_present()) {
  164. struct pnp_dev *pnp_d;
  165. while (ipid->card_vendor) {
  166. if ((pnp_c = pnp_find_card(ipid->card_vendor,
  167. ipid->card_device, pnp_c))) {
  168. pnp_d = NULL;
  169. if ((pnp_d = pnp_find_dev(pnp_c,
  170. ipid->vendor, ipid->function, pnp_d))) {
  171. int err;
  172. printk(KERN_INFO "HiSax: %s detected\n",
  173. (char *)ipid->driver_data);
  174. pnp_disable_dev(pnp_d);
  175. err = pnp_activate_dev(pnp_d);
  176. if (err < 0) {
  177. printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
  178. __func__, err);
  179. return (0);
  180. }
  181. card->para[1] = pnp_port_start(pnp_d, 0);
  182. card->para[0] = pnp_irq(pnp_d, 0);
  183. if (!card->para[0] || !card->para[1]) {
  184. printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
  185. card->para[0], card->para[1]);
  186. pnp_disable_dev(pnp_d);
  187. return (0);
  188. }
  189. break;
  190. } else {
  191. printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
  192. }
  193. }
  194. ipid++;
  195. pnp_c = NULL;
  196. }
  197. if (!ipid->card_vendor) {
  198. printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
  199. return (0);
  200. }
  201. }
  202. #endif
  203. cs->hw.hfcD.addr = card->para[1] & 0xfffe;
  204. cs->irq = card->para[0];
  205. cs->hw.hfcD.cip = 0;
  206. cs->hw.hfcD.int_s1 = 0;
  207. cs->hw.hfcD.send = NULL;
  208. cs->bcs[0].hw.hfc.send = NULL;
  209. cs->bcs[1].hw.hfc.send = NULL;
  210. cs->hw.hfcD.dfifosize = 512;
  211. cs->dc.hfcd.ph_state = 0;
  212. cs->hw.hfcD.fifo = 255;
  213. if (cs->typ == ISDN_CTYPE_TELES3C) {
  214. cs->hw.hfcD.bfifosize = 1024 + 512;
  215. } else if (cs->typ == ISDN_CTYPE_ACERP10) {
  216. cs->hw.hfcD.bfifosize = 7 * 1024 + 512;
  217. } else
  218. return (0);
  219. if (!request_region(cs->hw.hfcD.addr, 2, "HFCS isdn")) {
  220. printk(KERN_WARNING
  221. "HiSax: %s config port %x-%x already in use\n",
  222. CardType[card->typ],
  223. cs->hw.hfcD.addr,
  224. cs->hw.hfcD.addr + 2);
  225. return (0);
  226. }
  227. printk(KERN_INFO
  228. "HFCS: defined at 0x%x IRQ %d HZ %d\n",
  229. cs->hw.hfcD.addr,
  230. cs->irq, HZ);
  231. if (cs->typ == ISDN_CTYPE_TELES3C) {
  232. /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
  233. outb(0x00, cs->hw.hfcD.addr);
  234. outb(0x56, cs->hw.hfcD.addr | 1);
  235. } else if (cs->typ == ISDN_CTYPE_ACERP10) {
  236. /* Acer P10 IO ADR is 0x300 */
  237. outb(0x00, cs->hw.hfcD.addr);
  238. outb(0x57, cs->hw.hfcD.addr | 1);
  239. }
  240. set_cs_func(cs);
  241. cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
  242. cs->hw.hfcD.timer.data = (long) cs;
  243. init_timer(&cs->hw.hfcD.timer);
  244. cs->cardmsg = &hfcs_card_msg;
  245. cs->irq_func = &hfcs_interrupt;
  246. return (1);
  247. }