teles0.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /* $Id: teles0.c,v 2.15.2.4 2004/01/13 23:48:39 keil Exp $
  2. *
  3. * low level stuff for Teles Memory IO isdn cards
  4. *
  5. * Author Karsten Keil
  6. * based on the teles driver from Jan den Ouden
  7. * Copyright by Karsten Keil <keil@isdn4linux.de>
  8. *
  9. * This software may be used and distributed according to the terms
  10. * of the GNU General Public License, incorporated herein by reference.
  11. *
  12. * Thanks to Jan den Ouden
  13. * Fritz Elfert
  14. * Beat Doebeli
  15. *
  16. */
  17. #include <linux/init.h>
  18. #include "hisax.h"
  19. #include "isdnl1.h"
  20. #include "isac.h"
  21. #include "hscx.h"
  22. static const char *teles0_revision = "$Revision: 2.15.2.4 $";
  23. #define TELES_IOMEM_SIZE 0x400
  24. #define byteout(addr, val) outb(val, addr)
  25. #define bytein(addr) inb(addr)
  26. static inline u_char
  27. readisac(void __iomem *adr, u_char off)
  28. {
  29. return readb(adr + ((off & 1) ? 0x2ff : 0x100) + off);
  30. }
  31. static inline void
  32. writeisac(void __iomem *adr, u_char off, u_char data)
  33. {
  34. writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb();
  35. }
  36. static inline u_char
  37. readhscx(void __iomem *adr, int hscx, u_char off)
  38. {
  39. return readb(adr + (hscx ? 0x1c0 : 0x180) +
  40. ((off & 1) ? 0x1ff : 0) + off);
  41. }
  42. static inline void
  43. writehscx(void __iomem *adr, int hscx, u_char off, u_char data)
  44. {
  45. writeb(data, adr + (hscx ? 0x1c0 : 0x180) +
  46. ((off & 1) ? 0x1ff : 0) + off); mb();
  47. }
  48. static inline void
  49. read_fifo_isac(void __iomem *adr, u_char *data, int size)
  50. {
  51. register int i;
  52. register u_char __iomem *ad = adr + 0x100;
  53. for (i = 0; i < size; i++)
  54. data[i] = readb(ad);
  55. }
  56. static inline void
  57. write_fifo_isac(void __iomem *adr, u_char *data, int size)
  58. {
  59. register int i;
  60. register u_char __iomem *ad = adr + 0x100;
  61. for (i = 0; i < size; i++) {
  62. writeb(data[i], ad); mb();
  63. }
  64. }
  65. static inline void
  66. read_fifo_hscx(void __iomem *adr, int hscx, u_char *data, int size)
  67. {
  68. register int i;
  69. register u_char __iomem *ad = adr + (hscx ? 0x1c0 : 0x180);
  70. for (i = 0; i < size; i++)
  71. data[i] = readb(ad);
  72. }
  73. static inline void
  74. write_fifo_hscx(void __iomem *adr, int hscx, u_char *data, int size)
  75. {
  76. int i;
  77. register u_char __iomem *ad = adr + (hscx ? 0x1c0 : 0x180);
  78. for (i = 0; i < size; i++) {
  79. writeb(data[i], ad); mb();
  80. }
  81. }
  82. /* Interface functions */
  83. static u_char
  84. ReadISAC(struct IsdnCardState *cs, u_char offset)
  85. {
  86. return (readisac(cs->hw.teles0.membase, offset));
  87. }
  88. static void
  89. WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  90. {
  91. writeisac(cs->hw.teles0.membase, offset, value);
  92. }
  93. static void
  94. ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
  95. {
  96. read_fifo_isac(cs->hw.teles0.membase, data, size);
  97. }
  98. static void
  99. WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
  100. {
  101. write_fifo_isac(cs->hw.teles0.membase, data, size);
  102. }
  103. static u_char
  104. ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
  105. {
  106. return (readhscx(cs->hw.teles0.membase, hscx, offset));
  107. }
  108. static void
  109. WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
  110. {
  111. writehscx(cs->hw.teles0.membase, hscx, offset, value);
  112. }
  113. /*
  114. * fast interrupt HSCX stuff goes here
  115. */
  116. #define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
  117. #define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
  118. #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
  119. #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
  120. #include "hscx_irq.c"
  121. static irqreturn_t
  122. teles0_interrupt(int intno, void *dev_id)
  123. {
  124. struct IsdnCardState *cs = dev_id;
  125. u_char val;
  126. u_long flags;
  127. int count = 0;
  128. spin_lock_irqsave(&cs->lock, flags);
  129. val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
  130. Start_HSCX:
  131. if (val)
  132. hscx_int_main(cs, val);
  133. val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
  134. Start_ISAC:
  135. if (val)
  136. isac_interrupt(cs, val);
  137. count++;
  138. val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
  139. if (val && count < 5) {
  140. if (cs->debug & L1_DEB_HSCX)
  141. debugl1(cs, "HSCX IntStat after IntRoutine");
  142. goto Start_HSCX;
  143. }
  144. val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
  145. if (val && count < 5) {
  146. if (cs->debug & L1_DEB_ISAC)
  147. debugl1(cs, "ISAC IntStat after IntRoutine");
  148. goto Start_ISAC;
  149. }
  150. writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
  151. writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
  152. writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
  153. writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
  154. writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
  155. writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
  156. spin_unlock_irqrestore(&cs->lock, flags);
  157. return IRQ_HANDLED;
  158. }
  159. static void
  160. release_io_teles0(struct IsdnCardState *cs)
  161. {
  162. if (cs->hw.teles0.cfg_reg)
  163. release_region(cs->hw.teles0.cfg_reg, 8);
  164. iounmap(cs->hw.teles0.membase);
  165. release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
  166. }
  167. static int
  168. reset_teles0(struct IsdnCardState *cs)
  169. {
  170. u_char cfval;
  171. if (cs->hw.teles0.cfg_reg) {
  172. switch (cs->irq) {
  173. case 2:
  174. case 9:
  175. cfval = 0x00;
  176. break;
  177. case 3:
  178. cfval = 0x02;
  179. break;
  180. case 4:
  181. cfval = 0x04;
  182. break;
  183. case 5:
  184. cfval = 0x06;
  185. break;
  186. case 10:
  187. cfval = 0x08;
  188. break;
  189. case 11:
  190. cfval = 0x0A;
  191. break;
  192. case 12:
  193. cfval = 0x0C;
  194. break;
  195. case 15:
  196. cfval = 0x0E;
  197. break;
  198. default:
  199. return (1);
  200. }
  201. cfval |= ((cs->hw.teles0.phymem >> 9) & 0xF0);
  202. byteout(cs->hw.teles0.cfg_reg + 4, cfval);
  203. HZDELAY(HZ / 10 + 1);
  204. byteout(cs->hw.teles0.cfg_reg + 4, cfval | 1);
  205. HZDELAY(HZ / 10 + 1);
  206. }
  207. writeb(0, cs->hw.teles0.membase + 0x80); mb();
  208. HZDELAY(HZ / 5 + 1);
  209. writeb(1, cs->hw.teles0.membase + 0x80); mb();
  210. HZDELAY(HZ / 5 + 1);
  211. return (0);
  212. }
  213. static int
  214. Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  215. {
  216. u_long flags;
  217. switch (mt) {
  218. case CARD_RESET:
  219. spin_lock_irqsave(&cs->lock, flags);
  220. reset_teles0(cs);
  221. spin_unlock_irqrestore(&cs->lock, flags);
  222. return (0);
  223. case CARD_RELEASE:
  224. release_io_teles0(cs);
  225. return (0);
  226. case CARD_INIT:
  227. spin_lock_irqsave(&cs->lock, flags);
  228. inithscxisac(cs, 3);
  229. spin_unlock_irqrestore(&cs->lock, flags);
  230. return (0);
  231. case CARD_TEST:
  232. return (0);
  233. }
  234. return (0);
  235. }
  236. int setup_teles0(struct IsdnCard *card)
  237. {
  238. u_char val;
  239. struct IsdnCardState *cs = card->cs;
  240. char tmp[64];
  241. strcpy(tmp, teles0_revision);
  242. printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp));
  243. if ((cs->typ != ISDN_CTYPE_16_0) && (cs->typ != ISDN_CTYPE_8_0))
  244. return (0);
  245. if (cs->typ == ISDN_CTYPE_16_0)
  246. cs->hw.teles0.cfg_reg = card->para[2];
  247. else /* 8.0 */
  248. cs->hw.teles0.cfg_reg = 0;
  249. if (card->para[1] < 0x10000) {
  250. card->para[1] <<= 4;
  251. printk(KERN_INFO
  252. "Teles0: membase configured DOSish, assuming 0x%lx\n",
  253. (unsigned long) card->para[1]);
  254. }
  255. cs->irq = card->para[0];
  256. if (cs->hw.teles0.cfg_reg) {
  257. if (!request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg")) {
  258. printk(KERN_WARNING
  259. "HiSax: %s config port %x-%x already in use\n",
  260. CardType[card->typ],
  261. cs->hw.teles0.cfg_reg,
  262. cs->hw.teles0.cfg_reg + 8);
  263. return (0);
  264. }
  265. }
  266. if (cs->hw.teles0.cfg_reg) {
  267. if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
  268. printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
  269. cs->hw.teles0.cfg_reg + 0, val);
  270. release_region(cs->hw.teles0.cfg_reg, 8);
  271. return (0);
  272. }
  273. if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
  274. printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
  275. cs->hw.teles0.cfg_reg + 1, val);
  276. release_region(cs->hw.teles0.cfg_reg, 8);
  277. return (0);
  278. }
  279. val = bytein(cs->hw.teles0.cfg_reg + 2); /* 0x1e=without AB
  280. * 0x1f=with AB
  281. * 0x1c 16.3 ???
  282. */
  283. if (val != 0x1e && val != 0x1f) {
  284. printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
  285. cs->hw.teles0.cfg_reg + 2, val);
  286. release_region(cs->hw.teles0.cfg_reg, 8);
  287. return (0);
  288. }
  289. }
  290. /* 16.0 and 8.0 designed for IOM1 */
  291. test_and_set_bit(HW_IOM1, &cs->HW_Flags);
  292. cs->hw.teles0.phymem = card->para[1];
  293. if (!request_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem")) {
  294. printk(KERN_WARNING
  295. "HiSax: %s memory region %lx-%lx already in use\n",
  296. CardType[card->typ],
  297. cs->hw.teles0.phymem,
  298. cs->hw.teles0.phymem + TELES_IOMEM_SIZE);
  299. if (cs->hw.teles0.cfg_reg)
  300. release_region(cs->hw.teles0.cfg_reg, 8);
  301. return (0);
  302. }
  303. cs->hw.teles0.membase = ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
  304. printk(KERN_INFO
  305. "HiSax: %s config irq:%d mem:%p cfg:0x%X\n",
  306. CardType[cs->typ], cs->irq,
  307. cs->hw.teles0.membase, cs->hw.teles0.cfg_reg);
  308. if (reset_teles0(cs)) {
  309. printk(KERN_WARNING "Teles0: wrong IRQ\n");
  310. release_io_teles0(cs);
  311. return (0);
  312. }
  313. setup_isac(cs);
  314. cs->readisac = &ReadISAC;
  315. cs->writeisac = &WriteISAC;
  316. cs->readisacfifo = &ReadISACfifo;
  317. cs->writeisacfifo = &WriteISACfifo;
  318. cs->BC_Read_Reg = &ReadHSCX;
  319. cs->BC_Write_Reg = &WriteHSCX;
  320. cs->BC_Send_Data = &hscx_fill_fifo;
  321. cs->cardmsg = &Teles_card_msg;
  322. cs->irq_func = &teles0_interrupt;
  323. ISACVersion(cs, "Teles0:");
  324. if (HscxVersion(cs, "Teles0:")) {
  325. printk(KERN_WARNING
  326. "Teles0: wrong HSCX versions check IO/MEM addresses\n");
  327. release_io_teles0(cs);
  328. return (0);
  329. }
  330. return (1);
  331. }