bkm_a4t.c 8.7 KB

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