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

嵌入式Linux

开发平台:

Unix_Linux

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