more debug output
[linux-2.4.git] / drivers / isdn / hisax / avm_a1.c
1 /* $Id: avm_a1.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
2  *
3  * low level stuff for AVM A1 (Fritz) isdn cards
4  *
5  * Author       Karsten Keil
6  * Copyright    by Karsten Keil      <keil@isdn4linux.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 #include <linux/init.h>
15 #include "hisax.h"
16 #include "isac.h"
17 #include "hscx.h"
18 #include "isdnl1.h"
19
20 extern const char *CardType[];
21 static const char *avm_revision = "$Revision: 1.1.4.1 $";
22
23 #define  AVM_A1_STAT_ISAC       0x01
24 #define  AVM_A1_STAT_HSCX       0x02
25 #define  AVM_A1_STAT_TIMER      0x04
26
27 #define byteout(addr,val) outb(val,addr)
28 #define bytein(addr) inb(addr)
29
30 static inline u_char
31 readreg(unsigned int adr, u_char off)
32 {
33         return (bytein(adr + off));
34 }
35
36 static inline void
37 writereg(unsigned int adr, u_char off, u_char data)
38 {
39         byteout(adr + off, data);
40 }
41
42
43 static inline void
44 read_fifo(unsigned int adr, u_char * data, int size)
45 {
46         insb(adr, data, size);
47 }
48
49 static void
50 write_fifo(unsigned int adr, u_char * data, int size)
51 {
52         outsb(adr, data, size);
53 }
54
55 /* Interface functions */
56
57 static u_char
58 ReadISAC(struct IsdnCardState *cs, u_char offset)
59 {
60         return (readreg(cs->hw.avm.isac, offset));
61 }
62
63 static void
64 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
65 {
66         writereg(cs->hw.avm.isac, offset, value);
67 }
68
69 static void
70 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
71 {
72         read_fifo(cs->hw.avm.isacfifo, data, size);
73 }
74
75 static void
76 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
77 {
78         write_fifo(cs->hw.avm.isacfifo, data, size);
79 }
80
81 static u_char
82 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
83 {
84         return (readreg(cs->hw.avm.hscx[hscx], offset));
85 }
86
87 static void
88 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
89 {
90         writereg(cs->hw.avm.hscx[hscx], offset, value);
91 }
92
93 /*
94  * fast interrupt HSCX stuff goes here
95  */
96
97 #define READHSCX(cs, nr, reg) readreg(cs->hw.avm.hscx[nr], reg)
98 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.avm.hscx[nr], reg, data)
99 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
100 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
101
102 #include "hscx_irq.c"
103
104 static void
105 avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs)
106 {
107         struct IsdnCardState *cs = dev_id;
108         u_char val, sval;
109
110         if (!cs) {
111                 printk(KERN_WARNING "AVM A1: Spurious interrupt!\n");
112                 return;
113         }
114         while (((sval = bytein(cs->hw.avm.cfg_reg)) & 0xf) != 0x7) {
115                 if (!(sval & AVM_A1_STAT_TIMER)) {
116                         byteout(cs->hw.avm.cfg_reg, 0x1E);
117                         sval = bytein(cs->hw.avm.cfg_reg);
118                 } else if (cs->debug & L1_DEB_INTSTAT)
119                         debugl1(cs, "avm IntStatus %x", sval);
120                 if (!(sval & AVM_A1_STAT_HSCX)) {
121                         val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA);
122                         if (val)
123                                 hscx_int_main(cs, val);
124                 }
125                 if (!(sval & AVM_A1_STAT_ISAC)) {
126                         val = readreg(cs->hw.avm.isac, ISAC_ISTA);
127                         if (val)
128                                 isac_interrupt(cs, val);
129                 }
130         }
131         writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF);
132         writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF);
133         writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF);
134         writereg(cs->hw.avm.isac, ISAC_MASK, 0x0);
135         writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0);
136         writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0);
137 }
138
139 inline static void
140 release_ioregs(struct IsdnCardState *cs, int mask)
141 {
142         release_region(cs->hw.avm.cfg_reg, 8);
143         if (mask & 1)
144                 release_region(cs->hw.avm.isac + 32, 32);
145         if (mask & 2)
146                 release_region(cs->hw.avm.isacfifo, 1);
147         if (mask & 4)
148                 release_region(cs->hw.avm.hscx[0] + 32, 32);
149         if (mask & 8)
150                 release_region(cs->hw.avm.hscxfifo[0], 1);
151         if (mask & 0x10)
152                 release_region(cs->hw.avm.hscx[1] + 32, 32);
153         if (mask & 0x20)
154                 release_region(cs->hw.avm.hscxfifo[1], 1);
155 }
156
157 static int
158 AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
159 {
160         switch (mt) {
161                 case CARD_RESET:
162                         return(0);
163                 case CARD_RELEASE:
164                         release_ioregs(cs, 0x3f);
165                         return(0);
166                 case CARD_INIT:
167                         inithscxisac(cs, 1);
168                         byteout(cs->hw.avm.cfg_reg, 0x16);
169                         byteout(cs->hw.avm.cfg_reg, 0x1E);
170                         inithscxisac(cs, 2);
171                         return(0);
172                 case CARD_TEST:
173                         return(0);
174         }
175         return(0);
176 }
177
178 int __init
179 setup_avm_a1(struct IsdnCard *card)
180 {
181         u_char val;
182         struct IsdnCardState *cs = card->cs;
183         long flags;
184         char tmp[64];
185
186         strcpy(tmp, avm_revision);
187         printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
188         if (cs->typ != ISDN_CTYPE_A1)
189                 return (0);
190
191         cs->hw.avm.cfg_reg = card->para[1] + 0x1800;
192         cs->hw.avm.isac = card->para[1] + 0x1400 - 0x20;
193         cs->hw.avm.hscx[0] = card->para[1] + 0x400 - 0x20;
194         cs->hw.avm.hscx[1] = card->para[1] + 0xc00 - 0x20;
195         cs->hw.avm.isacfifo = card->para[1] + 0x1000;
196         cs->hw.avm.hscxfifo[0] = card->para[1];
197         cs->hw.avm.hscxfifo[1] = card->para[1] + 0x800;
198         cs->irq = card->para[0];
199         if (check_region((cs->hw.avm.cfg_reg), 8)) {
200                 printk(KERN_WARNING
201                        "HiSax: %s config port %x-%x already in use\n",
202                        CardType[card->typ],
203                        cs->hw.avm.cfg_reg,
204                        cs->hw.avm.cfg_reg + 8);
205                 return (0);
206         } else {
207                 request_region(cs->hw.avm.cfg_reg, 8, "avm cfg");
208         }
209         if (check_region((cs->hw.avm.isac + 32), 32)) {
210                 printk(KERN_WARNING
211                        "HiSax: %s isac ports %x-%x already in use\n",
212                        CardType[cs->typ],
213                        cs->hw.avm.isac + 32,
214                        cs->hw.avm.isac + 64);
215                 release_ioregs(cs, 0);
216                 return (0);
217         } else {
218                 request_region(cs->hw.avm.isac + 32, 32, "HiSax isac");
219         }
220         if (check_region((cs->hw.avm.isacfifo), 1)) {
221                 printk(KERN_WARNING
222                        "HiSax: %s isac fifo port %x already in use\n",
223                        CardType[cs->typ],
224                        cs->hw.avm.isacfifo);
225                 release_ioregs(cs, 1);
226                 return (0);
227         } else {
228                 request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo");
229         }
230         if (check_region((cs->hw.avm.hscx[0]) + 32, 32)) {
231                 printk(KERN_WARNING
232                        "HiSax: %s hscx A ports %x-%x already in use\n",
233                        CardType[cs->typ],
234                        cs->hw.avm.hscx[0] + 32,
235                        cs->hw.avm.hscx[0] + 64);
236                 release_ioregs(cs, 3);
237                 return (0);
238         } else {
239                 request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A");
240         }
241         if (check_region(cs->hw.avm.hscxfifo[0], 1)) {
242                 printk(KERN_WARNING
243                        "HiSax: %s hscx A fifo port %x already in use\n",
244                        CardType[cs->typ],
245                        cs->hw.avm.hscxfifo[0]);
246                 release_ioregs(cs, 7);
247                 return (0);
248         } else {
249                 request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo");
250         }
251         if (check_region(cs->hw.avm.hscx[1] + 32, 32)) {
252                 printk(KERN_WARNING
253                        "HiSax: %s hscx B ports %x-%x already in use\n",
254                        CardType[cs->typ],
255                        cs->hw.avm.hscx[1] + 32,
256                        cs->hw.avm.hscx[1] + 64);
257                 release_ioregs(cs, 0xf);
258                 return (0);
259         } else {
260                 request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B");
261         }
262         if (check_region(cs->hw.avm.hscxfifo[1], 1)) {
263                 printk(KERN_WARNING
264                        "HiSax: %s hscx B fifo port %x already in use\n",
265                        CardType[cs->typ],
266                        cs->hw.avm.hscxfifo[1]);
267                 release_ioregs(cs, 0x1f);
268                 return (0);
269         } else {
270                 request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo");
271         }
272         save_flags(flags);
273         byteout(cs->hw.avm.cfg_reg, 0x0);
274         sti();
275         HZDELAY(HZ / 5 + 1);
276         byteout(cs->hw.avm.cfg_reg, 0x1);
277         HZDELAY(HZ / 5 + 1);
278         byteout(cs->hw.avm.cfg_reg, 0x0);
279         HZDELAY(HZ / 5 + 1);
280         val = cs->irq;
281         if (val == 9)
282                 val = 2;
283         byteout(cs->hw.avm.cfg_reg + 1, val);
284         HZDELAY(HZ / 5 + 1);
285         byteout(cs->hw.avm.cfg_reg, 0x0);
286         HZDELAY(HZ / 5 + 1);
287         restore_flags(flags);
288
289         val = bytein(cs->hw.avm.cfg_reg);
290         printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
291                cs->hw.avm.cfg_reg, val);
292         val = bytein(cs->hw.avm.cfg_reg + 3);
293         printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
294                cs->hw.avm.cfg_reg + 3, val);
295         val = bytein(cs->hw.avm.cfg_reg + 2);
296         printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
297                cs->hw.avm.cfg_reg + 2, val);
298         val = bytein(cs->hw.avm.cfg_reg);
299         printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
300                cs->hw.avm.cfg_reg, val);
301
302         printk(KERN_INFO
303                "HiSax: %s config irq:%d cfg:0x%X\n",
304                CardType[cs->typ], cs->irq,
305                cs->hw.avm.cfg_reg);
306         printk(KERN_INFO
307                "HiSax: isac:0x%X/0x%X\n",
308                cs->hw.avm.isac + 32, cs->hw.avm.isacfifo);
309         printk(KERN_INFO
310                "HiSax: hscx A:0x%X/0x%X  hscx B:0x%X/0x%X\n",
311                cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0],
312                cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]);
313
314         cs->readisac = &ReadISAC;
315         cs->writeisac = &WriteISAC;
316         cs->readisacfifo = &ReadISACfifo;
317         cs->writeisacfifo = &WriteISACfifo;
318         cs->BC_Read_Reg = &ReadHSCX;
319         cs->BC_Write_Reg = &WriteHSCX;
320         cs->BC_Send_Data = &hscx_fill_fifo;
321         cs->cardmsg = &AVM_card_msg;
322         cs->irq_func = &avm_a1_interrupt;
323         ISACVersion(cs, "AVM A1:");
324         if (HscxVersion(cs, "AVM A1:")) {
325                 printk(KERN_WARNING
326                        "AVM A1: wrong HSCX versions check IO address\n");
327                 release_ioregs(cs, 0x3f);
328                 return (0);
329         }
330         return (1);
331 }