s0box.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /* $Id: s0box.c,v 2.6.2.4 2004/01/13 23:48:39 keil Exp $
  2. *
  3. * low level stuff for Creatix S0BOX
  4. *
  5. * Author Enrik Berkhan
  6. * Copyright by Enrik Berkhan <enrik@starfleet.inka.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 "hscx.h"
  16. #include "isdnl1.h"
  17. extern const char *CardType[];
  18. static const char *s0box_revision = "$Revision: 2.6.2.4 $";
  19. static inline void
  20. writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
  21. outb_p(0x1c,padr+2);
  22. outb_p(0x14,padr+2);
  23. outb_p((addr+off)&0x7f,padr);
  24. outb_p(0x16,padr+2);
  25. outb_p(val,padr);
  26. outb_p(0x17,padr+2);
  27. outb_p(0x14,padr+2);
  28. outb_p(0x1c,padr+2);
  29. }
  30. static u_char nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf,
  31. 0, 0, 0, 0, 0, 0, 0, 0,
  32. 0, 8, 4, 0xc, 2, 0xa, 6, 0xe } ;
  33. static inline u_char
  34. readreg(unsigned int padr, signed int addr, u_char off) {
  35. register u_char n1, n2;
  36. outb_p(0x1c,padr+2);
  37. outb_p(0x14,padr+2);
  38. outb_p((addr+off)|0x80,padr);
  39. outb_p(0x16,padr+2);
  40. outb_p(0x17,padr+2);
  41. n1 = (inb_p(padr+1) >> 3) & 0x17;
  42. outb_p(0x16,padr+2);
  43. n2 = (inb_p(padr+1) >> 3) & 0x17;
  44. outb_p(0x14,padr+2);
  45. outb_p(0x1c,padr+2);
  46. return nibtab[n1] | (nibtab[n2] << 4);
  47. }
  48. static inline void
  49. read_fifo(unsigned int padr, signed int adr, u_char * data, int size)
  50. {
  51. int i;
  52. register u_char n1, n2;
  53. outb_p(0x1c, padr+2);
  54. outb_p(0x14, padr+2);
  55. outb_p(adr|0x80, padr);
  56. outb_p(0x16, padr+2);
  57. for (i=0; i<size; i++) {
  58. outb_p(0x17, padr+2);
  59. n1 = (inb_p(padr+1) >> 3) & 0x17;
  60. outb_p(0x16,padr+2);
  61. n2 = (inb_p(padr+1) >> 3) & 0x17;
  62. *(data++)=nibtab[n1] | (nibtab[n2] << 4);
  63. }
  64. outb_p(0x14,padr+2);
  65. outb_p(0x1c,padr+2);
  66. return;
  67. }
  68. static inline void
  69. write_fifo(unsigned int padr, signed int adr, u_char * data, int size)
  70. {
  71. int i;
  72. outb_p(0x1c, padr+2);
  73. outb_p(0x14, padr+2);
  74. outb_p(adr&0x7f, padr);
  75. for (i=0; i<size; i++) {
  76. outb_p(0x16, padr+2);
  77. outb_p(*(data++), padr);
  78. outb_p(0x17, padr+2);
  79. }
  80. outb_p(0x14,padr+2);
  81. outb_p(0x1c,padr+2);
  82. return;
  83. }
  84. /* Interface functions */
  85. static u_char
  86. ReadISAC(struct IsdnCardState *cs, u_char offset)
  87. {
  88. return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset));
  89. }
  90. static void
  91. WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  92. {
  93. writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset, value);
  94. }
  95. static void
  96. ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  97. {
  98. read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
  99. }
  100. static void
  101. WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  102. {
  103. write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
  104. }
  105. static u_char
  106. ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
  107. {
  108. return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset));
  109. }
  110. static void
  111. WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
  112. {
  113. writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset, value);
  114. }
  115. /*
  116. * fast interrupt HSCX stuff goes here
  117. */
  118. #define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg)
  119. #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg, data)
  120. #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
  121. #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
  122. #include "hscx_irq.c"
  123. static irqreturn_t
  124. s0box_interrupt(int intno, void *dev_id)
  125. {
  126. #define MAXCOUNT 5
  127. struct IsdnCardState *cs = dev_id;
  128. u_char val;
  129. u_long flags;
  130. int count = 0;
  131. spin_lock_irqsave(&cs->lock, flags);
  132. val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
  133. Start_HSCX:
  134. if (val)
  135. hscx_int_main(cs, val);
  136. val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
  137. Start_ISAC:
  138. if (val)
  139. isac_interrupt(cs, val);
  140. count++;
  141. val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
  142. if (val && count < MAXCOUNT) {
  143. if (cs->debug & L1_DEB_HSCX)
  144. debugl1(cs, "HSCX IntStat after IntRoutine");
  145. goto Start_HSCX;
  146. }
  147. val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
  148. if (val && count < MAXCOUNT) {
  149. if (cs->debug & L1_DEB_ISAC)
  150. debugl1(cs, "ISAC IntStat after IntRoutine");
  151. goto Start_ISAC;
  152. }
  153. if (count >= MAXCOUNT)
  154. printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count);
  155. writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
  156. writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
  157. writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF);
  158. writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0);
  159. writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
  160. writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
  161. spin_unlock_irqrestore(&cs->lock, flags);
  162. return IRQ_HANDLED;
  163. }
  164. static void
  165. release_io_s0box(struct IsdnCardState *cs)
  166. {
  167. release_region(cs->hw.teles3.cfg_reg, 8);
  168. }
  169. static int
  170. S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  171. {
  172. u_long flags;
  173. switch (mt) {
  174. case CARD_RESET:
  175. break;
  176. case CARD_RELEASE:
  177. release_io_s0box(cs);
  178. break;
  179. case CARD_INIT:
  180. spin_lock_irqsave(&cs->lock, flags);
  181. inithscxisac(cs, 3);
  182. spin_unlock_irqrestore(&cs->lock, flags);
  183. break;
  184. case CARD_TEST:
  185. break;
  186. }
  187. return(0);
  188. }
  189. int __devinit
  190. setup_s0box(struct IsdnCard *card)
  191. {
  192. struct IsdnCardState *cs = card->cs;
  193. char tmp[64];
  194. strcpy(tmp, s0box_revision);
  195. printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
  196. if (cs->typ != ISDN_CTYPE_S0BOX)
  197. return (0);
  198. cs->hw.teles3.cfg_reg = card->para[1];
  199. cs->hw.teles3.hscx[0] = -0x20;
  200. cs->hw.teles3.hscx[1] = 0x0;
  201. cs->hw.teles3.isac = 0x20;
  202. cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
  203. cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
  204. cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
  205. cs->irq = card->para[0];
  206. if (!request_region(cs->hw.teles3.cfg_reg,8, "S0Box parallel I/O")) {
  207. printk(KERN_WARNING
  208. "HiSax: %s ports %x-%x already in use\n",
  209. CardType[cs->typ],
  210. cs->hw.teles3.cfg_reg,
  211. cs->hw.teles3.cfg_reg + 7);
  212. return 0;
  213. }
  214. printk(KERN_INFO
  215. "HiSax: %s config irq:%d isac:0x%x cfg:0x%x\n",
  216. CardType[cs->typ], cs->irq,
  217. cs->hw.teles3.isac, cs->hw.teles3.cfg_reg);
  218. printk(KERN_INFO
  219. "HiSax: hscx A:0x%x hscx B:0x%x\n",
  220. cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]);
  221. setup_isac(cs);
  222. cs->readisac = &ReadISAC;
  223. cs->writeisac = &WriteISAC;
  224. cs->readisacfifo = &ReadISACfifo;
  225. cs->writeisacfifo = &WriteISACfifo;
  226. cs->BC_Read_Reg = &ReadHSCX;
  227. cs->BC_Write_Reg = &WriteHSCX;
  228. cs->BC_Send_Data = &hscx_fill_fifo;
  229. cs->cardmsg = &S0Box_card_msg;
  230. cs->irq_func = &s0box_interrupt;
  231. ISACVersion(cs, "S0Box:");
  232. if (HscxVersion(cs, "S0Box:")) {
  233. printk(KERN_WARNING
  234. "S0Box: wrong HSCX versions check IO address\n");
  235. release_io_s0box(cs);
  236. return (0);
  237. }
  238. return (1);
  239. }