hfcscard.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. 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[] __devinitdata = {
  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 __devinitdata = &hfc_ids[0];
  155. static struct pnp_card *pnp_c __devinitdata = NULL;
  156. #endif
  157. int __devinit
  158. setup_hfcs(struct IsdnCard *card)
  159. {
  160. struct IsdnCardState *cs = card->cs;
  161. char tmp[64];
  162. strcpy(tmp, hfcs_revision);
  163. printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
  164. #ifdef __ISAPNP__
  165. if (!card->para[1] && isapnp_present()) {
  166. struct pnp_dev *pnp_d;
  167. while(ipid->card_vendor) {
  168. if ((pnp_c = pnp_find_card(ipid->card_vendor,
  169. ipid->card_device, pnp_c))) {
  170. pnp_d = NULL;
  171. if ((pnp_d = pnp_find_dev(pnp_c,
  172. ipid->vendor, ipid->function, pnp_d))) {
  173. int err;
  174. printk(KERN_INFO "HiSax: %s detected\n",
  175. (char *)ipid->driver_data);
  176. pnp_disable_dev(pnp_d);
  177. err = pnp_activate_dev(pnp_d);
  178. if (err<0) {
  179. printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
  180. __func__, err);
  181. return(0);
  182. }
  183. card->para[1] = pnp_port_start(pnp_d, 0);
  184. card->para[0] = pnp_irq(pnp_d, 0);
  185. if (!card->para[0] || !card->para[1]) {
  186. printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
  187. card->para[0], card->para[1]);
  188. pnp_disable_dev(pnp_d);
  189. return(0);
  190. }
  191. break;
  192. } else {
  193. printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
  194. }
  195. }
  196. ipid++;
  197. pnp_c = NULL;
  198. }
  199. if (!ipid->card_vendor) {
  200. printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
  201. return(0);
  202. }
  203. }
  204. #endif
  205. cs->hw.hfcD.addr = card->para[1] & 0xfffe;
  206. cs->irq = card->para[0];
  207. cs->hw.hfcD.cip = 0;
  208. cs->hw.hfcD.int_s1 = 0;
  209. cs->hw.hfcD.send = NULL;
  210. cs->bcs[0].hw.hfc.send = NULL;
  211. cs->bcs[1].hw.hfc.send = NULL;
  212. cs->hw.hfcD.dfifosize = 512;
  213. cs->dc.hfcd.ph_state = 0;
  214. cs->hw.hfcD.fifo = 255;
  215. if (cs->typ == ISDN_CTYPE_TELES3C) {
  216. cs->hw.hfcD.bfifosize = 1024 + 512;
  217. } else if (cs->typ == ISDN_CTYPE_ACERP10) {
  218. cs->hw.hfcD.bfifosize = 7*1024 + 512;
  219. } else
  220. return (0);
  221. if (!request_region(cs->hw.hfcD.addr, 2, "HFCS isdn")) {
  222. printk(KERN_WARNING
  223. "HiSax: %s config port %x-%x already in use\n",
  224. CardType[card->typ],
  225. cs->hw.hfcD.addr,
  226. cs->hw.hfcD.addr + 2);
  227. return (0);
  228. }
  229. printk(KERN_INFO
  230. "HFCS: defined at 0x%x IRQ %d HZ %d\n",
  231. cs->hw.hfcD.addr,
  232. cs->irq, HZ);
  233. if (cs->typ == ISDN_CTYPE_TELES3C) {
  234. /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
  235. outb(0x00, cs->hw.hfcD.addr);
  236. outb(0x56, cs->hw.hfcD.addr | 1);
  237. } else if (cs->typ == ISDN_CTYPE_ACERP10) {
  238. /* Acer P10 IO ADR is 0x300 */
  239. outb(0x00, cs->hw.hfcD.addr);
  240. outb(0x57, cs->hw.hfcD.addr | 1);
  241. }
  242. set_cs_func(cs);
  243. cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
  244. cs->hw.hfcD.timer.data = (long) cs;
  245. init_timer(&cs->hw.hfcD.timer);
  246. cs->cardmsg = &hfcs_card_msg;
  247. cs->irq_func = &hfcs_interrupt;
  248. return (1);
  249. }