* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / isdn / hisax / teles0.c
blob4046c4357d25ee8a75c670eaff958a729b6d0a89
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
9 * Fritz Elfert
10 * Beat Doebeli
12 * $Log: teles0.c,v $
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
18 * new init code
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
24 * IRQ 9
26 * Revision 2.5 1998/02/02 13:29:47 keil
27 * fast io
29 * Revision 2.4 1997/11/08 21:35:54 keil
30 * new l1 init
32 * Revision 2.3 1997/11/06 17:09:31 keil
33 * New 2.1 init code
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
48 * Using SKB's
50 * removed old log info /KKe
53 #define __NO_VERSION__
54 #include "hisax.h"
55 #include "isdnl1.h"
56 #include "isac.h"
57 #include "hscx.h"
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)
66 static inline u_char
67 readisac(unsigned int adr, u_char off)
69 return readb(adr + ((off & 1) ? 0x2ff : 0x100) + off);
72 static inline void
73 writeisac(unsigned int adr, u_char off, u_char data)
75 writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb();
79 static inline u_char
80 readhscx(unsigned int adr, int hscx, u_char off)
82 return readb(adr + (hscx ? 0x1c0 : 0x180) +
83 ((off & 1) ? 0x1ff : 0) + off);
86 static inline void
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();
93 static inline void
94 read_fifo_isac(unsigned int adr, u_char * data, int size)
96 register int i;
97 register u_char *ad = (u_char *) ((long)adr + 0x100);
98 for (i = 0; i < size; i++)
99 data[i] = readb(ad);
102 static inline void
103 write_fifo_isac(unsigned int adr, u_char * data, int size)
105 register int i;
106 register u_char *ad = (u_char *) ((long)adr + 0x100);
107 for (i = 0; i < size; i++) {
108 writeb(data[i], ad); mb();
112 static inline void
113 read_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
115 register int i;
116 register u_char *ad = (u_char *) ((long)adr + (hscx ? 0x1c0 : 0x180));
117 for (i = 0; i < size; i++)
118 data[i] = readb(ad);
121 static inline void
122 write_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
124 int i;
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 */
133 static u_char
134 ReadISAC(struct IsdnCardState *cs, u_char offset)
136 return (readisac(cs->hw.teles0.membase, offset));
139 static void
140 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
142 writeisac(cs->hw.teles0.membase, offset, value);
145 static void
146 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
148 read_fifo_isac(cs->hw.teles0.membase, data, size);
151 static void
152 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
154 write_fifo_isac(cs->hw.teles0.membase, data, size);
157 static u_char
158 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
160 return (readhscx(cs->hw.teles0.membase, hscx, offset));
163 static void
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"
180 static void
181 teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs)
183 struct IsdnCardState *cs = dev_id;
184 u_char val;
185 int count = 0;
187 if (!cs) {
188 printk(KERN_WARNING "Teles0: Spurious interrupt!\n");
189 return;
191 val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
192 Start_HSCX:
193 if (val)
194 hscx_int_main(cs, val);
195 val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
196 Start_ISAC:
197 if (val)
198 isac_interrupt(cs, val);
199 count++;
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");
204 goto Start_HSCX;
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");
210 goto Start_ISAC;
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);
220 void
221 release_io_teles0(struct IsdnCardState *cs)
223 if (cs->hw.teles0.cfg_reg)
224 release_region(cs->hw.teles0.cfg_reg, 8);
227 static int
228 reset_teles0(struct IsdnCardState *cs)
230 u_char cfval;
231 long flags;
233 save_flags(flags);
234 sti();
235 if (cs->hw.teles0.cfg_reg) {
236 switch (cs->irq) {
237 case 2:
238 case 9:
239 cfval = 0x00;
240 break;
241 case 3:
242 cfval = 0x02;
243 break;
244 case 4:
245 cfval = 0x04;
246 break;
247 case 5:
248 cfval = 0x06;
249 break;
250 case 10:
251 cfval = 0x08;
252 break;
253 case 11:
254 cfval = 0x0A;
255 break;
256 case 12:
257 cfval = 0x0C;
258 break;
259 case 15:
260 cfval = 0x0E;
261 break;
262 default:
263 return(1);
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();
272 HZDELAY(HZ / 5 + 1);
273 writeb(1, cs->hw.teles0.membase + 0x80); mb();
274 HZDELAY(HZ / 5 + 1);
275 restore_flags(flags);
276 return(0);
279 static int
280 Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
282 switch (mt) {
283 case CARD_RESET:
284 reset_teles0(cs);
285 return(0);
286 case CARD_RELEASE:
287 release_io_teles0(cs);
288 return(0);
289 case CARD_INIT:
290 inithscxisac(cs, 3);
291 return(0);
292 case CARD_TEST:
293 return(0);
295 return(0);
298 int __init
299 setup_teles0(struct IsdnCard *card)
301 u_char val;
302 struct IsdnCardState *cs = card->cs;
303 char tmp[64];
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))
308 return (0);
310 if (cs->typ == ISDN_CTYPE_16_0)
311 cs->hw.teles0.cfg_reg = card->para[2];
312 else /* 8.0 */
313 cs->hw.teles0.cfg_reg = 0;
315 if (card->para[1] < 0x10000) {
316 card->para[1] <<= 4;
317 printk(KERN_INFO
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)) {
325 printk(KERN_WARNING
326 "HiSax: %s config port %x-%x already in use\n",
327 CardType[card->typ],
328 cs->hw.teles0.cfg_reg,
329 cs->hw.teles0.cfg_reg + 8);
330 return (0);
331 } else {
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);
340 return (0);
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);
346 return (0);
348 val = bytein(cs->hw.teles0.cfg_reg + 2); /* 0x1e=without AB
349 * 0x1f=with AB
350 * 0x1c 16.3 ???
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);
356 return (0);
359 /* 16.0 and 8.0 designed for IOM1 */
360 test_and_set_bit(HW_IOM1, &cs->HW_Flags);
361 printk(KERN_INFO
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);
368 return (0);
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:")) {
381 printk(KERN_WARNING
382 "Teles0: wrong HSCX versions check IO/MEM addresses\n");
383 release_io_teles0(cs);
384 return (0);
386 return (1);