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>
22 #include <linux/pci.h>
25 extern const char *CardType
[];
27 const char *bkm_a4t_revision
= "$Revision: 1.13.6.2 $";
31 readreg(unsigned int ale
, unsigned int adr
, u_char off
)
35 unsigned int *po
= (unsigned int *) adr
; /* Postoffice */
38 *po
= (GCS_2
| PO_WRITE
| off
);
40 *po
= (ale
| PO_READ
);
44 return ((unsigned char) ret
);
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 */
53 for (i
= 0; i
< size
; i
++)
54 *data
++ = readreg(ale
, adr
, off
);
59 writereg(unsigned int ale
, unsigned int adr
, u_char off
, u_char data
)
62 unsigned int *po
= (unsigned int *) adr
; /* Postoffice */
65 *po
= (GCS_2
| PO_WRITE
| off
);
67 *po
= (ale
| PO_WRITE
| data
);
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 */
79 for (i
= 0; i
< size
; i
++)
80 writereg(ale
, adr
, off
, *data
++);
84 /* Interface functions */
87 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
89 return (readreg(cs
->hw
.ax
.isac_ale
, cs
->hw
.ax
.isac_adr
, offset
));
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
);
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
);
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
);
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))));
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"
139 bkm_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
141 struct IsdnCardState
*cs
= dev_id
;
143 I20_REGISTER_FILE
*pI20_Regs
;
146 printk(KERN_WARNING
"HiSax: Telekom A4T: Spurious interrupt!\n");
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);
160 jade_int_main(cs
, val
, 0);
163 val
= readreg(cs
->hw
.ax
.jade_ale
, cs
->hw
.ax
.jade_adr
, jade_HDLC_ISR
+ 0xC0);
165 jade_int_main(cs
, val
, 1);
168 val
= readreg(cs
->hw
.ax
.isac_ale
, cs
->hw
.ax
.isac_adr
, ISAC_ISTA
);
170 isac_interrupt(cs
, val
);
172 /* Reenable ISDN interrupt */
173 pI20_Regs
->i20IntCtrl
|= intISDN
;
178 release_io_bkm(struct IsdnCardState
*cs
)
180 if (cs
->hw
.ax
.base
) {
181 iounmap((void *) cs
->hw
.ax
.base
);
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
);
192 pI20_Regs
->i20IntCtrl
|= (intISDN
| intPCI
);
194 /* CAUTION: This disables the video capture driver too */
195 pI20_Regs
->i20IntCtrl
&= ~(intISDN
| intPCI
);
200 reset_bkm(struct IsdnCardState
*cs
)
204 if (cs
->typ
== ISDN_CTYPE_BKM_A4T
) {
205 I20_REGISTER_FILE
*pI20_Regs
= (I20_REGISTER_FILE
*) (cs
->hw
.ax
.base
);
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
|
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
|
232 set_current_state(TASK_UNINTERRUPTIBLE
);
233 schedule_timeout((10 * HZ
) / 1000);
234 restore_flags(flags
);
239 BKM_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
244 enable_bkm_int(cs
, 0);
249 enable_bkm_int(cs
, 0);
254 clear_pending_isac_ints(cs
);
255 clear_pending_jade_ints(cs
);
259 enable_bkm_int(cs
, 1);
267 static struct pci_dev
*dev_a4t __initdata
= NULL
;
270 setup_bkm_a4t(struct IsdnCard
*card
)
272 struct IsdnCardState
*cs
= card
->cs
;
274 u_int pci_memaddr
= 0, found
= 0;
275 I20_REGISTER_FILE
*pI20_Regs
;
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
;
287 if (!pci_present()) {
288 printk(KERN_ERR
"bkm_a4t: no PCI bus present\n");
291 while ((dev_a4t
= pci_find_device(PCI_VENDOR_ID_ZORAN
,
292 PCI_DEVICE_ID_ZORAN_36120
, dev_a4t
))) {
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
))
302 pci_memaddr
= pci_resource_start(dev_a4t
, 0);
303 cs
->irq
= dev_a4t
->irq
;
308 printk(KERN_WARNING
"HiSax: %s: Card not found\n", CardType
[card
->typ
]);
311 if (!cs
->irq
) { /* IRQ range check ?? */
312 printk(KERN_WARNING
"HiSax: %s: No IRQ\n", CardType
[card
->typ
]);
316 printk(KERN_WARNING
"HiSax: %s: No Memory base address\n", CardType
[card
->typ
]);
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
);
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
;
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
]);
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
);
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:");
354 JadeVersion(cs
, "Telekom A4T:");