bkm_a4t.c 8.8 KB

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