mic.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /* $Id: mic.c,v 1.12.2.4 2004/01/13 23:48:39 keil Exp $
  2. *
  3. * low level stuff for mic cards
  4. *
  5. * Author Stephan von Krawczynski
  6. * Copyright by Stephan von Krawczynski <skraw@ithnet.com>
  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 *mic_revision = "$Revision: 1.12.2.4 $";
  19. #define byteout(addr,val) outb(val,addr)
  20. #define bytein(addr) inb(addr)
  21. #define MIC_ISAC 2
  22. #define MIC_HSCX 1
  23. #define MIC_ADR 7
  24. /* CARD_ADR (Write) */
  25. #define MIC_RESET 0x3 /* same as DOS driver */
  26. static inline u_char
  27. readreg(unsigned int ale, unsigned int adr, u_char off)
  28. {
  29. register u_char ret;
  30. byteout(ale, off);
  31. ret = bytein(adr);
  32. return (ret);
  33. }
  34. static inline void
  35. readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
  36. {
  37. byteout(ale, off);
  38. insb(adr, data, size);
  39. }
  40. static inline void
  41. writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
  42. {
  43. byteout(ale, off);
  44. byteout(adr, data);
  45. }
  46. static inline void
  47. writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
  48. {
  49. byteout(ale, off);
  50. outsb(adr, data, size);
  51. }
  52. /* Interface functions */
  53. static u_char
  54. ReadISAC(struct IsdnCardState *cs, u_char offset)
  55. {
  56. return (readreg(cs->hw.mic.adr, cs->hw.mic.isac, offset));
  57. }
  58. static void
  59. WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  60. {
  61. writereg(cs->hw.mic.adr, cs->hw.mic.isac, offset, value);
  62. }
  63. static void
  64. ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  65. {
  66. readfifo(cs->hw.mic.adr, cs->hw.mic.isac, 0, data, size);
  67. }
  68. static void
  69. WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  70. {
  71. writefifo(cs->hw.mic.adr, cs->hw.mic.isac, 0, data, size);
  72. }
  73. static u_char
  74. ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
  75. {
  76. return (readreg(cs->hw.mic.adr,
  77. cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0)));
  78. }
  79. static void
  80. WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
  81. {
  82. writereg(cs->hw.mic.adr,
  83. cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0), value);
  84. }
  85. /*
  86. * fast interrupt HSCX stuff goes here
  87. */
  88. #define READHSCX(cs, nr, reg) readreg(cs->hw.mic.adr, \
  89. cs->hw.mic.hscx, reg + (nr ? 0x40 : 0))
  90. #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.mic.adr, \
  91. cs->hw.mic.hscx, reg + (nr ? 0x40 : 0), data)
  92. #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.mic.adr, \
  93. cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt)
  94. #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.mic.adr, \
  95. cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt)
  96. #include "hscx_irq.c"
  97. static irqreturn_t
  98. mic_interrupt(int intno, void *dev_id)
  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.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40);
  105. Start_HSCX:
  106. if (val)
  107. hscx_int_main(cs, val);
  108. val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA);
  109. Start_ISAC:
  110. if (val)
  111. isac_interrupt(cs, val);
  112. val = readreg(cs->hw.mic.adr, cs->hw.mic.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.mic.adr, cs->hw.mic.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. writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF);
  125. writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF);
  126. writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF);
  127. writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0);
  128. writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0);
  129. writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0);
  130. spin_unlock_irqrestore(&cs->lock, flags);
  131. return IRQ_HANDLED;
  132. }
  133. static void
  134. release_io_mic(struct IsdnCardState *cs)
  135. {
  136. int bytecnt = 8;
  137. if (cs->hw.mic.cfg_reg)
  138. release_region(cs->hw.mic.cfg_reg, bytecnt);
  139. }
  140. static int
  141. mic_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  142. {
  143. u_long flags;
  144. switch (mt) {
  145. case CARD_RESET:
  146. return(0);
  147. case CARD_RELEASE:
  148. release_io_mic(cs);
  149. return(0);
  150. case CARD_INIT:
  151. spin_lock_irqsave(&cs->lock, flags);
  152. inithscx(cs); /* /RTSA := ISAC RST */
  153. inithscxisac(cs, 3);
  154. spin_unlock_irqrestore(&cs->lock, flags);
  155. return(0);
  156. case CARD_TEST:
  157. return(0);
  158. }
  159. return(0);
  160. }
  161. int __devinit
  162. setup_mic(struct IsdnCard *card)
  163. {
  164. int bytecnt;
  165. struct IsdnCardState *cs = card->cs;
  166. char tmp[64];
  167. strcpy(tmp, mic_revision);
  168. printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
  169. if (cs->typ != ISDN_CTYPE_MIC)
  170. return (0);
  171. bytecnt = 8;
  172. cs->hw.mic.cfg_reg = card->para[1];
  173. cs->irq = card->para[0];
  174. cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR;
  175. cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC;
  176. cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX;
  177. if (!request_region(cs->hw.mic.cfg_reg, bytecnt, "mic isdn")) {
  178. printk(KERN_WARNING
  179. "HiSax: %s config port %x-%x already in use\n",
  180. CardType[card->typ],
  181. cs->hw.mic.cfg_reg,
  182. cs->hw.mic.cfg_reg + bytecnt);
  183. return (0);
  184. }
  185. printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n",
  186. cs->hw.mic.cfg_reg, cs->irq);
  187. setup_isac(cs);
  188. cs->readisac = &ReadISAC;
  189. cs->writeisac = &WriteISAC;
  190. cs->readisacfifo = &ReadISACfifo;
  191. cs->writeisacfifo = &WriteISACfifo;
  192. cs->BC_Read_Reg = &ReadHSCX;
  193. cs->BC_Write_Reg = &WriteHSCX;
  194. cs->BC_Send_Data = &hscx_fill_fifo;
  195. cs->cardmsg = &mic_card_msg;
  196. cs->irq_func = &mic_interrupt;
  197. ISACVersion(cs, "mic:");
  198. if (HscxVersion(cs, "mic:")) {
  199. printk(KERN_WARNING
  200. "mic: wrong HSCX versions check IO address\n");
  201. release_io_mic(cs);
  202. return (0);
  203. }
  204. return (1);
  205. }