avm_a1.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: avm_a1.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  2.  *
  3.  * low level stuff for AVM A1 (Fritz) isdn cards
  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.  */
  12. #define __NO_VERSION__
  13. #include <linux/init.h>
  14. #include "hisax.h"
  15. #include "isac.h"
  16. #include "hscx.h"
  17. #include "isdnl1.h"
  18. extern const char *CardType[];
  19. static const char *avm_revision = "$Revision: 1.1.4.1 $";
  20. #define  AVM_A1_STAT_ISAC 0x01
  21. #define  AVM_A1_STAT_HSCX 0x02
  22. #define  AVM_A1_STAT_TIMER 0x04
  23. #define byteout(addr,val) outb(val,addr)
  24. #define bytein(addr) inb(addr)
  25. static inline u_char
  26. readreg(unsigned int adr, u_char off)
  27. {
  28. return (bytein(adr + off));
  29. }
  30. static inline void
  31. writereg(unsigned int adr, u_char off, u_char data)
  32. {
  33. byteout(adr + off, data);
  34. }
  35. static inline void
  36. read_fifo(unsigned int adr, u_char * data, int size)
  37. {
  38. insb(adr, data, size);
  39. }
  40. static void
  41. write_fifo(unsigned int adr, u_char * data, int size)
  42. {
  43. outsb(adr, data, size);
  44. }
  45. /* Interface functions */
  46. static u_char
  47. ReadISAC(struct IsdnCardState *cs, u_char offset)
  48. {
  49. return (readreg(cs->hw.avm.isac, offset));
  50. }
  51. static void
  52. WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  53. {
  54. writereg(cs->hw.avm.isac, offset, value);
  55. }
  56. static void
  57. ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  58. {
  59. read_fifo(cs->hw.avm.isacfifo, data, size);
  60. }
  61. static void
  62. WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  63. {
  64. write_fifo(cs->hw.avm.isacfifo, data, size);
  65. }
  66. static u_char
  67. ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
  68. {
  69. return (readreg(cs->hw.avm.hscx[hscx], offset));
  70. }
  71. static void
  72. WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
  73. {
  74. writereg(cs->hw.avm.hscx[hscx], offset, value);
  75. }
  76. /*
  77.  * fast interrupt HSCX stuff goes here
  78.  */
  79. #define READHSCX(cs, nr, reg) readreg(cs->hw.avm.hscx[nr], reg)
  80. #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.avm.hscx[nr], reg, data)
  81. #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
  82. #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
  83. #include "hscx_irq.c"
  84. static void
  85. avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs)
  86. {
  87. struct IsdnCardState *cs = dev_id;
  88. u_char val, sval;
  89. if (!cs) {
  90. printk(KERN_WARNING "AVM A1: Spurious interrupt!n");
  91. return;
  92. }
  93. while (((sval = bytein(cs->hw.avm.cfg_reg)) & 0xf) != 0x7) {
  94. if (!(sval & AVM_A1_STAT_TIMER)) {
  95. byteout(cs->hw.avm.cfg_reg, 0x1E);
  96. sval = bytein(cs->hw.avm.cfg_reg);
  97. } else if (cs->debug & L1_DEB_INTSTAT)
  98. debugl1(cs, "avm IntStatus %x", sval);
  99. if (!(sval & AVM_A1_STAT_HSCX)) {
  100. val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA);
  101. if (val)
  102. hscx_int_main(cs, val);
  103. }
  104. if (!(sval & AVM_A1_STAT_ISAC)) {
  105. val = readreg(cs->hw.avm.isac, ISAC_ISTA);
  106. if (val)
  107. isac_interrupt(cs, val);
  108. }
  109. }
  110. writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF);
  111. writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF);
  112. writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF);
  113. writereg(cs->hw.avm.isac, ISAC_MASK, 0x0);
  114. writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0);
  115. writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0);
  116. }
  117. inline static void
  118. release_ioregs(struct IsdnCardState *cs, int mask)
  119. {
  120. release_region(cs->hw.avm.cfg_reg, 8);
  121. if (mask & 1)
  122. release_region(cs->hw.avm.isac + 32, 32);
  123. if (mask & 2)
  124. release_region(cs->hw.avm.isacfifo, 1);
  125. if (mask & 4)
  126. release_region(cs->hw.avm.hscx[0] + 32, 32);
  127. if (mask & 8)
  128. release_region(cs->hw.avm.hscxfifo[0], 1);
  129. if (mask & 0x10)
  130. release_region(cs->hw.avm.hscx[1] + 32, 32);
  131. if (mask & 0x20)
  132. release_region(cs->hw.avm.hscxfifo[1], 1);
  133. }
  134. static int
  135. AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  136. {
  137. switch (mt) {
  138. case CARD_RESET:
  139. return(0);
  140. case CARD_RELEASE:
  141. release_ioregs(cs, 0x3f);
  142. return(0);
  143. case CARD_INIT:
  144. inithscxisac(cs, 1);
  145. byteout(cs->hw.avm.cfg_reg, 0x16);
  146. byteout(cs->hw.avm.cfg_reg, 0x1E);
  147. inithscxisac(cs, 2);
  148. return(0);
  149. case CARD_TEST:
  150. return(0);
  151. }
  152. return(0);
  153. }
  154. int __init
  155. setup_avm_a1(struct IsdnCard *card)
  156. {
  157. u_char val;
  158. struct IsdnCardState *cs = card->cs;
  159. long flags;
  160. char tmp[64];
  161. strcpy(tmp, avm_revision);
  162. printk(KERN_INFO "HiSax: AVM driver Rev. %sn", HiSax_getrev(tmp));
  163. if (cs->typ != ISDN_CTYPE_A1)
  164. return (0);
  165. cs->hw.avm.cfg_reg = card->para[1] + 0x1800;
  166. cs->hw.avm.isac = card->para[1] + 0x1400 - 0x20;
  167. cs->hw.avm.hscx[0] = card->para[1] + 0x400 - 0x20;
  168. cs->hw.avm.hscx[1] = card->para[1] + 0xc00 - 0x20;
  169. cs->hw.avm.isacfifo = card->para[1] + 0x1000;
  170. cs->hw.avm.hscxfifo[0] = card->para[1];
  171. cs->hw.avm.hscxfifo[1] = card->para[1] + 0x800;
  172. cs->irq = card->para[0];
  173. if (check_region((cs->hw.avm.cfg_reg), 8)) {
  174. printk(KERN_WARNING
  175.        "HiSax: %s config port %x-%x already in usen",
  176.        CardType[card->typ],
  177.        cs->hw.avm.cfg_reg,
  178.        cs->hw.avm.cfg_reg + 8);
  179. return (0);
  180. } else {
  181. request_region(cs->hw.avm.cfg_reg, 8, "avm cfg");
  182. }
  183. if (check_region((cs->hw.avm.isac + 32), 32)) {
  184. printk(KERN_WARNING
  185.        "HiSax: %s isac ports %x-%x already in usen",
  186.        CardType[cs->typ],
  187.        cs->hw.avm.isac + 32,
  188.        cs->hw.avm.isac + 64);
  189. release_ioregs(cs, 0);
  190. return (0);
  191. } else {
  192. request_region(cs->hw.avm.isac + 32, 32, "HiSax isac");
  193. }
  194. if (check_region((cs->hw.avm.isacfifo), 1)) {
  195. printk(KERN_WARNING
  196.        "HiSax: %s isac fifo port %x already in usen",
  197.        CardType[cs->typ],
  198.        cs->hw.avm.isacfifo);
  199. release_ioregs(cs, 1);
  200. return (0);
  201. } else {
  202. request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo");
  203. }
  204. if (check_region((cs->hw.avm.hscx[0]) + 32, 32)) {
  205. printk(KERN_WARNING
  206.        "HiSax: %s hscx A ports %x-%x already in usen",
  207.        CardType[cs->typ],
  208.        cs->hw.avm.hscx[0] + 32,
  209.        cs->hw.avm.hscx[0] + 64);
  210. release_ioregs(cs, 3);
  211. return (0);
  212. } else {
  213. request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A");
  214. }
  215. if (check_region(cs->hw.avm.hscxfifo[0], 1)) {
  216. printk(KERN_WARNING
  217.        "HiSax: %s hscx A fifo port %x already in usen",
  218.        CardType[cs->typ],
  219.        cs->hw.avm.hscxfifo[0]);
  220. release_ioregs(cs, 7);
  221. return (0);
  222. } else {
  223. request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo");
  224. }
  225. if (check_region(cs->hw.avm.hscx[1] + 32, 32)) {
  226. printk(KERN_WARNING
  227.        "HiSax: %s hscx B ports %x-%x already in usen",
  228.        CardType[cs->typ],
  229.        cs->hw.avm.hscx[1] + 32,
  230.        cs->hw.avm.hscx[1] + 64);
  231. release_ioregs(cs, 0xf);
  232. return (0);
  233. } else {
  234. request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B");
  235. }
  236. if (check_region(cs->hw.avm.hscxfifo[1], 1)) {
  237. printk(KERN_WARNING
  238.        "HiSax: %s hscx B fifo port %x already in usen",
  239.        CardType[cs->typ],
  240.        cs->hw.avm.hscxfifo[1]);
  241. release_ioregs(cs, 0x1f);
  242. return (0);
  243. } else {
  244. request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo");
  245. }
  246. save_flags(flags);
  247. byteout(cs->hw.avm.cfg_reg, 0x0);
  248. sti();
  249. HZDELAY(HZ / 5 + 1);
  250. byteout(cs->hw.avm.cfg_reg, 0x1);
  251. HZDELAY(HZ / 5 + 1);
  252. byteout(cs->hw.avm.cfg_reg, 0x0);
  253. HZDELAY(HZ / 5 + 1);
  254. val = cs->irq;
  255. if (val == 9)
  256. val = 2;
  257. byteout(cs->hw.avm.cfg_reg + 1, val);
  258. HZDELAY(HZ / 5 + 1);
  259. byteout(cs->hw.avm.cfg_reg, 0x0);
  260. HZDELAY(HZ / 5 + 1);
  261. restore_flags(flags);
  262. val = bytein(cs->hw.avm.cfg_reg);
  263. printk(KERN_INFO "AVM A1: Byte at %x is %xn",
  264.        cs->hw.avm.cfg_reg, val);
  265. val = bytein(cs->hw.avm.cfg_reg + 3);
  266. printk(KERN_INFO "AVM A1: Byte at %x is %xn",
  267.        cs->hw.avm.cfg_reg + 3, val);
  268. val = bytein(cs->hw.avm.cfg_reg + 2);
  269. printk(KERN_INFO "AVM A1: Byte at %x is %xn",
  270.        cs->hw.avm.cfg_reg + 2, val);
  271. val = bytein(cs->hw.avm.cfg_reg);
  272. printk(KERN_INFO "AVM A1: Byte at %x is %xn",
  273.        cs->hw.avm.cfg_reg, val);
  274. printk(KERN_INFO
  275.        "HiSax: %s config irq:%d cfg:0x%Xn",
  276.        CardType[cs->typ], cs->irq,
  277.        cs->hw.avm.cfg_reg);
  278. printk(KERN_INFO
  279.        "HiSax: isac:0x%X/0x%Xn",
  280.        cs->hw.avm.isac + 32, cs->hw.avm.isacfifo);
  281. printk(KERN_INFO
  282.        "HiSax: hscx A:0x%X/0x%X  hscx B:0x%X/0x%Xn",
  283.        cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0],
  284.        cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]);
  285. cs->readisac = &ReadISAC;
  286. cs->writeisac = &WriteISAC;
  287. cs->readisacfifo = &ReadISACfifo;
  288. cs->writeisacfifo = &WriteISACfifo;
  289. cs->BC_Read_Reg = &ReadHSCX;
  290. cs->BC_Write_Reg = &WriteHSCX;
  291. cs->BC_Send_Data = &hscx_fill_fifo;
  292. cs->cardmsg = &AVM_card_msg;
  293. cs->irq_func = &avm_a1_interrupt;
  294. ISACVersion(cs, "AVM A1:");
  295. if (HscxVersion(cs, "AVM A1:")) {
  296. printk(KERN_WARNING
  297.        "AVM A1: wrong HSCX versions check IO addressn");
  298. release_ioregs(cs, 0x3f);
  299. return (0);
  300. }
  301. return (1);
  302. }