avm_a1.c 8.3 KB

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