bkm_a4t.c 8.9 KB

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