saphir.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /* $Id: saphir.c,v 1.10.2.4 2004/01/13 23:48:39 keil Exp $
  2. *
  3. * low level stuff for HST Saphir 1
  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. * Thanks to HST High Soft Tech GmbH
  12. *
  13. */
  14. #include <linux/init.h>
  15. #include "hisax.h"
  16. #include "isac.h"
  17. #include "hscx.h"
  18. #include "isdnl1.h"
  19. static char *saphir_rev = "$Revision: 1.10.2.4 $";
  20. #define byteout(addr, val) outb(val, addr)
  21. #define bytein(addr) inb(addr)
  22. #define ISAC_DATA 0
  23. #define HSCX_DATA 1
  24. #define ADDRESS_REG 2
  25. #define IRQ_REG 3
  26. #define SPARE_REG 4
  27. #define RESET_REG 5
  28. static inline u_char
  29. readreg(unsigned int ale, unsigned int adr, u_char off)
  30. {
  31. register u_char ret;
  32. byteout(ale, off);
  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. byteout(ale, off);
  40. insb(adr, data, size);
  41. }
  42. static inline void
  43. writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
  44. {
  45. byteout(ale, off);
  46. byteout(adr, data);
  47. }
  48. static inline void
  49. writefifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size)
  50. {
  51. byteout(ale, off);
  52. outsb(adr, data, size);
  53. }
  54. /* Interface functions */
  55. static u_char
  56. ReadISAC(struct IsdnCardState *cs, u_char offset)
  57. {
  58. return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset));
  59. }
  60. static void
  61. WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  62. {
  63. writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value);
  64. }
  65. static void
  66. ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
  67. {
  68. readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
  69. }
  70. static void
  71. WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
  72. {
  73. writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
  74. }
  75. static u_char
  76. ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
  77. {
  78. return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
  79. offset + (hscx ? 0x40 : 0)));
  80. }
  81. static void
  82. WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
  83. {
  84. writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
  85. offset + (hscx ? 0x40 : 0), value);
  86. }
  87. #define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale, \
  88. cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0))
  89. #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale, \
  90. cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data)
  91. #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale, \
  92. cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
  93. #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale, \
  94. cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
  95. #include "hscx_irq.c"
  96. static irqreturn_t
  97. saphir_interrupt(int intno, void *dev_id)
  98. {
  99. struct IsdnCardState *cs = dev_id;
  100. u_char val;
  101. u_long flags;
  102. spin_lock_irqsave(&cs->lock, flags);
  103. val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
  104. Start_HSCX:
  105. if (val)
  106. hscx_int_main(cs, val);
  107. val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
  108. Start_ISAC:
  109. if (val)
  110. isac_interrupt(cs, val);
  111. val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
  112. if (val) {
  113. if (cs->debug & L1_DEB_HSCX)
  114. debugl1(cs, "HSCX IntStat after IntRoutine");
  115. goto Start_HSCX;
  116. }
  117. val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
  118. if (val) {
  119. if (cs->debug & L1_DEB_ISAC)
  120. debugl1(cs, "ISAC IntStat after IntRoutine");
  121. goto Start_ISAC;
  122. }
  123. /* Watchdog */
  124. if (cs->hw.saphir.timer.function)
  125. mod_timer(&cs->hw.saphir.timer, jiffies + 1 * HZ);
  126. else
  127. printk(KERN_WARNING "saphir: Spurious timer!\n");
  128. writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF);
  129. writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF);
  130. writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF);
  131. writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0);
  132. writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0);
  133. writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0);
  134. spin_unlock_irqrestore(&cs->lock, flags);
  135. return IRQ_HANDLED;
  136. }
  137. static void
  138. SaphirWatchDog(struct IsdnCardState *cs)
  139. {
  140. u_long flags;
  141. spin_lock_irqsave(&cs->lock, flags);
  142. /* 5 sec WatchDog, so read at least every 4 sec */
  143. cs->readisac(cs, ISAC_RBCH);
  144. spin_unlock_irqrestore(&cs->lock, flags);
  145. mod_timer(&cs->hw.saphir.timer, jiffies + 1 * HZ);
  146. }
  147. static void
  148. release_io_saphir(struct IsdnCardState *cs)
  149. {
  150. byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
  151. del_timer(&cs->hw.saphir.timer);
  152. cs->hw.saphir.timer.function = NULL;
  153. if (cs->hw.saphir.cfg_reg)
  154. release_region(cs->hw.saphir.cfg_reg, 6);
  155. }
  156. static int
  157. saphir_reset(struct IsdnCardState *cs)
  158. {
  159. u_char irq_val;
  160. switch (cs->irq) {
  161. case 5: irq_val = 0;
  162. break;
  163. case 3: irq_val = 1;
  164. break;
  165. case 11:
  166. irq_val = 2;
  167. break;
  168. case 12:
  169. irq_val = 3;
  170. break;
  171. case 15:
  172. irq_val = 4;
  173. break;
  174. default:
  175. printk(KERN_WARNING "HiSax: saphir wrong IRQ %d\n",
  176. cs->irq);
  177. return (1);
  178. }
  179. byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
  180. byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1);
  181. mdelay(10);
  182. byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0);
  183. mdelay(10);
  184. byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
  185. byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02);
  186. return (0);
  187. }
  188. static int
  189. saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  190. {
  191. u_long flags;
  192. switch (mt) {
  193. case CARD_RESET:
  194. spin_lock_irqsave(&cs->lock, flags);
  195. saphir_reset(cs);
  196. spin_unlock_irqrestore(&cs->lock, flags);
  197. return (0);
  198. case CARD_RELEASE:
  199. release_io_saphir(cs);
  200. return (0);
  201. case CARD_INIT:
  202. spin_lock_irqsave(&cs->lock, flags);
  203. inithscxisac(cs, 3);
  204. spin_unlock_irqrestore(&cs->lock, flags);
  205. return (0);
  206. case CARD_TEST:
  207. return (0);
  208. }
  209. return (0);
  210. }
  211. int setup_saphir(struct IsdnCard *card)
  212. {
  213. struct IsdnCardState *cs = card->cs;
  214. char tmp[64];
  215. strcpy(tmp, saphir_rev);
  216. printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
  217. if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
  218. return (0);
  219. /* IO-Ports */
  220. cs->hw.saphir.cfg_reg = card->para[1];
  221. cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
  222. cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
  223. cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
  224. cs->irq = card->para[0];
  225. if (!request_region(cs->hw.saphir.cfg_reg, 6, "saphir")) {
  226. printk(KERN_WARNING
  227. "HiSax: HST Saphir config port %x-%x already in use\n",
  228. cs->hw.saphir.cfg_reg,
  229. cs->hw.saphir.cfg_reg + 5);
  230. return (0);
  231. }
  232. printk(KERN_INFO "HiSax: HST Saphir config irq:%d io:0x%X\n",
  233. cs->irq, cs->hw.saphir.cfg_reg);
  234. setup_isac(cs);
  235. cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
  236. cs->hw.saphir.timer.data = (long) cs;
  237. init_timer(&cs->hw.saphir.timer);
  238. cs->hw.saphir.timer.expires = jiffies + 4 * HZ;
  239. add_timer(&cs->hw.saphir.timer);
  240. if (saphir_reset(cs)) {
  241. release_io_saphir(cs);
  242. return (0);
  243. }
  244. cs->readisac = &ReadISAC;
  245. cs->writeisac = &WriteISAC;
  246. cs->readisacfifo = &ReadISACfifo;
  247. cs->writeisacfifo = &WriteISACfifo;
  248. cs->BC_Read_Reg = &ReadHSCX;
  249. cs->BC_Write_Reg = &WriteHSCX;
  250. cs->BC_Send_Data = &hscx_fill_fifo;
  251. cs->cardmsg = &saphir_card_msg;
  252. cs->irq_func = &saphir_interrupt;
  253. ISACVersion(cs, "saphir:");
  254. if (HscxVersion(cs, "saphir:")) {
  255. printk(KERN_WARNING
  256. "saphir: wrong HSCX versions check IO address\n");
  257. release_io_saphir(cs);
  258. return (0);
  259. }
  260. return (1);
  261. }