hfcscard.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. extern const char *CardType[];
  18. static const char *hfcs_revision = "$Revision: 1.10.2.4 $";
  19. static irqreturn_t
  20. hfcs_interrupt(int intno, void *dev_id)
  21. {
  22. struct IsdnCardState *cs = dev_id;
  23. u_char val, stat;
  24. u_long flags;
  25. spin_lock_irqsave(&cs->lock, flags);
  26. if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) &
  27. (stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
  28. val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
  29. if (cs->debug & L1_DEB_ISAC)
  30. debugl1(cs, "HFCS: stat(%02x) s1(%02x)", stat, val);
  31. hfc2bds0_interrupt(cs, val);
  32. } else {
  33. if (cs->debug & L1_DEB_ISAC)
  34. debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat);
  35. }
  36. spin_unlock_irqrestore(&cs->lock, flags);
  37. return IRQ_HANDLED;
  38. }
  39. static void
  40. hfcs_Timer(struct IsdnCardState *cs)
  41. {
  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. cs->hw.hfcD.timer.expires = jiffies + delay;
  112. add_timer(&cs->hw.hfcD.timer);
  113. spin_lock_irqsave(&cs->lock, flags);
  114. reset_hfcs(cs);
  115. init2bds0(cs);
  116. spin_unlock_irqrestore(&cs->lock, flags);
  117. delay = (80*HZ)/1000 +1;
  118. msleep(80);
  119. spin_lock_irqsave(&cs->lock, flags);
  120. cs->hw.hfcD.ctmt |= HFCD_TIM800;
  121. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
  122. cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
  123. spin_unlock_irqrestore(&cs->lock, flags);
  124. return(0);
  125. case CARD_TEST:
  126. return(0);
  127. }
  128. return(0);
  129. }
  130. #ifdef __ISAPNP__
  131. static struct isapnp_device_id hfc_ids[] __devinitdata = {
  132. { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
  133. ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
  134. (unsigned long) "Acer P10" },
  135. { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
  136. ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
  137. (unsigned long) "Billion 2" },
  138. { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
  139. ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
  140. (unsigned long) "Billion 1" },
  141. { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
  142. ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
  143. (unsigned long) "IStar PnP" },
  144. { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
  145. ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
  146. (unsigned long) "Teles 16.3c" },
  147. { ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
  148. ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
  149. (unsigned long) "Tornado Tipa C" },
  150. { ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
  151. ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
  152. (unsigned long) "Genius Speed Surfer" },
  153. { 0, }
  154. };
  155. static struct isapnp_device_id *ipid __devinitdata = &hfc_ids[0];
  156. static struct pnp_card *pnp_c __devinitdata = NULL;
  157. #endif
  158. int __devinit
  159. setup_hfcs(struct IsdnCard *card)
  160. {
  161. struct IsdnCardState *cs = card->cs;
  162. char tmp[64];
  163. strcpy(tmp, hfcs_revision);
  164. printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
  165. #ifdef __ISAPNP__
  166. if (!card->para[1] && isapnp_present()) {
  167. struct pnp_dev *pnp_d;
  168. while(ipid->card_vendor) {
  169. if ((pnp_c = pnp_find_card(ipid->card_vendor,
  170. ipid->card_device, pnp_c))) {
  171. pnp_d = NULL;
  172. if ((pnp_d = pnp_find_dev(pnp_c,
  173. ipid->vendor, ipid->function, pnp_d))) {
  174. int err;
  175. printk(KERN_INFO "HiSax: %s detected\n",
  176. (char *)ipid->driver_data);
  177. pnp_disable_dev(pnp_d);
  178. err = pnp_activate_dev(pnp_d);
  179. if (err<0) {
  180. printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
  181. __FUNCTION__, err);
  182. return(0);
  183. }
  184. card->para[1] = pnp_port_start(pnp_d, 0);
  185. card->para[0] = pnp_irq(pnp_d, 0);
  186. if (!card->para[0] || !card->para[1]) {
  187. printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
  188. card->para[0], card->para[1]);
  189. pnp_disable_dev(pnp_d);
  190. return(0);
  191. }
  192. break;
  193. } else {
  194. printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
  195. }
  196. }
  197. ipid++;
  198. pnp_c = NULL;
  199. }
  200. if (!ipid->card_vendor) {
  201. printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
  202. return(0);
  203. }
  204. }
  205. #endif
  206. cs->hw.hfcD.addr = card->para[1] & 0xfffe;
  207. cs->irq = card->para[0];
  208. cs->hw.hfcD.cip = 0;
  209. cs->hw.hfcD.int_s1 = 0;
  210. cs->hw.hfcD.send = NULL;
  211. cs->bcs[0].hw.hfc.send = NULL;
  212. cs->bcs[1].hw.hfc.send = NULL;
  213. cs->hw.hfcD.dfifosize = 512;
  214. cs->dc.hfcd.ph_state = 0;
  215. cs->hw.hfcD.fifo = 255;
  216. if (cs->typ == ISDN_CTYPE_TELES3C) {
  217. cs->hw.hfcD.bfifosize = 1024 + 512;
  218. } else if (cs->typ == ISDN_CTYPE_ACERP10) {
  219. cs->hw.hfcD.bfifosize = 7*1024 + 512;
  220. } else
  221. return (0);
  222. if (!request_region(cs->hw.hfcD.addr, 2, "HFCS isdn")) {
  223. printk(KERN_WARNING
  224. "HiSax: %s config port %x-%x already in use\n",
  225. CardType[card->typ],
  226. cs->hw.hfcD.addr,
  227. cs->hw.hfcD.addr + 2);
  228. return (0);
  229. }
  230. printk(KERN_INFO
  231. "HFCS: defined at 0x%x IRQ %d HZ %d\n",
  232. cs->hw.hfcD.addr,
  233. cs->irq, HZ);
  234. if (cs->typ == ISDN_CTYPE_TELES3C) {
  235. /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
  236. outb(0x00, cs->hw.hfcD.addr);
  237. outb(0x56, cs->hw.hfcD.addr | 1);
  238. } else if (cs->typ == ISDN_CTYPE_ACERP10) {
  239. /* Acer P10 IO ADR is 0x300 */
  240. outb(0x00, cs->hw.hfcD.addr);
  241. outb(0x57, cs->hw.hfcD.addr | 1);
  242. }
  243. set_cs_func(cs);
  244. cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
  245. cs->hw.hfcD.timer.data = (long) cs;
  246. init_timer(&cs->hw.hfcD.timer);
  247. cs->cardmsg = &hfcs_card_msg;
  248. cs->irq_func = &hfcs_interrupt;
  249. return (1);
  250. }