- Andries Brouwer: final isofs pieces.
[davej-history.git] / drivers / isdn / hisax / bkm_a4t.c
blobc8a4896a9f0272a2e0245e020773ee82e36ae530
1 /* $Id: bkm_a4t.c,v 1.13.6.2 2000/11/29 16:00:14 kai Exp $
2 * bkm_a4t.c low level stuff for T-Berkom A4T
3 * derived from the original file sedlbauer.c
4 * derived from the original file niccy.c
5 * derived from the original file netjet.c
7 * Author Roland Klabunde (R.Klabunde@Berkom.de)
9 * This file is (c) under GNU PUBLIC LICENSE
13 #define __NO_VERSION__
15 #include <linux/config.h>
16 #include <linux/init.h>
17 #include "hisax.h"
18 #include "isac.h"
19 #include "hscx.h"
20 #include "jade.h"
21 #include "isdnl1.h"
22 #include <linux/pci.h>
23 #include "bkm_ax.h"
25 extern const char *CardType[];
27 const char *bkm_a4t_revision = "$Revision: 1.13.6.2 $";
30 static inline u_char
31 readreg(unsigned int ale, unsigned int adr, u_char off)
33 register u_int ret;
34 long flags;
35 unsigned int *po = (unsigned int *) adr; /* Postoffice */
36 save_flags(flags);
37 cli();
38 *po = (GCS_2 | PO_WRITE | off);
39 __WAITI20__(po);
40 *po = (ale | PO_READ);
41 __WAITI20__(po);
42 ret = *po;
43 restore_flags(flags);
44 return ((unsigned char) ret);
48 static inline void
49 readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
51 /* fifo read without cli because it's allready done */
52 int i;
53 for (i = 0; i < size; i++)
54 *data++ = readreg(ale, adr, off);
58 static inline void
59 writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
61 long flags;
62 unsigned int *po = (unsigned int *) adr; /* Postoffice */
63 save_flags(flags);
64 cli();
65 *po = (GCS_2 | PO_WRITE | off);
66 __WAITI20__(po);
67 *po = (ale | PO_WRITE | data);
68 __WAITI20__(po);
69 restore_flags(flags);
73 static inline void
74 writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
76 /* fifo write without cli because it's allready done */
77 int i;
79 for (i = 0; i < size; i++)
80 writereg(ale, adr, off, *data++);
84 /* Interface functions */
86 static u_char
87 ReadISAC(struct IsdnCardState *cs, u_char offset)
89 return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset));
92 static void
93 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
95 writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value);
98 static void
99 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
101 readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
104 static void
105 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
107 writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
110 static u_char
111 ReadJADE(struct IsdnCardState *cs, int jade, u_char offset)
113 return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80))));
116 static void
117 WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value)
119 writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value);
123 * fast interrupt JADE stuff goes here
126 #define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,\
127 cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)))
128 #define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,\
129 cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data)
131 #define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,\
132 cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
133 #define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,\
134 cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
136 #include "jade_irq.c"
138 static void
139 bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
141 struct IsdnCardState *cs = dev_id;
142 u_char val = 0;
143 I20_REGISTER_FILE *pI20_Regs;
145 if (!cs) {
146 printk(KERN_WARNING "HiSax: Telekom A4T: Spurious interrupt!\n");
147 return;
149 pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
151 /* ISDN interrupt pending? */
152 if (pI20_Regs->i20IntStatus & intISDN) {
153 /* Reset the ISDN interrupt */
154 pI20_Regs->i20IntStatus = intISDN;
155 /* Disable ISDN interrupt */
156 pI20_Regs->i20IntCtrl &= ~intISDN;
157 /* Channel A first */
158 val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0x80);
159 if (val) {
160 jade_int_main(cs, val, 0);
162 /* Channel B */
163 val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0xC0);
164 if (val) {
165 jade_int_main(cs, val, 1);
167 /* D-Channel */
168 val = readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, ISAC_ISTA);
169 if (val) {
170 isac_interrupt(cs, val);
172 /* Reenable ISDN interrupt */
173 pI20_Regs->i20IntCtrl |= intISDN;
177 void
178 release_io_bkm(struct IsdnCardState *cs)
180 if (cs->hw.ax.base) {
181 iounmap((void *) cs->hw.ax.base);
182 cs->hw.ax.base = 0;
186 static void
187 enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
189 if (cs->typ == ISDN_CTYPE_BKM_A4T) {
190 I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
191 if (bEnable)
192 pI20_Regs->i20IntCtrl |= (intISDN | intPCI);
193 else
194 /* CAUTION: This disables the video capture driver too */
195 pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI);
199 static void
200 reset_bkm(struct IsdnCardState *cs)
202 long flags;
204 if (cs->typ == ISDN_CTYPE_BKM_A4T) {
205 I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
206 save_flags(flags);
207 sti();
208 /* Issue the I20 soft reset */
209 pI20_Regs->i20SysControl = 0xFF; /* all in */
210 set_current_state(TASK_UNINTERRUPTIBLE);
211 schedule_timeout((10 * HZ) / 1000);
212 /* Remove the soft reset */
213 pI20_Regs->i20SysControl = sysRESET | 0xFF;
214 set_current_state(TASK_UNINTERRUPTIBLE);
215 schedule_timeout((10 * HZ) / 1000);
216 /* Set our configuration */
217 pI20_Regs->i20SysControl = sysRESET | sysCFG;
218 /* Issue ISDN reset */
219 pI20_Regs->i20GuestControl = guestWAIT_CFG |
220 g_A4T_JADE_RES |
221 g_A4T_ISAR_RES |
222 g_A4T_ISAC_RES |
223 g_A4T_JADE_BOOTR |
224 g_A4T_ISAR_BOOTR;
225 set_current_state(TASK_UNINTERRUPTIBLE);
226 schedule_timeout((10 * HZ) / 1000);
228 /* Remove RESET state from ISDN */
229 pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES |
230 g_A4T_JADE_RES |
231 g_A4T_ISAR_RES);
232 set_current_state(TASK_UNINTERRUPTIBLE);
233 schedule_timeout((10 * HZ) / 1000);
234 restore_flags(flags);
238 static int
239 BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
241 switch (mt) {
242 case CARD_RESET:
243 /* Disable ints */
244 enable_bkm_int(cs, 0);
245 reset_bkm(cs);
246 return (0);
247 case CARD_RELEASE:
248 /* Sanity */
249 enable_bkm_int(cs, 0);
250 reset_bkm(cs);
251 release_io_bkm(cs);
252 return (0);
253 case CARD_INIT:
254 clear_pending_isac_ints(cs);
255 clear_pending_jade_ints(cs);
256 initisac(cs);
257 initjade(cs);
258 /* Enable ints */
259 enable_bkm_int(cs, 1);
260 return (0);
261 case CARD_TEST:
262 return (0);
264 return (0);
267 static struct pci_dev *dev_a4t __initdata = NULL;
269 int __init
270 setup_bkm_a4t(struct IsdnCard *card)
272 struct IsdnCardState *cs = card->cs;
273 char tmp[64];
274 u_int pci_memaddr = 0, found = 0;
275 I20_REGISTER_FILE *pI20_Regs;
276 #if CONFIG_PCI
277 #endif
279 strcpy(tmp, bkm_a4t_revision);
280 printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
281 if (cs->typ == ISDN_CTYPE_BKM_A4T) {
282 cs->subtyp = BKM_A4T;
283 } else
284 return (0);
286 #if CONFIG_PCI
287 if (!pci_present()) {
288 printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
289 return (0);
291 while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
292 PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
293 u16 sub_sys;
294 u16 sub_vendor;
296 sub_vendor = dev_a4t->subsystem_vendor;
297 sub_sys = dev_a4t->subsystem_device;
298 if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
299 if (pci_enable_device(dev_a4t))
300 return(0);
301 found = 1;
302 pci_memaddr = pci_resource_start(dev_a4t, 0);
303 cs->irq = dev_a4t->irq;
304 break;
307 if (!found) {
308 printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
309 return (0);
311 if (!cs->irq) { /* IRQ range check ?? */
312 printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
313 return (0);
315 if (!pci_memaddr) {
316 printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
317 return (0);
319 cs->hw.ax.base = (u_int) ioremap(pci_memaddr, 4096);
320 /* Check suspecious address */
321 pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
322 if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
323 printk(KERN_WARNING "HiSax: %s address %x-%x suspecious\n",
324 CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
325 iounmap((void *) cs->hw.ax.base);
326 cs->hw.ax.base = 0;
327 return (0);
329 cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
330 cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
331 cs->hw.ax.isac_ale = GCS_1;
332 cs->hw.ax.jade_ale = GCS_3;
333 #else
334 printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]);
335 printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]);
336 return (0);
337 #endif /* CONFIG_PCI */
338 printk(KERN_INFO "HiSax: %s: Card configured at 0x%X IRQ %d\n",
339 CardType[card->typ], cs->hw.ax.base, cs->irq);
341 reset_bkm(cs);
342 cs->readisac = &ReadISAC;
343 cs->writeisac = &WriteISAC;
344 cs->readisacfifo = &ReadISACfifo;
345 cs->writeisacfifo = &WriteISACfifo;
346 cs->BC_Read_Reg = &ReadJADE;
347 cs->BC_Write_Reg = &WriteJADE;
348 cs->BC_Send_Data = &jade_fill_fifo;
349 cs->cardmsg = &BKM_card_msg;
350 cs->irq_func = &bkm_interrupt;
351 cs->irq_flags |= SA_SHIRQ;
352 ISACVersion(cs, "Telekom A4T:");
353 /* Jade version */
354 JadeVersion(cs, "Telekom A4T:");
355 return (1);