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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: bkm_a4t.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  2.  *
  3.  * low level stuff for T-Berkom A4T
  4.  *
  5.  * Author       Roland Klabunde
  6.  * Copyright    by Roland Klabunde   <R.Klabunde@Berkom.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/config.h>
  14. #include <linux/init.h>
  15. #include "hisax.h"
  16. #include "isac.h"
  17. #include "hscx.h"
  18. #include "jade.h"
  19. #include "isdnl1.h"
  20. #include <linux/pci.h>
  21. #include "bkm_ax.h"
  22. extern const char *CardType[];
  23. const char *bkm_a4t_revision = "$Revision: 1.1.4.1 $";
  24. static inline u_char
  25. readreg(unsigned int ale, unsigned long adr, u_char off)
  26. {
  27. register u_int ret;
  28. long flags;
  29. unsigned int *po = (unsigned int *) adr; /* Postoffice */
  30. save_flags(flags);
  31. cli();
  32. *po = (GCS_2 | PO_WRITE | off);
  33. __WAITI20__(po);
  34. *po = (ale | PO_READ);
  35. __WAITI20__(po);
  36. ret = *po;
  37. restore_flags(flags);
  38. return ((unsigned char) ret);
  39. }
  40. static inline void
  41. readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
  42. {
  43. /* fifo read without cli because it's allready done  */
  44. int i;
  45. for (i = 0; i < size; i++)
  46. *data++ = readreg(ale, adr, off);
  47. }
  48. static inline void
  49. writereg(unsigned int ale, unsigned long adr, u_char off, u_char data)
  50. {
  51. long flags;
  52. unsigned int *po = (unsigned int *) adr; /* Postoffice */
  53. save_flags(flags);
  54. cli();
  55. *po = (GCS_2 | PO_WRITE | off);
  56. __WAITI20__(po);
  57. *po = (ale | PO_WRITE | data);
  58. __WAITI20__(po);
  59. restore_flags(flags);
  60. }
  61. static inline void
  62. writefifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
  63. {
  64. /* fifo write without cli because it's allready done  */
  65. int i;
  66. for (i = 0; i < size; i++)
  67. writereg(ale, adr, off, *data++);
  68. }
  69. /* Interface functions */
  70. static u_char
  71. ReadISAC(struct IsdnCardState *cs, u_char offset)
  72. {
  73. return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset));
  74. }
  75. static void
  76. WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  77. {
  78. writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value);
  79. }
  80. static void
  81. ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  82. {
  83. readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
  84. }
  85. static void
  86. WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  87. {
  88. writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
  89. }
  90. static u_char
  91. ReadJADE(struct IsdnCardState *cs, int jade, u_char offset)
  92. {
  93. return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80))));
  94. }
  95. static void
  96. WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value)
  97. {
  98. writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value);
  99. }
  100. /*
  101.  * fast interrupt JADE stuff goes here
  102.  */
  103. #define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,
  104.   cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)))
  105. #define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,
  106.   cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data)
  107. #define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,
  108. cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
  109. #define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,
  110. cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
  111. #include "jade_irq.c"
  112. static void
  113. bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
  114. {
  115. struct IsdnCardState *cs = dev_id;
  116. u_char val = 0;
  117. I20_REGISTER_FILE *pI20_Regs;
  118. if (!cs) {
  119. printk(KERN_WARNING "HiSax: Telekom A4T: Spurious interrupt!n");
  120. return;
  121. }
  122. pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
  123. /* ISDN interrupt pending? */
  124. if (pI20_Regs->i20IntStatus & intISDN) {
  125. /* Reset the ISDN interrupt     */
  126. pI20_Regs->i20IntStatus = intISDN;
  127. /* Disable ISDN interrupt */
  128. pI20_Regs->i20IntCtrl &= ~intISDN;
  129. /* Channel A first */
  130. val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0x80);
  131. if (val) {
  132. jade_int_main(cs, val, 0);
  133. }
  134. /* Channel B  */
  135. val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0xC0);
  136. if (val) {
  137. jade_int_main(cs, val, 1);
  138. }
  139. /* D-Channel */
  140. val = readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, ISAC_ISTA);
  141. if (val) {
  142. isac_interrupt(cs, val);
  143. }
  144. /* Reenable ISDN interrupt */
  145. pI20_Regs->i20IntCtrl |= intISDN;
  146. }
  147. }
  148. void
  149. release_io_bkm(struct IsdnCardState *cs)
  150. {
  151. if (cs->hw.ax.base) {
  152. iounmap((void *) cs->hw.ax.base);
  153. cs->hw.ax.base = 0;
  154. }
  155. }
  156. static void
  157. enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
  158. {
  159. if (cs->typ == ISDN_CTYPE_BKM_A4T) {
  160. I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
  161. if (bEnable)
  162. pI20_Regs->i20IntCtrl |= (intISDN | intPCI);
  163. else
  164. /* CAUTION: This disables the video capture driver too */
  165. pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI);
  166. }
  167. }
  168. static void
  169. reset_bkm(struct IsdnCardState *cs)
  170. {
  171. long flags;
  172. if (cs->typ == ISDN_CTYPE_BKM_A4T) {
  173. I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
  174. save_flags(flags);
  175. sti();
  176. /* Issue the I20 soft reset     */
  177. pI20_Regs->i20SysControl = 0xFF; /* all in */
  178. set_current_state(TASK_UNINTERRUPTIBLE);
  179. schedule_timeout((10 * HZ) / 1000);
  180. /* Remove the soft reset */
  181. pI20_Regs->i20SysControl = sysRESET | 0xFF;
  182. set_current_state(TASK_UNINTERRUPTIBLE);
  183. schedule_timeout((10 * HZ) / 1000);
  184. /* Set our configuration */
  185. pI20_Regs->i20SysControl = sysRESET | sysCFG;
  186. /* Issue ISDN reset     */
  187. pI20_Regs->i20GuestControl = guestWAIT_CFG |
  188.     g_A4T_JADE_RES |
  189.     g_A4T_ISAR_RES |
  190.     g_A4T_ISAC_RES |
  191.     g_A4T_JADE_BOOTR |
  192.     g_A4T_ISAR_BOOTR;
  193. set_current_state(TASK_UNINTERRUPTIBLE);
  194. schedule_timeout((10 * HZ) / 1000);
  195. /* Remove RESET state from ISDN */
  196. pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES |
  197. g_A4T_JADE_RES |
  198. g_A4T_ISAR_RES);
  199. set_current_state(TASK_UNINTERRUPTIBLE);
  200. schedule_timeout((10 * HZ) / 1000);
  201. restore_flags(flags);
  202. }
  203. }
  204. static int
  205. BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  206. {
  207. switch (mt) {
  208. case CARD_RESET:
  209. /* Disable ints */
  210. enable_bkm_int(cs, 0);
  211. reset_bkm(cs);
  212. return (0);
  213. case CARD_RELEASE:
  214. /* Sanity */
  215. enable_bkm_int(cs, 0);
  216. reset_bkm(cs);
  217. release_io_bkm(cs);
  218. return (0);
  219. case CARD_INIT:
  220. clear_pending_isac_ints(cs);
  221. clear_pending_jade_ints(cs);
  222. initisac(cs);
  223. initjade(cs);
  224. /* Enable ints */
  225. enable_bkm_int(cs, 1);
  226. return (0);
  227. case CARD_TEST:
  228. return (0);
  229. }
  230. return (0);
  231. }
  232. static struct pci_dev *dev_a4t __initdata = NULL;
  233. int __init
  234. setup_bkm_a4t(struct IsdnCard *card)
  235. {
  236. struct IsdnCardState *cs = card->cs;
  237. char tmp[64];
  238. u_int pci_memaddr = 0, found = 0;
  239. I20_REGISTER_FILE *pI20_Regs;
  240. #if CONFIG_PCI
  241. #endif
  242. strcpy(tmp, bkm_a4t_revision);
  243. printk(KERN_INFO "HiSax: T-Berkom driver Rev. %sn", HiSax_getrev(tmp));
  244. if (cs->typ == ISDN_CTYPE_BKM_A4T) {
  245. cs->subtyp = BKM_A4T;
  246. } else
  247. return (0);
  248. #if CONFIG_PCI
  249. if (!pci_present()) {
  250. printk(KERN_ERR "bkm_a4t: no PCI bus presentn");
  251. return (0);
  252. }
  253. while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
  254. PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
  255. u16 sub_sys;
  256. u16 sub_vendor;
  257. sub_vendor = dev_a4t->subsystem_vendor;
  258. sub_sys = dev_a4t->subsystem_device;
  259. if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
  260. if (pci_enable_device(dev_a4t))
  261. return(0);
  262. found = 1;
  263. pci_memaddr = pci_resource_start(dev_a4t, 0);
  264. cs->irq = dev_a4t->irq;
  265. break;
  266. }
  267. }
  268. if (!found) {
  269. printk(KERN_WARNING "HiSax: %s: Card not foundn", CardType[card->typ]);
  270. return (0);
  271. }
  272. if (!cs->irq) { /* IRQ range check ?? */
  273. printk(KERN_WARNING "HiSax: %s: No IRQn", CardType[card->typ]);
  274. return (0);
  275. }
  276. if (!pci_memaddr) {
  277. printk(KERN_WARNING "HiSax: %s: No Memory base addressn", CardType[card->typ]);
  278. return (0);
  279. }
  280. cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096);
  281. /* Check suspecious address */
  282. pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
  283. if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
  284. printk(KERN_WARNING "HiSax: %s address %lx-%lx suspeciousn",
  285.        CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
  286. iounmap((void *) cs->hw.ax.base);
  287. cs->hw.ax.base = 0;
  288. return (0);
  289. }
  290. cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
  291. cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
  292. cs->hw.ax.isac_ale = GCS_1;
  293. cs->hw.ax.jade_ale = GCS_3;
  294. #else
  295. printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOSn", CardType[card->typ]);
  296. printk(KERN_WARNING "HiSax: %s: unable to configuren", CardType[card->typ]);
  297. return (0);
  298. #endif /* CONFIG_PCI */
  299. printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %dn",
  300.        CardType[card->typ], cs->hw.ax.base, cs->irq);
  301. reset_bkm(cs);
  302. cs->readisac = &ReadISAC;
  303. cs->writeisac = &WriteISAC;
  304. cs->readisacfifo = &ReadISACfifo;
  305. cs->writeisacfifo = &WriteISACfifo;
  306. cs->BC_Read_Reg = &ReadJADE;
  307. cs->BC_Write_Reg = &WriteJADE;
  308. cs->BC_Send_Data = &jade_fill_fifo;
  309. cs->cardmsg = &BKM_card_msg;
  310. cs->irq_func = &bkm_interrupt;
  311. cs->irq_flags |= SA_SHIRQ;
  312. ISACVersion(cs, "Telekom A4T:");
  313. /* Jade version */
  314. JadeVersion(cs, "Telekom A4T:");
  315. return (1);
  316. }