1 /* $Id: teles0.c,v 2.9 1999/07/12 21:05:31 keil Exp $
3 * teles0.c low level stuff for Teles Memory IO isdn cards
4 * based on the teles driver from Jan den Ouden
6 * Author Karsten Keil (keil@temic-ech.spacenet.de)
8 * Thanks to Jan den Ouden
13 * Revision 2.9 1999/07/12 21:05:31 keil
14 * fix race in IRQ handling
15 * added watchdog for lost IRQs
17 * Revision 2.8 1998/04/15 16:44:28 keil
20 * Revision 2.7 1998/03/07 22:57:08 tsbogend
21 * made HiSax working on Linux/Alpha
23 * Revision 2.6 1998/02/03 23:27:47 keil
26 * Revision 2.5 1998/02/02 13:29:47 keil
29 * Revision 2.4 1997/11/08 21:35:54 keil
32 * Revision 2.3 1997/11/06 17:09:31 keil
35 * Revision 2.2 1997/10/29 18:55:57 keil
36 * changes for 2.1.60 (irq2dev_map)
38 * Revision 2.1 1997/07/27 21:47:10 keil
39 * new interface structures
41 * Revision 2.0 1997/06/26 11:02:43 keil
42 * New Layer and card interface
44 * Revision 1.8 1997/04/13 19:54:04 keil
45 * Change in IRQ check delay for SMP
47 * Revision 1.7 1997/04/06 22:54:04 keil
50 * removed old log info /KKe
53 #define __NO_VERSION__
59 extern const char *CardType
[];
61 const char *teles0_revision
= "$Revision: 2.9 $";
63 #define byteout(addr,val) outb(val,addr)
64 #define bytein(addr) inb(addr)
67 readisac(unsigned int adr
, u_char off
)
69 return readb(adr
+ ((off
& 1) ? 0x2ff : 0x100) + off
);
73 writeisac(unsigned int adr
, u_char off
, u_char data
)
75 writeb(data
, adr
+ ((off
& 1) ? 0x2ff : 0x100) + off
); mb();
80 readhscx(unsigned int adr
, int hscx
, u_char off
)
82 return readb(adr
+ (hscx
? 0x1c0 : 0x180) +
83 ((off
& 1) ? 0x1ff : 0) + off
);
87 writehscx(unsigned int adr
, int hscx
, u_char off
, u_char data
)
89 writeb(data
, adr
+ (hscx
? 0x1c0 : 0x180) +
90 ((off
& 1) ? 0x1ff : 0) + off
); mb();
94 read_fifo_isac(unsigned int adr
, u_char
* data
, int size
)
97 register u_char
*ad
= (u_char
*) ((long)adr
+ 0x100);
98 for (i
= 0; i
< size
; i
++)
103 write_fifo_isac(unsigned int adr
, u_char
* data
, int size
)
106 register u_char
*ad
= (u_char
*) ((long)adr
+ 0x100);
107 for (i
= 0; i
< size
; i
++) {
108 writeb(data
[i
], ad
); mb();
113 read_fifo_hscx(unsigned int adr
, int hscx
, u_char
* data
, int size
)
116 register u_char
*ad
= (u_char
*) ((long)adr
+ (hscx
? 0x1c0 : 0x180));
117 for (i
= 0; i
< size
; i
++)
122 write_fifo_hscx(unsigned int adr
, int hscx
, u_char
* data
, int size
)
125 register u_char
*ad
= (u_char
*) ((long)adr
+ (hscx
? 0x1c0 : 0x180));
126 for (i
= 0; i
< size
; i
++) {
127 writeb(data
[i
], ad
); mb();
131 /* Interface functions */
134 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
136 return (readisac(cs
->hw
.teles0
.membase
, offset
));
140 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
142 writeisac(cs
->hw
.teles0
.membase
, offset
, value
);
146 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
148 read_fifo_isac(cs
->hw
.teles0
.membase
, data
, size
);
152 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
154 write_fifo_isac(cs
->hw
.teles0
.membase
, data
, size
);
158 ReadHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
)
160 return (readhscx(cs
->hw
.teles0
.membase
, hscx
, offset
));
164 WriteHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
, u_char value
)
166 writehscx(cs
->hw
.teles0
.membase
, hscx
, offset
, value
);
170 * fast interrupt HSCX stuff goes here
173 #define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
174 #define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
175 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
176 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
178 #include "hscx_irq.c"
181 teles0_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
183 struct IsdnCardState
*cs
= dev_id
;
188 printk(KERN_WARNING
"Teles0: Spurious interrupt!\n");
191 val
= readhscx(cs
->hw
.teles0
.membase
, 1, HSCX_ISTA
);
194 hscx_int_main(cs
, val
);
195 val
= readisac(cs
->hw
.teles0
.membase
, ISAC_ISTA
);
198 isac_interrupt(cs
, val
);
200 val
= readhscx(cs
->hw
.teles0
.membase
, 1, HSCX_ISTA
);
201 if (val
&& count
< 5) {
202 if (cs
->debug
& L1_DEB_HSCX
)
203 debugl1(cs
, "HSCX IntStat after IntRoutine");
206 val
= readisac(cs
->hw
.teles0
.membase
, ISAC_ISTA
);
207 if (val
&& count
< 5) {
208 if (cs
->debug
& L1_DEB_ISAC
)
209 debugl1(cs
, "ISAC IntStat after IntRoutine");
212 writehscx(cs
->hw
.teles0
.membase
, 0, HSCX_MASK
, 0xFF);
213 writehscx(cs
->hw
.teles0
.membase
, 1, HSCX_MASK
, 0xFF);
214 writeisac(cs
->hw
.teles0
.membase
, ISAC_MASK
, 0xFF);
215 writeisac(cs
->hw
.teles0
.membase
, ISAC_MASK
, 0x0);
216 writehscx(cs
->hw
.teles0
.membase
, 0, HSCX_MASK
, 0x0);
217 writehscx(cs
->hw
.teles0
.membase
, 1, HSCX_MASK
, 0x0);
221 release_io_teles0(struct IsdnCardState
*cs
)
223 if (cs
->hw
.teles0
.cfg_reg
)
224 release_region(cs
->hw
.teles0
.cfg_reg
, 8);
228 reset_teles0(struct IsdnCardState
*cs
)
235 if (cs
->hw
.teles0
.cfg_reg
) {
265 cfval
|= ((cs
->hw
.teles0
.membase
>> 9) & 0xF0);
266 byteout(cs
->hw
.teles0
.cfg_reg
+ 4, cfval
);
267 HZDELAY(HZ
/ 10 + 1);
268 byteout(cs
->hw
.teles0
.cfg_reg
+ 4, cfval
| 1);
269 HZDELAY(HZ
/ 10 + 1);
271 writeb(0, cs
->hw
.teles0
.membase
+ 0x80); mb();
273 writeb(1, cs
->hw
.teles0
.membase
+ 0x80); mb();
275 restore_flags(flags
);
280 Teles_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
287 release_io_teles0(cs
);
299 setup_teles0(struct IsdnCard
*card
)
302 struct IsdnCardState
*cs
= card
->cs
;
305 strcpy(tmp
, teles0_revision
);
306 printk(KERN_INFO
"HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp
));
307 if ((cs
->typ
!= ISDN_CTYPE_16_0
) && (cs
->typ
!= ISDN_CTYPE_8_0
))
310 if (cs
->typ
== ISDN_CTYPE_16_0
)
311 cs
->hw
.teles0
.cfg_reg
= card
->para
[2];
313 cs
->hw
.teles0
.cfg_reg
= 0;
315 if (card
->para
[1] < 0x10000) {
318 "Teles0: membase configured DOSish, assuming 0x%lx\n",
319 (unsigned long) card
->para
[1]);
321 cs
->hw
.teles0
.membase
= card
->para
[1];
322 cs
->irq
= card
->para
[0];
323 if (cs
->hw
.teles0
.cfg_reg
) {
324 if (check_region((cs
->hw
.teles0
.cfg_reg
), 8)) {
326 "HiSax: %s config port %x-%x already in use\n",
328 cs
->hw
.teles0
.cfg_reg
,
329 cs
->hw
.teles0
.cfg_reg
+ 8);
332 request_region(cs
->hw
.teles0
.cfg_reg
, 8, "teles cfg");
335 if (cs
->hw
.teles0
.cfg_reg
) {
336 if ((val
= bytein(cs
->hw
.teles0
.cfg_reg
+ 0)) != 0x51) {
337 printk(KERN_WARNING
"Teles0: 16.0 Byte at %x is %x\n",
338 cs
->hw
.teles0
.cfg_reg
+ 0, val
);
339 release_region(cs
->hw
.teles0
.cfg_reg
, 8);
342 if ((val
= bytein(cs
->hw
.teles0
.cfg_reg
+ 1)) != 0x93) {
343 printk(KERN_WARNING
"Teles0: 16.0 Byte at %x is %x\n",
344 cs
->hw
.teles0
.cfg_reg
+ 1, val
);
345 release_region(cs
->hw
.teles0
.cfg_reg
, 8);
348 val
= bytein(cs
->hw
.teles0
.cfg_reg
+ 2); /* 0x1e=without AB
352 if (val
!= 0x1e && val
!= 0x1f) {
353 printk(KERN_WARNING
"Teles0: 16.0 Byte at %x is %x\n",
354 cs
->hw
.teles0
.cfg_reg
+ 2, val
);
355 release_region(cs
->hw
.teles0
.cfg_reg
, 8);
359 /* 16.0 and 8.0 designed for IOM1 */
360 test_and_set_bit(HW_IOM1
, &cs
->HW_Flags
);
362 "HiSax: %s config irq:%d mem:0x%X cfg:0x%X\n",
363 CardType
[cs
->typ
], cs
->irq
,
364 cs
->hw
.teles0
.membase
, cs
->hw
.teles0
.cfg_reg
);
365 if (reset_teles0(cs
)) {
366 printk(KERN_WARNING
"Teles0: wrong IRQ\n");
367 release_io_teles0(cs
);
370 cs
->readisac
= &ReadISAC
;
371 cs
->writeisac
= &WriteISAC
;
372 cs
->readisacfifo
= &ReadISACfifo
;
373 cs
->writeisacfifo
= &WriteISACfifo
;
374 cs
->BC_Read_Reg
= &ReadHSCX
;
375 cs
->BC_Write_Reg
= &WriteHSCX
;
376 cs
->BC_Send_Data
= &hscx_fill_fifo
;
377 cs
->cardmsg
= &Teles_card_msg
;
378 cs
->irq_func
= &teles0_interrupt
;
379 ISACVersion(cs
, "Teles0:");
380 if (HscxVersion(cs
, "Teles0:")) {
382 "Teles0: wrong HSCX versions check IO/MEM addresses\n");
383 release_io_teles0(cs
);