Import 2.4.0-test6pre6
[davej-history.git] / drivers / isdn / hisax / bkm_a4t.c
blob17e3a19a78faccb4cd53e350b90b243dfba43e9e
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>
16 #include "hisax.h"
17 #include "isac.h"
18 #include "hscx.h"
19 #include "jade.h"
20 #include "isdnl1.h"
21 #include "bkm_ax.h"
22 #include <linux/pci.h>
24 extern const char *CardType[];
26 const char *bkm_a4t_revision = "$Revision: 1.9 $";
29 static inline u_char
30 readreg(unsigned int ale, unsigned int adr, u_char off)
32 register u_int ret;
33 long flags;
34 unsigned int *po = (unsigned int *) adr; /* Postoffice */
35 save_flags(flags);
36 cli();
37 *po = (GCS_2 | PO_WRITE | off);
38 __WAITI20__(po);
39 *po = (ale | PO_READ);
40 __WAITI20__(po);
41 ret = *po;
42 restore_flags(flags);
43 return ((unsigned char) ret);
47 static inline void
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 */
51 int i;
52 for (i = 0; i < size; i++)
53 *data++ = readreg(ale, adr, off);
57 static inline void
58 writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
60 long flags;
61 unsigned int *po = (unsigned int *) adr; /* Postoffice */
62 save_flags(flags);
63 cli();
64 *po = (GCS_2 | PO_WRITE | off);
65 __WAITI20__(po);
66 *po = (ale | PO_WRITE | data);
67 __WAITI20__(po);
68 restore_flags(flags);
72 static inline void
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 */
76 int i;
78 for (i = 0; i < size; i++)
79 writereg(ale, adr, off, *data++);
83 /* Interface functions */
85 static u_char
86 ReadISAC(struct IsdnCardState *cs, u_char offset)
88 return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset));
91 static void
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);
97 static void
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);
103 static void
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);
109 static u_char
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))));
115 static void
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"
137 static void
138 bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
140 struct IsdnCardState *cs = dev_id;
141 u_char val = 0;
142 I20_REGISTER_FILE *pI20_Regs;
144 if (!cs) {
145 printk(KERN_WARNING "HiSax: Telekom A4T: Spurious interrupt!\n");
146 return;
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);
158 if (val) {
159 jade_int_main(cs, val, 0);
161 /* Channel B */
162 val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0xC0);
163 if (val) {
164 jade_int_main(cs, val, 1);
166 /* D-Channel */
167 val = readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, ISAC_ISTA);
168 if (val) {
169 isac_interrupt(cs, val);
171 /* Reenable ISDN interrupt */
172 pI20_Regs->i20IntCtrl |= intISDN;
176 void
177 release_io_bkm(struct IsdnCardState *cs)
179 if (cs->hw.ax.base) {
180 iounmap((void *) cs->hw.ax.base);
181 cs->hw.ax.base = 0;
185 static void
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);
190 if (bEnable)
191 pI20_Regs->i20IntCtrl |= (intISDN | intPCI);
192 else
193 /* CAUTION: This disables the video capture driver too */
194 pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI);
198 static void
199 reset_bkm(struct IsdnCardState *cs)
201 long flags;
203 if (cs->typ == ISDN_CTYPE_BKM_A4T) {
204 I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
205 save_flags(flags);
206 sti();
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 |
219 g_A4T_JADE_RES |
220 g_A4T_ISAR_RES |
221 g_A4T_ISAC_RES |
222 g_A4T_JADE_BOOTR |
223 g_A4T_ISAR_BOOTR;
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 |
229 g_A4T_JADE_RES |
230 g_A4T_ISAR_RES);
231 set_current_state(TASK_UNINTERRUPTIBLE);
232 schedule_timeout((10 * HZ) / 1000);
233 restore_flags(flags);
237 static int
238 BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
240 switch (mt) {
241 case CARD_RESET:
242 /* Disable ints */
243 enable_bkm_int(cs, 0);
244 reset_bkm(cs);
245 return (0);
246 case CARD_RELEASE:
247 /* Sanity */
248 enable_bkm_int(cs, 0);
249 reset_bkm(cs);
250 release_io_bkm(cs);
251 return (0);
252 case CARD_INIT:
253 clear_pending_isac_ints(cs);
254 clear_pending_jade_ints(cs);
255 initisac(cs);
256 initjade(cs);
257 /* Enable ints */
258 enable_bkm_int(cs, 1);
259 return (0);
260 case CARD_TEST:
261 return (0);
263 return (0);
266 static struct pci_dev *dev_a4t __initdata = NULL;
268 __initfunc(int
269 setup_bkm_a4t(struct IsdnCard *card))
271 struct IsdnCardState *cs = card->cs;
272 char tmp[64];
273 u_int pci_memaddr = 0, found = 0;
274 I20_REGISTER_FILE *pI20_Regs;
275 #if CONFIG_PCI
276 #endif
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;
282 } else
283 return (0);
285 #if CONFIG_PCI
286 if (!pci_present()) {
287 printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
288 return (0);
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))
294 return (0);
295 pci_read_config_dword(dev_a4t, PCI_SUBSYSTEM_VENDOR_ID,
296 &sub_sys_id);
297 if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) {
298 found = 1;
299 pci_memaddr = pci_resource_start (dev_a4t, 0);
300 cs->irq = dev_a4t->irq;
303 if (!found) {
304 printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
305 return (0);
307 if (!cs->irq) { /* IRQ range check ?? */
308 printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
309 return (0);
311 if (!pci_memaddr) {
312 printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
313 return (0);
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);
322 cs->hw.ax.base = 0;
323 return (0);
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;
329 #else
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]);
332 return (0);
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);
337 reset_bkm(cs);
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:");
349 /* Jade version */
350 JadeVersion(cs, "Telekom A4T:");
351 return (1);