avm_a1p.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: avm_a1p.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  2.  *
  3.  * low level stuff for the following AVM cards:
  4.  * A1 PCMCIA
  5.  * FRITZ!Card PCMCIA
  6.  * FRITZ!Card PCMCIA 2.0
  7.  *
  8.  * Author       Carsten Paeth
  9.  * Copyright    by Carsten Paeth     <calle@calle.de>
  10.  *
  11.  * This software may be used and distributed according to the terms
  12.  * of the GNU General Public License, incorporated herein by reference.
  13.  *
  14.  */
  15. #define __NO_VERSION__
  16. #include <linux/init.h>
  17. #include "hisax.h"
  18. #include "isac.h"
  19. #include "hscx.h"
  20. #include "isdnl1.h"
  21. /* register offsets */
  22. #define ADDRREG_OFFSET 0x02
  23. #define DATAREG_OFFSET 0x03
  24. #define ASL0_OFFSET 0x04
  25. #define ASL1_OFFSET 0x05
  26. #define MODREG_OFFSET 0x06
  27. #define VERREG_OFFSET 0x07
  28. /* address offsets */
  29. #define ISAC_FIFO_OFFSET 0x00
  30. #define ISAC_REG_OFFSET 0x20
  31. #define HSCX_CH_DIFF 0x40
  32. #define HSCX_FIFO_OFFSET 0x80
  33. #define HSCX_REG_OFFSET 0xa0
  34. /* read bits ASL0 */
  35. #define  ASL0_R_TIMER 0x10 /* active low */
  36. #define  ASL0_R_ISAC 0x20 /* active low */
  37. #define  ASL0_R_HSCX 0x40 /* active low */
  38. #define  ASL0_R_TESTBIT 0x80
  39. #define  ASL0_R_IRQPENDING (ASL0_R_ISAC|ASL0_R_HSCX|ASL0_R_TIMER)
  40. /* write bits ASL0 */
  41. #define  ASL0_W_RESET 0x01
  42. #define  ASL0_W_TDISABLE 0x02
  43. #define  ASL0_W_TRESET 0x04
  44. #define  ASL0_W_IRQENABLE 0x08
  45. #define  ASL0_W_TESTBIT 0x80
  46. /* write bits ASL1 */
  47. #define  ASL1_W_LED0 0x10
  48. #define  ASL1_W_LED1 0x20
  49. #define  ASL1_W_ENABLE_S0 0xC0
  50.  
  51. #define byteout(addr,val) outb(val,addr)
  52. #define bytein(addr) inb(addr)
  53. static const char *avm_revision = "$Revision: 1.1.4.1 $";
  54. static inline u_char
  55. ReadISAC(struct IsdnCardState *cs, u_char offset)
  56. {
  57. long flags;
  58.         u_char ret;
  59.         offset -= 0x20;
  60. save_flags(flags);
  61. cli();
  62.         byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
  63. ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
  64. restore_flags(flags);
  65. return ret;
  66. }
  67. static inline void
  68. WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  69. {
  70. long flags;
  71.         offset -= 0x20;
  72. save_flags(flags);
  73. cli();
  74.         byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
  75. byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
  76. restore_flags(flags);
  77. }
  78. static inline void
  79. ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  80. {
  81. long flags;
  82. save_flags(flags);
  83. cli();
  84. byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
  85. insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
  86. restore_flags(flags);
  87. }
  88. static inline void
  89. WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  90. {
  91. long flags;
  92. save_flags(flags);
  93. cli();
  94. byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
  95. outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
  96. restore_flags(flags);
  97. }
  98. static inline u_char
  99. ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
  100. {
  101. u_char ret;
  102. long flags;
  103.         offset -= 0x20;
  104. save_flags(flags);
  105. cli();
  106. byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
  107. HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
  108. ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
  109. restore_flags(flags);
  110. return ret;
  111. }
  112. static inline void
  113. WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
  114. {
  115. long flags;
  116.         offset -= 0x20;
  117. save_flags(flags);
  118. cli();
  119. byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
  120. HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
  121. byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
  122. restore_flags(flags);
  123. }
  124. static inline void
  125. ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
  126. {
  127. long flags;
  128. save_flags(flags);
  129. cli();
  130. byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
  131. HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
  132. insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
  133. restore_flags(flags);
  134. }
  135. static inline void
  136. WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
  137. {
  138. long flags;
  139. save_flags(flags);
  140. cli();
  141. byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
  142. HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
  143. outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
  144. restore_flags(flags);
  145. }
  146. /*
  147.  * fast interrupt HSCX stuff goes here
  148.  */
  149. #define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
  150. #define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
  151. #define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) 
  152. #define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
  153. #include "hscx_irq.c"
  154. static void
  155. avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs)
  156. {
  157. struct IsdnCardState *cs = dev_id;
  158. u_char val, sval;
  159. if (!cs) {
  160. printk(KERN_WARNING "AVM A1 PCMCIA: Spurious interrupt!n");
  161. return;
  162. }
  163. while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) {
  164. if (cs->debug & L1_DEB_INTSTAT)
  165. debugl1(cs, "avm IntStatus %x", sval);
  166. if (sval & ASL0_R_HSCX) {
  167.                         val = ReadHSCX(cs, 1, HSCX_ISTA);
  168. if (val)
  169. hscx_int_main(cs, val);
  170. }
  171. if (sval & ASL0_R_ISAC) {
  172. val = ReadISAC(cs, ISAC_ISTA);
  173. if (val)
  174. isac_interrupt(cs, val);
  175. }
  176. }
  177. WriteHSCX(cs, 0, HSCX_MASK, 0xff);
  178. WriteHSCX(cs, 1, HSCX_MASK, 0xff);
  179. WriteISAC(cs, ISAC_MASK, 0xff);
  180. WriteISAC(cs, ISAC_MASK, 0x00);
  181. WriteHSCX(cs, 0, HSCX_MASK, 0x00);
  182. WriteHSCX(cs, 1, HSCX_MASK, 0x00);
  183. }
  184. static int
  185. AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  186. {
  187. switch (mt) {
  188. case CARD_RESET:
  189. byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
  190. HZDELAY(HZ / 5 + 1);
  191. byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
  192. HZDELAY(HZ / 5 + 1);
  193. byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
  194. return 0;
  195. case CARD_RELEASE:
  196. /* free_irq is done in HiSax_closecard(). */
  197.         /* free_irq(cs->irq, cs); */
  198. return 0;
  199. case CARD_INIT:
  200. byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
  201. clear_pending_isac_ints(cs);
  202. clear_pending_hscx_ints(cs);
  203. inithscxisac(cs, 1);
  204. inithscxisac(cs, 2);
  205. return 0;
  206. case CARD_TEST:
  207. /* we really don't need it for the PCMCIA Version */
  208. return 0;
  209. default:
  210. /* all card drivers ignore others, so we do the same */
  211. return 0;
  212. }
  213. return 0;
  214. }
  215. int __devinit
  216. setup_avm_a1_pcmcia(struct IsdnCard *card)
  217. {
  218. u_char model, vers;
  219. struct IsdnCardState *cs = card->cs;
  220. long flags;
  221. char tmp[64];
  222. strcpy(tmp, avm_revision);
  223. printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %sn",
  224.  HiSax_getrev(tmp));
  225. if (cs->typ != ISDN_CTYPE_A1_PCMCIA)
  226. return (0);
  227. cs->hw.avm.cfg_reg = card->para[1];
  228. cs->irq = card->para[0];
  229. save_flags(flags);
  230. outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
  231.         sti();
  232. byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
  233. HZDELAY(HZ / 5 + 1);
  234. byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
  235. HZDELAY(HZ / 5 + 1);
  236. byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
  237. byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET, ASL0_W_TDISABLE|ASL0_W_TRESET);
  238. restore_flags(flags);
  239. model = bytein(cs->hw.avm.cfg_reg+MODREG_OFFSET);
  240. vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
  241. printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %dn",
  242. cs->hw.avm.cfg_reg, cs->irq, model, vers);
  243. cs->readisac = &ReadISAC;
  244. cs->writeisac = &WriteISAC;
  245. cs->readisacfifo = &ReadISACfifo;
  246. cs->writeisacfifo = &WriteISACfifo;
  247. cs->BC_Read_Reg = &ReadHSCX;
  248. cs->BC_Write_Reg = &WriteHSCX;
  249. cs->BC_Send_Data = &hscx_fill_fifo;
  250. cs->cardmsg = &AVM_card_msg;
  251. cs->irq_func = &avm_a1p_interrupt;
  252. ISACVersion(cs, "AVM A1 PCMCIA:");
  253. if (HscxVersion(cs, "AVM A1 PCMCIA:")) {
  254. printk(KERN_WARNING
  255.        "AVM A1 PCMCIA: wrong HSCX versions check IO addressn");
  256. return (0);
  257. }
  258. return (1);
  259. }