1 /* $Id: bkm_a4t.c,v 1.11 2000/06/26 08:59:12 keil 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>
22 #include <linux/pci.h>
24 extern const char *CardType
[];
26 const char *bkm_a4t_revision
= "$Revision: 1.9 $";
30 readreg(unsigned int ale
, unsigned int adr
, u_char off
)
34 unsigned int *po
= (unsigned int *) adr
; /* Postoffice */
37 *po
= (GCS_2
| PO_WRITE
| off
);
39 *po
= (ale
| PO_READ
);
43 return ((unsigned char) ret
);
48 readfifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
* data
, int size
)
50 /* fifo read without cli because it's allready done */
52 for (i
= 0; i
< size
; i
++)
53 *data
++ = readreg(ale
, adr
, off
);
58 writereg(unsigned int ale
, unsigned int adr
, u_char off
, u_char data
)
61 unsigned int *po
= (unsigned int *) adr
; /* Postoffice */
64 *po
= (GCS_2
| PO_WRITE
| off
);
66 *po
= (ale
| PO_WRITE
| data
);
73 writefifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
* data
, int size
)
75 /* fifo write without cli because it's allready done */
78 for (i
= 0; i
< size
; i
++)
79 writereg(ale
, adr
, off
, *data
++);
83 /* Interface functions */
86 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
88 return (readreg(cs
->hw
.ax
.isac_ale
, cs
->hw
.ax
.isac_adr
, offset
));
92 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
94 writereg(cs
->hw
.ax
.isac_ale
, cs
->hw
.ax
.isac_adr
, offset
, value
);
98 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
100 readfifo(cs
->hw
.ax
.isac_ale
, cs
->hw
.ax
.isac_adr
, 0, data
, size
);
104 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
106 writefifo(cs
->hw
.ax
.isac_ale
, cs
->hw
.ax
.isac_adr
, 0, data
, size
);
110 ReadJADE(struct IsdnCardState
*cs
, int jade
, u_char offset
)
112 return (readreg(cs
->hw
.ax
.jade_ale
, cs
->hw
.ax
.jade_adr
, offset
+ (jade
== -1 ? 0 : (jade
? 0xC0 : 0x80))));
116 WriteJADE(struct IsdnCardState
*cs
, int jade
, u_char offset
, u_char value
)
118 writereg(cs
->hw
.ax
.jade_ale
, cs
->hw
.ax
.jade_adr
, offset
+ (jade
== -1 ? 0 : (jade
? 0xC0 : 0x80)), value
);
122 * fast interrupt JADE stuff goes here
125 #define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,\
126 cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)))
127 #define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,\
128 cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data)
130 #define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,\
131 cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
132 #define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,\
133 cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
135 #include "jade_irq.c"
138 bkm_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
140 struct IsdnCardState
*cs
= dev_id
;
142 I20_REGISTER_FILE
*pI20_Regs
;
145 printk(KERN_WARNING
"HiSax: Telekom A4T: Spurious interrupt!\n");
148 pI20_Regs
= (I20_REGISTER_FILE
*) (cs
->hw
.ax
.base
);
150 /* ISDN interrupt pending? */
151 if (pI20_Regs
->i20IntStatus
& intISDN
) {
152 /* Reset the ISDN interrupt */
153 pI20_Regs
->i20IntStatus
= intISDN
;
154 /* Disable ISDN interrupt */
155 pI20_Regs
->i20IntCtrl
&= ~intISDN
;
156 /* Channel A first */
157 val
= readreg(cs
->hw
.ax
.jade_ale
, cs
->hw
.ax
.jade_adr
, jade_HDLC_ISR
+ 0x80);
159 jade_int_main(cs
, val
, 0);
162 val
= readreg(cs
->hw
.ax
.jade_ale
, cs
->hw
.ax
.jade_adr
, jade_HDLC_ISR
+ 0xC0);
164 jade_int_main(cs
, val
, 1);
167 val
= readreg(cs
->hw
.ax
.isac_ale
, cs
->hw
.ax
.isac_adr
, ISAC_ISTA
);
169 isac_interrupt(cs
, val
);
171 /* Reenable ISDN interrupt */
172 pI20_Regs
->i20IntCtrl
|= intISDN
;
177 release_io_bkm(struct IsdnCardState
*cs
)
179 if (cs
->hw
.ax
.base
) {
180 iounmap((void *) cs
->hw
.ax
.base
);
186 enable_bkm_int(struct IsdnCardState
*cs
, unsigned bEnable
)
188 if (cs
->typ
== ISDN_CTYPE_BKM_A4T
) {
189 I20_REGISTER_FILE
*pI20_Regs
= (I20_REGISTER_FILE
*) (cs
->hw
.ax
.base
);
191 pI20_Regs
->i20IntCtrl
|= (intISDN
| intPCI
);
193 /* CAUTION: This disables the video capture driver too */
194 pI20_Regs
->i20IntCtrl
&= ~(intISDN
| intPCI
);
199 reset_bkm(struct IsdnCardState
*cs
)
203 if (cs
->typ
== ISDN_CTYPE_BKM_A4T
) {
204 I20_REGISTER_FILE
*pI20_Regs
= (I20_REGISTER_FILE
*) (cs
->hw
.ax
.base
);
207 /* Issue the I20 soft reset */
208 pI20_Regs
->i20SysControl
= 0xFF; /* all in */
209 set_current_state(TASK_UNINTERRUPTIBLE
);
210 schedule_timeout((10 * HZ
) / 1000);
211 /* Remove the soft reset */
212 pI20_Regs
->i20SysControl
= sysRESET
| 0xFF;
213 set_current_state(TASK_UNINTERRUPTIBLE
);
214 schedule_timeout((10 * HZ
) / 1000);
215 /* Set our configuration */
216 pI20_Regs
->i20SysControl
= sysRESET
| sysCFG
;
217 /* Issue ISDN reset */
218 pI20_Regs
->i20GuestControl
= guestWAIT_CFG
|
224 set_current_state(TASK_UNINTERRUPTIBLE
);
225 schedule_timeout((10 * HZ
) / 1000);
227 /* Remove RESET state from ISDN */
228 pI20_Regs
->i20GuestControl
&= ~(g_A4T_ISAC_RES
|
231 set_current_state(TASK_UNINTERRUPTIBLE
);
232 schedule_timeout((10 * HZ
) / 1000);
233 restore_flags(flags
);
238 BKM_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
243 enable_bkm_int(cs
, 0);
248 enable_bkm_int(cs
, 0);
253 clear_pending_isac_ints(cs
);
254 clear_pending_jade_ints(cs
);
258 enable_bkm_int(cs
, 1);
266 static struct pci_dev
*dev_a4t __initdata
= NULL
;
269 setup_bkm_a4t(struct IsdnCard
*card
))
271 struct IsdnCardState
*cs
= card
->cs
;
273 u_int pci_memaddr
= 0, found
= 0;
274 I20_REGISTER_FILE
*pI20_Regs
;
278 strcpy(tmp
, bkm_a4t_revision
);
279 printk(KERN_INFO
"HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp
));
280 if (cs
->typ
== ISDN_CTYPE_BKM_A4T
) {
281 cs
->subtyp
= BKM_A4T
;
286 if (!pci_present()) {
287 printk(KERN_ERR
"bkm_a4t: no PCI bus present\n");
290 if ((dev_a4t
= pci_find_device(I20_VENDOR_ID
, I20_DEVICE_ID
, dev_a4t
))) {
291 u_int sub_sys_id
= 0;
293 if (pci_enable_device(dev_a4t
))
295 pci_read_config_dword(dev_a4t
, PCI_SUBSYSTEM_VENDOR_ID
,
297 if (sub_sys_id
== ((A4T_SUBSYS_ID
<< 16) | A4T_SUBVEN_ID
)) {
299 pci_memaddr
= pci_resource_start (dev_a4t
, 0);
300 cs
->irq
= dev_a4t
->irq
;
304 printk(KERN_WARNING
"HiSax: %s: Card not found\n", CardType
[card
->typ
]);
307 if (!cs
->irq
) { /* IRQ range check ?? */
308 printk(KERN_WARNING
"HiSax: %s: No IRQ\n", CardType
[card
->typ
]);
312 printk(KERN_WARNING
"HiSax: %s: No Memory base address\n", CardType
[card
->typ
]);
315 cs
->hw
.ax
.base
= (u_int
) ioremap(pci_memaddr
, 4096);
316 /* Check suspecious address */
317 pI20_Regs
= (I20_REGISTER_FILE
*) (cs
->hw
.ax
.base
);
318 if ((pI20_Regs
->i20IntStatus
& 0x8EFFFFFF) != 0) {
319 printk(KERN_WARNING
"HiSax: %s address %x-%x suspecious\n",
320 CardType
[card
->typ
], cs
->hw
.ax
.base
, cs
->hw
.ax
.base
+ 4096);
321 iounmap((void *) cs
->hw
.ax
.base
);
325 cs
->hw
.ax
.isac_adr
= cs
->hw
.ax
.base
+ PO_OFFSET
;
326 cs
->hw
.ax
.jade_adr
= cs
->hw
.ax
.base
+ PO_OFFSET
;
327 cs
->hw
.ax
.isac_ale
= GCS_1
;
328 cs
->hw
.ax
.jade_ale
= GCS_3
;
330 printk(KERN_WARNING
"HiSax: %s: NO_PCI_BIOS\n", CardType
[card
->typ
]);
331 printk(KERN_WARNING
"HiSax: %s: unable to configure\n", CardType
[card
->typ
]);
333 #endif /* CONFIG_PCI */
334 printk(KERN_INFO
"HiSax: %s: Card configured at 0x%X IRQ %d\n",
335 CardType
[card
->typ
], cs
->hw
.ax
.base
, cs
->irq
);
338 cs
->readisac
= &ReadISAC
;
339 cs
->writeisac
= &WriteISAC
;
340 cs
->readisacfifo
= &ReadISACfifo
;
341 cs
->writeisacfifo
= &WriteISACfifo
;
342 cs
->BC_Read_Reg
= &ReadJADE
;
343 cs
->BC_Write_Reg
= &WriteJADE
;
344 cs
->BC_Send_Data
= &jade_fill_fifo
;
345 cs
->cardmsg
= &BKM_card_msg
;
346 cs
->irq_func
= &bkm_interrupt
;
347 cs
->irq_flags
|= SA_SHIRQ
;
348 ISACVersion(cs
, "Telekom A4T:");
350 JadeVersion(cs
, "Telekom A4T:");