1 /* $Id: bkm_a4t.c,v 1.1.4.1 2001/11/20 14:19:35 kai 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
13 #define __NO_VERSION__
14
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"
24
25 extern const char *CardType[];
26
27 const char *bkm_a4t_revision = "$Revision: 1.1.4.1 $";
28
29
30 static inline u_char
readreg(unsigned int ale,unsigned long adr,u_char off)31 readreg(unsigned int ale, unsigned long adr, u_char off)
32 {
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);
45 }
46
47
48 static inline void
readfifo(unsigned int ale,unsigned long adr,u_char off,u_char * data,int size)49 readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
50 {
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);
55 }
56
57
58 static inline void
writereg(unsigned int ale,unsigned long adr,u_char off,u_char data)59 writereg(unsigned int ale, unsigned long adr, u_char off, u_char data)
60 {
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);
70 }
71
72
73 static inline void
writefifo(unsigned int ale,unsigned long adr,u_char off,u_char * data,int size)74 writefifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
75 {
76 /* fifo write without cli because it's allready done */
77 int i;
78
79 for (i = 0; i < size; i++)
80 writereg(ale, adr, off, *data++);
81 }
82
83
84 /* Interface functions */
85
86 static u_char
ReadISAC(struct IsdnCardState * cs,u_char offset)87 ReadISAC(struct IsdnCardState *cs, u_char offset)
88 {
89 return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset));
90 }
91
92 static void
WriteISAC(struct IsdnCardState * cs,u_char offset,u_char value)93 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
94 {
95 writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value);
96 }
97
98 static void
ReadISACfifo(struct IsdnCardState * cs,u_char * data,int size)99 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
100 {
101 readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
102 }
103
104 static void
WriteISACfifo(struct IsdnCardState * cs,u_char * data,int size)105 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
106 {
107 writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
108 }
109
110 static u_char
ReadJADE(struct IsdnCardState * cs,int jade,u_char offset)111 ReadJADE(struct IsdnCardState *cs, int jade, u_char offset)
112 {
113 return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80))));
114 }
115
116 static void
WriteJADE(struct IsdnCardState * cs,int jade,u_char offset,u_char value)117 WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value)
118 {
119 writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value);
120 }
121
122 /*
123 * fast interrupt JADE stuff goes here
124 */
125
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)
130
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)
135
136 #include "jade_irq.c"
137
138 static void
bkm_interrupt(int intno,void * dev_id,struct pt_regs * regs)139 bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
140 {
141 struct IsdnCardState *cs = dev_id;
142 u_char val = 0;
143 I20_REGISTER_FILE *pI20_Regs;
144
145 if (!cs) {
146 printk(KERN_WARNING "HiSax: Telekom A4T: Spurious interrupt!\n");
147 return;
148 }
149 pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
150
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);
161 }
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);
166 }
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);
171 }
172 /* Reenable ISDN interrupt */
173 pI20_Regs->i20IntCtrl |= intISDN;
174 }
175 }
176
177 void
release_io_bkm(struct IsdnCardState * cs)178 release_io_bkm(struct IsdnCardState *cs)
179 {
180 if (cs->hw.ax.base) {
181 iounmap((void *) cs->hw.ax.base);
182 cs->hw.ax.base = 0;
183 }
184 }
185
186 static void
enable_bkm_int(struct IsdnCardState * cs,unsigned bEnable)187 enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
188 {
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);
196 }
197 }
198
199 static void
reset_bkm(struct IsdnCardState * cs)200 reset_bkm(struct IsdnCardState *cs)
201 {
202 long flags;
203
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);
227
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);
235 }
236 }
237
238 static int
BKM_card_msg(struct IsdnCardState * cs,int mt,void * arg)239 BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
240 {
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);
263 }
264 return (0);
265 }
266
267 static struct pci_dev *dev_a4t __initdata = NULL;
268
269 int __init
setup_bkm_a4t(struct IsdnCard * card)270 setup_bkm_a4t(struct IsdnCard *card)
271 {
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
278
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);
285
286 #if CONFIG_PCI
287 if (!pci_present()) {
288 printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
289 return (0);
290 }
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;
295
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;
305 }
306 }
307 if (!found) {
308 printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
309 return (0);
310 }
311 if (!cs->irq) { /* IRQ range check ?? */
312 printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
313 return (0);
314 }
315 if (!pci_memaddr) {
316 printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
317 return (0);
318 }
319 cs->hw.ax.base = (long) 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 %lx-%lx 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);
328 }
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%lX IRQ %d\n",
339 CardType[card->typ], cs->hw.ax.base, cs->irq);
340
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);
356 }
357