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