saphir.c 7.4 KB

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