teles0.c 9.1 KB

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