1 /* $Id: avm_a1.c,v 2.13 2000/11/24 17:05:37 kai Exp $
3 * avm_a1.c low level stuff for AVM A1 (Fritz) isdn cards
5 * Author Karsten Keil (keil@isdn4linux.de)
7 * This file is (c) under GNU PUBLIC LICENSE
10 #define __NO_VERSION__
11 #include <linux/init.h>
17 extern const char *CardType
[];
18 static const char *avm_revision
= "$Revision: 2.13 $";
20 #define AVM_A1_STAT_ISAC 0x01
21 #define AVM_A1_STAT_HSCX 0x02
22 #define AVM_A1_STAT_TIMER 0x04
24 #define byteout(addr,val) outb(val,addr)
25 #define bytein(addr) inb(addr)
28 readreg(unsigned int adr
, u_char off
)
30 return (bytein(adr
+ off
));
34 writereg(unsigned int adr
, u_char off
, u_char data
)
36 byteout(adr
+ off
, data
);
41 read_fifo(unsigned int adr
, u_char
* data
, int size
)
43 insb(adr
, data
, size
);
47 write_fifo(unsigned int adr
, u_char
* data
, int size
)
49 outsb(adr
, data
, size
);
52 /* Interface functions */
55 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
57 return (readreg(cs
->hw
.avm
.isac
, offset
));
61 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
63 writereg(cs
->hw
.avm
.isac
, offset
, value
);
67 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
69 read_fifo(cs
->hw
.avm
.isacfifo
, data
, size
);
73 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
75 write_fifo(cs
->hw
.avm
.isacfifo
, data
, size
);
79 ReadHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
)
81 return (readreg(cs
->hw
.avm
.hscx
[hscx
], offset
));
85 WriteHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
, u_char value
)
87 writereg(cs
->hw
.avm
.hscx
[hscx
], offset
, value
);
91 * fast interrupt HSCX stuff goes here
94 #define READHSCX(cs, nr, reg) readreg(cs->hw.avm.hscx[nr], reg)
95 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.avm.hscx[nr], reg, data)
96 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
97 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
102 avm_a1_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
104 struct IsdnCardState
*cs
= dev_id
;
108 printk(KERN_WARNING
"AVM A1: Spurious interrupt!\n");
111 while (((sval
= bytein(cs
->hw
.avm
.cfg_reg
)) & 0xf) != 0x7) {
112 if (!(sval
& AVM_A1_STAT_TIMER
)) {
113 byteout(cs
->hw
.avm
.cfg_reg
, 0x1E);
114 sval
= bytein(cs
->hw
.avm
.cfg_reg
);
115 } else if (cs
->debug
& L1_DEB_INTSTAT
)
116 debugl1(cs
, "avm IntStatus %x", sval
);
117 if (!(sval
& AVM_A1_STAT_HSCX
)) {
118 val
= readreg(cs
->hw
.avm
.hscx
[1], HSCX_ISTA
);
120 hscx_int_main(cs
, val
);
122 if (!(sval
& AVM_A1_STAT_ISAC
)) {
123 val
= readreg(cs
->hw
.avm
.isac
, ISAC_ISTA
);
125 isac_interrupt(cs
, val
);
128 writereg(cs
->hw
.avm
.hscx
[0], HSCX_MASK
, 0xFF);
129 writereg(cs
->hw
.avm
.hscx
[1], HSCX_MASK
, 0xFF);
130 writereg(cs
->hw
.avm
.isac
, ISAC_MASK
, 0xFF);
131 writereg(cs
->hw
.avm
.isac
, ISAC_MASK
, 0x0);
132 writereg(cs
->hw
.avm
.hscx
[0], HSCX_MASK
, 0x0);
133 writereg(cs
->hw
.avm
.hscx
[1], HSCX_MASK
, 0x0);
137 release_ioregs(struct IsdnCardState
*cs
, int mask
)
139 release_region(cs
->hw
.avm
.cfg_reg
, 8);
141 release_region(cs
->hw
.avm
.isac
+ 32, 32);
143 release_region(cs
->hw
.avm
.isacfifo
, 1);
145 release_region(cs
->hw
.avm
.hscx
[0] + 32, 32);
147 release_region(cs
->hw
.avm
.hscxfifo
[0], 1);
149 release_region(cs
->hw
.avm
.hscx
[1] + 32, 32);
151 release_region(cs
->hw
.avm
.hscxfifo
[1], 1);
155 AVM_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
161 release_ioregs(cs
, 0x3f);
165 byteout(cs
->hw
.avm
.cfg_reg
, 0x16);
166 byteout(cs
->hw
.avm
.cfg_reg
, 0x1E);
176 setup_avm_a1(struct IsdnCard
*card
)
179 struct IsdnCardState
*cs
= card
->cs
;
183 strcpy(tmp
, avm_revision
);
184 printk(KERN_INFO
"HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp
));
185 if (cs
->typ
!= ISDN_CTYPE_A1
)
188 cs
->hw
.avm
.cfg_reg
= card
->para
[1] + 0x1800;
189 cs
->hw
.avm
.isac
= card
->para
[1] + 0x1400 - 0x20;
190 cs
->hw
.avm
.hscx
[0] = card
->para
[1] + 0x400 - 0x20;
191 cs
->hw
.avm
.hscx
[1] = card
->para
[1] + 0xc00 - 0x20;
192 cs
->hw
.avm
.isacfifo
= card
->para
[1] + 0x1000;
193 cs
->hw
.avm
.hscxfifo
[0] = card
->para
[1];
194 cs
->hw
.avm
.hscxfifo
[1] = card
->para
[1] + 0x800;
195 cs
->irq
= card
->para
[0];
196 if (check_region((cs
->hw
.avm
.cfg_reg
), 8)) {
198 "HiSax: %s config port %x-%x already in use\n",
201 cs
->hw
.avm
.cfg_reg
+ 8);
204 request_region(cs
->hw
.avm
.cfg_reg
, 8, "avm cfg");
206 if (check_region((cs
->hw
.avm
.isac
+ 32), 32)) {
208 "HiSax: %s isac ports %x-%x already in use\n",
210 cs
->hw
.avm
.isac
+ 32,
211 cs
->hw
.avm
.isac
+ 64);
212 release_ioregs(cs
, 0);
215 request_region(cs
->hw
.avm
.isac
+ 32, 32, "HiSax isac");
217 if (check_region((cs
->hw
.avm
.isacfifo
), 1)) {
219 "HiSax: %s isac fifo port %x already in use\n",
221 cs
->hw
.avm
.isacfifo
);
222 release_ioregs(cs
, 1);
225 request_region(cs
->hw
.avm
.isacfifo
, 1, "HiSax isac fifo");
227 if (check_region((cs
->hw
.avm
.hscx
[0]) + 32, 32)) {
229 "HiSax: %s hscx A ports %x-%x already in use\n",
231 cs
->hw
.avm
.hscx
[0] + 32,
232 cs
->hw
.avm
.hscx
[0] + 64);
233 release_ioregs(cs
, 3);
236 request_region(cs
->hw
.avm
.hscx
[0] + 32, 32, "HiSax hscx A");
238 if (check_region(cs
->hw
.avm
.hscxfifo
[0], 1)) {
240 "HiSax: %s hscx A fifo port %x already in use\n",
242 cs
->hw
.avm
.hscxfifo
[0]);
243 release_ioregs(cs
, 7);
246 request_region(cs
->hw
.avm
.hscxfifo
[0], 1, "HiSax hscx A fifo");
248 if (check_region(cs
->hw
.avm
.hscx
[1] + 32, 32)) {
250 "HiSax: %s hscx B ports %x-%x already in use\n",
252 cs
->hw
.avm
.hscx
[1] + 32,
253 cs
->hw
.avm
.hscx
[1] + 64);
254 release_ioregs(cs
, 0xf);
257 request_region(cs
->hw
.avm
.hscx
[1] + 32, 32, "HiSax hscx B");
259 if (check_region(cs
->hw
.avm
.hscxfifo
[1], 1)) {
261 "HiSax: %s hscx B fifo port %x already in use\n",
263 cs
->hw
.avm
.hscxfifo
[1]);
264 release_ioregs(cs
, 0x1f);
267 request_region(cs
->hw
.avm
.hscxfifo
[1], 1, "HiSax hscx B fifo");
270 byteout(cs
->hw
.avm
.cfg_reg
, 0x0);
273 byteout(cs
->hw
.avm
.cfg_reg
, 0x1);
275 byteout(cs
->hw
.avm
.cfg_reg
, 0x0);
280 byteout(cs
->hw
.avm
.cfg_reg
+ 1, val
);
282 byteout(cs
->hw
.avm
.cfg_reg
, 0x0);
284 restore_flags(flags
);
286 val
= bytein(cs
->hw
.avm
.cfg_reg
);
287 printk(KERN_INFO
"AVM A1: Byte at %x is %x\n",
288 cs
->hw
.avm
.cfg_reg
, val
);
289 val
= bytein(cs
->hw
.avm
.cfg_reg
+ 3);
290 printk(KERN_INFO
"AVM A1: Byte at %x is %x\n",
291 cs
->hw
.avm
.cfg_reg
+ 3, val
);
292 val
= bytein(cs
->hw
.avm
.cfg_reg
+ 2);
293 printk(KERN_INFO
"AVM A1: Byte at %x is %x\n",
294 cs
->hw
.avm
.cfg_reg
+ 2, val
);
295 val
= bytein(cs
->hw
.avm
.cfg_reg
);
296 printk(KERN_INFO
"AVM A1: Byte at %x is %x\n",
297 cs
->hw
.avm
.cfg_reg
, val
);
300 "HiSax: %s config irq:%d cfg:0x%X\n",
301 CardType
[cs
->typ
], cs
->irq
,
304 "HiSax: isac:0x%X/0x%X\n",
305 cs
->hw
.avm
.isac
+ 32, cs
->hw
.avm
.isacfifo
);
307 "HiSax: hscx A:0x%X/0x%X hscx B:0x%X/0x%X\n",
308 cs
->hw
.avm
.hscx
[0] + 32, cs
->hw
.avm
.hscxfifo
[0],
309 cs
->hw
.avm
.hscx
[1] + 32, cs
->hw
.avm
.hscxfifo
[1]);
311 cs
->readisac
= &ReadISAC
;
312 cs
->writeisac
= &WriteISAC
;
313 cs
->readisacfifo
= &ReadISACfifo
;
314 cs
->writeisacfifo
= &WriteISACfifo
;
315 cs
->BC_Read_Reg
= &ReadHSCX
;
316 cs
->BC_Write_Reg
= &WriteHSCX
;
317 cs
->BC_Send_Data
= &hscx_fill_fifo
;
318 cs
->cardmsg
= &AVM_card_msg
;
319 cs
->irq_func
= &avm_a1_interrupt
;
320 ISACVersion(cs
, "AVM A1:");
321 if (HscxVersion(cs
, "AVM A1:")) {
323 "AVM A1: wrong HSCX versions check IO address\n");
324 release_ioregs(cs
, 0x3f);