Import 2.4.0-test6pre6
[davej-history.git] / drivers / isdn / hisax / teles0.c
blobc9c5838a5d7685a6cc8d6101c51247686ff455c7
1 /* $Id: teles0.c,v 2.12 2000/06/26 08:59:14 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@isdn4linux.de)
8 * Thanks to Jan den Ouden
9 * Fritz Elfert
10 * Beat Doebeli
12 * This file is (c) under GNU PUBLIC LICENSE
15 #define __NO_VERSION__
16 #include "hisax.h"
17 #include "isdnl1.h"
18 #include "isac.h"
19 #include "hscx.h"
21 extern const char *CardType[];
23 const char *teles0_revision = "$Revision: 2.12 $";
25 #define TELES_IOMEM_SIZE 0x400
26 #define byteout(addr,val) outb(val,addr)
27 #define bytein(addr) inb(addr)
29 static inline u_char
30 readisac(unsigned long adr, u_char off)
32 return readb(adr + ((off & 1) ? 0x2ff : 0x100) + off);
35 static inline void
36 writeisac(unsigned long adr, u_char off, u_char data)
38 writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb();
42 static inline u_char
43 readhscx(unsigned long adr, int hscx, u_char off)
45 return readb(adr + (hscx ? 0x1c0 : 0x180) +
46 ((off & 1) ? 0x1ff : 0) + off);
49 static inline void
50 writehscx(unsigned long adr, int hscx, u_char off, u_char data)
52 writeb(data, adr + (hscx ? 0x1c0 : 0x180) +
53 ((off & 1) ? 0x1ff : 0) + off); mb();
56 static inline void
57 read_fifo_isac(unsigned long adr, u_char * data, int size)
59 register int i;
60 register u_char *ad = (u_char *)adr + 0x100;
61 for (i = 0; i < size; i++)
62 data[i] = readb(ad);
65 static inline void
66 write_fifo_isac(unsigned long adr, u_char * data, int size)
68 register int i;
69 register u_char *ad = (u_char *)adr + 0x100;
70 for (i = 0; i < size; i++) {
71 writeb(data[i], ad); mb();
75 static inline void
76 read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size)
78 register int i;
79 register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180));
80 for (i = 0; i < size; i++)
81 data[i] = readb(ad);
84 static inline void
85 write_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size)
87 int i;
88 register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180));
89 for (i = 0; i < size; i++) {
90 writeb(data[i], ad); mb();
94 /* Interface functions */
96 static u_char
97 ReadISAC(struct IsdnCardState *cs, u_char offset)
99 return (readisac(cs->hw.teles0.membase, offset));
102 static void
103 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
105 writeisac(cs->hw.teles0.membase, offset, value);
108 static void
109 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
111 read_fifo_isac(cs->hw.teles0.membase, data, size);
114 static void
115 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
117 write_fifo_isac(cs->hw.teles0.membase, data, size);
120 static u_char
121 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
123 return (readhscx(cs->hw.teles0.membase, hscx, offset));
126 static void
127 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
129 writehscx(cs->hw.teles0.membase, hscx, offset, value);
133 * fast interrupt HSCX stuff goes here
136 #define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
137 #define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
138 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
139 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
141 #include "hscx_irq.c"
143 static void
144 teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs)
146 struct IsdnCardState *cs = dev_id;
147 u_char val;
148 int count = 0;
150 if (!cs) {
151 printk(KERN_WARNING "Teles0: Spurious interrupt!\n");
152 return;
154 val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
155 Start_HSCX:
156 if (val)
157 hscx_int_main(cs, val);
158 val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
159 Start_ISAC:
160 if (val)
161 isac_interrupt(cs, val);
162 count++;
163 val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
164 if (val && count < 5) {
165 if (cs->debug & L1_DEB_HSCX)
166 debugl1(cs, "HSCX IntStat after IntRoutine");
167 goto Start_HSCX;
169 val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
170 if (val && count < 5) {
171 if (cs->debug & L1_DEB_ISAC)
172 debugl1(cs, "ISAC IntStat after IntRoutine");
173 goto Start_ISAC;
175 writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
176 writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
177 writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
178 writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
179 writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
180 writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
183 void
184 release_io_teles0(struct IsdnCardState *cs)
186 if (cs->hw.teles0.cfg_reg)
187 release_region(cs->hw.teles0.cfg_reg, 8);
188 iounmap((unsigned char *)cs->hw.teles0.membase);
189 release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
192 static int
193 reset_teles0(struct IsdnCardState *cs)
195 u_char cfval;
196 long flags;
198 save_flags(flags);
199 sti();
200 if (cs->hw.teles0.cfg_reg) {
201 switch (cs->irq) {
202 case 2:
203 case 9:
204 cfval = 0x00;
205 break;
206 case 3:
207 cfval = 0x02;
208 break;
209 case 4:
210 cfval = 0x04;
211 break;
212 case 5:
213 cfval = 0x06;
214 break;
215 case 10:
216 cfval = 0x08;
217 break;
218 case 11:
219 cfval = 0x0A;
220 break;
221 case 12:
222 cfval = 0x0C;
223 break;
224 case 15:
225 cfval = 0x0E;
226 break;
227 default:
228 return(1);
230 cfval |= ((cs->hw.teles0.phymem >> 9) & 0xF0);
231 byteout(cs->hw.teles0.cfg_reg + 4, cfval);
232 HZDELAY(HZ / 10 + 1);
233 byteout(cs->hw.teles0.cfg_reg + 4, cfval | 1);
234 HZDELAY(HZ / 10 + 1);
236 writeb(0, cs->hw.teles0.membase + 0x80); mb();
237 HZDELAY(HZ / 5 + 1);
238 writeb(1, cs->hw.teles0.membase + 0x80); mb();
239 HZDELAY(HZ / 5 + 1);
240 restore_flags(flags);
241 return(0);
244 static int
245 Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
247 switch (mt) {
248 case CARD_RESET:
249 reset_teles0(cs);
250 return(0);
251 case CARD_RELEASE:
252 release_io_teles0(cs);
253 return(0);
254 case CARD_INIT:
255 inithscxisac(cs, 3);
256 return(0);
257 case CARD_TEST:
258 return(0);
260 return(0);
263 __initfunc(int
264 setup_teles0(struct IsdnCard *card))
266 u_char val;
267 struct IsdnCardState *cs = card->cs;
268 char tmp[64];
270 strcpy(tmp, teles0_revision);
271 printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp));
272 if ((cs->typ != ISDN_CTYPE_16_0) && (cs->typ != ISDN_CTYPE_8_0))
273 return (0);
275 if (cs->typ == ISDN_CTYPE_16_0)
276 cs->hw.teles0.cfg_reg = card->para[2];
277 else /* 8.0 */
278 cs->hw.teles0.cfg_reg = 0;
280 if (card->para[1] < 0x10000) {
281 card->para[1] <<= 4;
282 printk(KERN_INFO
283 "Teles0: membase configured DOSish, assuming 0x%lx\n",
284 (unsigned long) card->para[1]);
286 cs->irq = card->para[0];
287 if (cs->hw.teles0.cfg_reg) {
288 if (check_region(cs->hw.teles0.cfg_reg, 8)) {
289 printk(KERN_WARNING
290 "HiSax: %s config port %x-%x already in use\n",
291 CardType[card->typ],
292 cs->hw.teles0.cfg_reg,
293 cs->hw.teles0.cfg_reg + 8);
294 return (0);
295 } else {
296 request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg");
299 if (cs->hw.teles0.cfg_reg) {
300 if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
301 printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
302 cs->hw.teles0.cfg_reg + 0, val);
303 release_region(cs->hw.teles0.cfg_reg, 8);
304 return (0);
306 if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
307 printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
308 cs->hw.teles0.cfg_reg + 1, val);
309 release_region(cs->hw.teles0.cfg_reg, 8);
310 return (0);
312 val = bytein(cs->hw.teles0.cfg_reg + 2); /* 0x1e=without AB
313 * 0x1f=with AB
314 * 0x1c 16.3 ???
316 if (val != 0x1e && val != 0x1f) {
317 printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
318 cs->hw.teles0.cfg_reg + 2, val);
319 release_region(cs->hw.teles0.cfg_reg, 8);
320 return (0);
323 /* 16.0 and 8.0 designed for IOM1 */
324 test_and_set_bit(HW_IOM1, &cs->HW_Flags);
325 cs->hw.teles0.phymem = card->para[1];
326 if (check_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE)) {
327 printk(KERN_WARNING
328 "HiSax: %s memory region %lx-%lx already in use\n",
329 CardType[card->typ],
330 cs->hw.teles0.phymem,
331 cs->hw.teles0.phymem + TELES_IOMEM_SIZE);
332 if (cs->hw.teles0.cfg_reg)
333 release_region(cs->hw.teles0.cfg_reg, 8);
334 return (0);
335 } else {
336 request_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE,
337 "teles iomem");
339 cs->hw.teles0.membase =
340 (unsigned long) ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
341 printk(KERN_INFO
342 "HiSax: %s config irq:%d mem:0x%lX cfg:0x%X\n",
343 CardType[cs->typ], cs->irq,
344 cs->hw.teles0.membase, cs->hw.teles0.cfg_reg);
345 if (reset_teles0(cs)) {
346 printk(KERN_WARNING "Teles0: wrong IRQ\n");
347 release_io_teles0(cs);
348 return (0);
350 cs->readisac = &ReadISAC;
351 cs->writeisac = &WriteISAC;
352 cs->readisacfifo = &ReadISACfifo;
353 cs->writeisacfifo = &WriteISACfifo;
354 cs->BC_Read_Reg = &ReadHSCX;
355 cs->BC_Write_Reg = &WriteHSCX;
356 cs->BC_Send_Data = &hscx_fill_fifo;
357 cs->cardmsg = &Teles_card_msg;
358 cs->irq_func = &teles0_interrupt;
359 ISACVersion(cs, "Teles0:");
360 if (HscxVersion(cs, "Teles0:")) {
361 printk(KERN_WARNING
362 "Teles0: wrong HSCX versions check IO/MEM addresses\n");
363 release_io_teles0(cs);
364 return (0);
366 return (1);