teleint.c 7.8 KB

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