teleint.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /* $Id: teleint.c,v 1.16.2.5 2004/01/19 15:31:50 keil Exp $
  2. *
  3. * low level stuff for TeleInt isdn cards
  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 "hisax.h"
  14. #include "isac.h"
  15. #include "hfc_2bs0.h"
  16. #include "isdnl1.h"
  17. static const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
  18. #define byteout(addr,val) outb(val,addr)
  19. #define bytein(addr) inb(addr)
  20. static inline u_char
  21. readreg(unsigned int ale, unsigned int adr, u_char off)
  22. {
  23. register u_char ret;
  24. int max_delay = 2000;
  25. byteout(ale, off);
  26. ret = HFC_BUSY & bytein(ale);
  27. while (ret && --max_delay)
  28. ret = HFC_BUSY & bytein(ale);
  29. if (!max_delay) {
  30. printk(KERN_WARNING "TeleInt Busy not inactive\n");
  31. return (0);
  32. }
  33. ret = bytein(adr);
  34. return (ret);
  35. }
  36. static inline void
  37. readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
  38. {
  39. register u_char ret;
  40. register int max_delay = 20000;
  41. register int i;
  42. byteout(ale, off);
  43. for (i = 0; i<size; i++) {
  44. ret = HFC_BUSY & bytein(ale);
  45. while (ret && --max_delay)
  46. ret = HFC_BUSY & bytein(ale);
  47. if (!max_delay) {
  48. printk(KERN_WARNING "TeleInt Busy not inactive\n");
  49. return;
  50. }
  51. data[i] = bytein(adr);
  52. }
  53. }
  54. static inline void
  55. writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
  56. {
  57. register u_char ret;
  58. int max_delay = 2000;
  59. byteout(ale, off);
  60. ret = HFC_BUSY & bytein(ale);
  61. while (ret && --max_delay)
  62. ret = HFC_BUSY & bytein(ale);
  63. if (!max_delay) {
  64. printk(KERN_WARNING "TeleInt Busy not inactive\n");
  65. return;
  66. }
  67. byteout(adr, data);
  68. }
  69. static inline void
  70. writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
  71. {
  72. register u_char ret;
  73. register int max_delay = 20000;
  74. register int i;
  75. byteout(ale, off);
  76. for (i = 0; i<size; i++) {
  77. ret = HFC_BUSY & bytein(ale);
  78. while (ret && --max_delay)
  79. ret = HFC_BUSY & bytein(ale);
  80. if (!max_delay) {
  81. printk(KERN_WARNING "TeleInt Busy not inactive\n");
  82. return;
  83. }
  84. byteout(adr, data[i]);
  85. }
  86. }
  87. /* Interface functions */
  88. static u_char
  89. ReadISAC(struct IsdnCardState *cs, u_char offset)
  90. {
  91. cs->hw.hfc.cip = offset;
  92. return (readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset));
  93. }
  94. static void
  95. WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  96. {
  97. cs->hw.hfc.cip = offset;
  98. writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset, value);
  99. }
  100. static void
  101. ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  102. {
  103. cs->hw.hfc.cip = 0;
  104. readfifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size);
  105. }
  106. static void
  107. WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  108. {
  109. cs->hw.hfc.cip = 0;
  110. writefifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size);
  111. }
  112. static u_char
  113. ReadHFC(struct IsdnCardState *cs, int data, u_char reg)
  114. {
  115. register u_char ret;
  116. if (data) {
  117. cs->hw.hfc.cip = reg;
  118. byteout(cs->hw.hfc.addr | 1, reg);
  119. ret = bytein(cs->hw.hfc.addr);
  120. if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
  121. debugl1(cs, "hfc RD %02x %02x", reg, ret);
  122. } else
  123. ret = bytein(cs->hw.hfc.addr | 1);
  124. return (ret);
  125. }
  126. static void
  127. WriteHFC(struct IsdnCardState *cs, int data, u_char reg, u_char value)
  128. {
  129. byteout(cs->hw.hfc.addr | 1, reg);
  130. cs->hw.hfc.cip = reg;
  131. if (data)
  132. byteout(cs->hw.hfc.addr, value);
  133. if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
  134. debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
  135. }
  136. static irqreturn_t
  137. TeleInt_interrupt(int intno, void *dev_id)
  138. {
  139. struct IsdnCardState *cs = dev_id;
  140. u_char val;
  141. u_long flags;
  142. spin_lock_irqsave(&cs->lock, flags);
  143. val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
  144. Start_ISAC:
  145. if (val)
  146. isac_interrupt(cs, val);
  147. val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
  148. if (val) {
  149. if (cs->debug & L1_DEB_ISAC)
  150. debugl1(cs, "ISAC IntStat after IntRoutine");
  151. goto Start_ISAC;
  152. }
  153. writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
  154. writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
  155. spin_unlock_irqrestore(&cs->lock, flags);
  156. return IRQ_HANDLED;
  157. }
  158. static void
  159. TeleInt_Timer(struct IsdnCardState *cs)
  160. {
  161. int stat = 0;
  162. u_long flags;
  163. spin_lock_irqsave(&cs->lock, flags);
  164. if (cs->bcs[0].mode) {
  165. stat |= 1;
  166. main_irq_hfc(&cs->bcs[0]);
  167. }
  168. if (cs->bcs[1].mode) {
  169. stat |= 2;
  170. main_irq_hfc(&cs->bcs[1]);
  171. }
  172. spin_unlock_irqrestore(&cs->lock, flags);
  173. stat = HZ/100;
  174. if (!stat)
  175. stat = 1;
  176. cs->hw.hfc.timer.expires = jiffies + stat;
  177. add_timer(&cs->hw.hfc.timer);
  178. }
  179. static void
  180. release_io_TeleInt(struct IsdnCardState *cs)
  181. {
  182. del_timer(&cs->hw.hfc.timer);
  183. releasehfc(cs);
  184. if (cs->hw.hfc.addr)
  185. release_region(cs->hw.hfc.addr, 2);
  186. }
  187. static void
  188. reset_TeleInt(struct IsdnCardState *cs)
  189. {
  190. printk(KERN_INFO "TeleInt: resetting card\n");
  191. cs->hw.hfc.cirm |= HFC_RESET;
  192. byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset On */
  193. mdelay(10);
  194. cs->hw.hfc.cirm &= ~HFC_RESET;
  195. byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */
  196. mdelay(10);
  197. }
  198. static int
  199. TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  200. {
  201. u_long flags;
  202. int delay;
  203. switch (mt) {
  204. case CARD_RESET:
  205. spin_lock_irqsave(&cs->lock, flags);
  206. reset_TeleInt(cs);
  207. spin_unlock_irqrestore(&cs->lock, flags);
  208. return(0);
  209. case CARD_RELEASE:
  210. release_io_TeleInt(cs);
  211. return(0);
  212. case CARD_INIT:
  213. spin_lock_irqsave(&cs->lock, flags);
  214. reset_TeleInt(cs);
  215. inithfc(cs);
  216. clear_pending_isac_ints(cs);
  217. initisac(cs);
  218. /* Reenable all IRQ */
  219. cs->writeisac(cs, ISAC_MASK, 0);
  220. cs->writeisac(cs, ISAC_CMDR, 0x41);
  221. spin_unlock_irqrestore(&cs->lock, flags);
  222. delay = HZ/100;
  223. if (!delay)
  224. delay = 1;
  225. cs->hw.hfc.timer.expires = jiffies + delay;
  226. add_timer(&cs->hw.hfc.timer);
  227. return(0);
  228. case CARD_TEST:
  229. return(0);
  230. }
  231. return(0);
  232. }
  233. int __devinit
  234. setup_TeleInt(struct IsdnCard *card)
  235. {
  236. struct IsdnCardState *cs = card->cs;
  237. char tmp[64];
  238. strcpy(tmp, TeleInt_revision);
  239. printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
  240. if (cs->typ != ISDN_CTYPE_TELEINT)
  241. return (0);
  242. cs->hw.hfc.addr = card->para[1] & 0x3fe;
  243. cs->irq = card->para[0];
  244. cs->hw.hfc.cirm = HFC_CIRM;
  245. cs->hw.hfc.isac_spcr = 0x00;
  246. cs->hw.hfc.cip = 0;
  247. cs->hw.hfc.ctmt = HFC_CTMT | HFC_CLTIMER;
  248. cs->bcs[0].hw.hfc.send = NULL;
  249. cs->bcs[1].hw.hfc.send = NULL;
  250. cs->hw.hfc.fifosize = 7 * 1024 + 512;
  251. cs->hw.hfc.timer.function = (void *) TeleInt_Timer;
  252. cs->hw.hfc.timer.data = (long) cs;
  253. init_timer(&cs->hw.hfc.timer);
  254. if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) {
  255. printk(KERN_WARNING
  256. "HiSax: TeleInt config port %x-%x already in use\n",
  257. cs->hw.hfc.addr,
  258. cs->hw.hfc.addr + 2);
  259. return (0);
  260. }
  261. /* HW IO = IO */
  262. byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
  263. byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54);
  264. switch (cs->irq) {
  265. case 3:
  266. cs->hw.hfc.cirm |= HFC_INTA;
  267. break;
  268. case 4:
  269. cs->hw.hfc.cirm |= HFC_INTB;
  270. break;
  271. case 5:
  272. cs->hw.hfc.cirm |= HFC_INTC;
  273. break;
  274. case 7:
  275. cs->hw.hfc.cirm |= HFC_INTD;
  276. break;
  277. case 10:
  278. cs->hw.hfc.cirm |= HFC_INTE;
  279. break;
  280. case 11:
  281. cs->hw.hfc.cirm |= HFC_INTF;
  282. break;
  283. default:
  284. printk(KERN_WARNING "TeleInt: wrong IRQ\n");
  285. release_io_TeleInt(cs);
  286. return (0);
  287. }
  288. byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
  289. byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
  290. printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n",
  291. cs->hw.hfc.addr, cs->irq);
  292. setup_isac(cs);
  293. cs->readisac = &ReadISAC;
  294. cs->writeisac = &WriteISAC;
  295. cs->readisacfifo = &ReadISACfifo;
  296. cs->writeisacfifo = &WriteISACfifo;
  297. cs->BC_Read_Reg = &ReadHFC;
  298. cs->BC_Write_Reg = &WriteHFC;
  299. cs->cardmsg = &TeleInt_card_msg;
  300. cs->irq_func = &TeleInt_interrupt;
  301. ISACVersion(cs, "TeleInt:");
  302. return (1);
  303. }