1 /* $Id: avm_a1.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
3 * low level stuff for AVM A1 (Fritz) isdn cards
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
13 #define __NO_VERSION__
14 #include <linux/init.h>
20 extern const char *CardType[];
21 static const char *avm_revision = "$Revision: 1.1.4.1 $";
23 #define AVM_A1_STAT_ISAC 0x01
24 #define AVM_A1_STAT_HSCX 0x02
25 #define AVM_A1_STAT_TIMER 0x04
27 #define byteout(addr,val) outb(val,addr)
28 #define bytein(addr) inb(addr)
31 readreg(unsigned int adr, u_char off)
33 return (bytein(adr + off));
37 writereg(unsigned int adr, u_char off, u_char data)
39 byteout(adr + off, data);
44 read_fifo(unsigned int adr, u_char * data, int size)
46 insb(adr, data, size);
50 write_fifo(unsigned int adr, u_char * data, int size)
52 outsb(adr, data, size);
55 /* Interface functions */
58 ReadISAC(struct IsdnCardState *cs, u_char offset)
60 return (readreg(cs->hw.avm.isac, offset));
64 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
66 writereg(cs->hw.avm.isac, offset, value);
70 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
72 read_fifo(cs->hw.avm.isacfifo, data, size);
76 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
78 write_fifo(cs->hw.avm.isacfifo, data, size);
82 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
84 return (readreg(cs->hw.avm.hscx[hscx], offset));
88 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
90 writereg(cs->hw.avm.hscx[hscx], offset, value);
94 * fast interrupt HSCX stuff goes here
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)
102 #include "hscx_irq.c"
105 avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs)
107 struct IsdnCardState *cs = dev_id;
111 printk(KERN_WARNING "AVM A1: Spurious interrupt!\n");
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);
123 hscx_int_main(cs, val);
125 if (!(sval & AVM_A1_STAT_ISAC)) {
126 val = readreg(cs->hw.avm.isac, ISAC_ISTA);
128 isac_interrupt(cs, val);
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);
140 release_ioregs(struct IsdnCardState *cs, int mask)
142 release_region(cs->hw.avm.cfg_reg, 8);
144 release_region(cs->hw.avm.isac + 32, 32);
146 release_region(cs->hw.avm.isacfifo, 1);
148 release_region(cs->hw.avm.hscx[0] + 32, 32);
150 release_region(cs->hw.avm.hscxfifo[0], 1);
152 release_region(cs->hw.avm.hscx[1] + 32, 32);
154 release_region(cs->hw.avm.hscxfifo[1], 1);
158 AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
164 release_ioregs(cs, 0x3f);
168 byteout(cs->hw.avm.cfg_reg, 0x16);
169 byteout(cs->hw.avm.cfg_reg, 0x1E);
179 setup_avm_a1(struct IsdnCard *card)
182 struct IsdnCardState *cs = card->cs;
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)
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)) {
201 "HiSax: %s config port %x-%x already in use\n",
204 cs->hw.avm.cfg_reg + 8);
207 request_region(cs->hw.avm.cfg_reg, 8, "avm cfg");
209 if (check_region((cs->hw.avm.isac + 32), 32)) {
211 "HiSax: %s isac ports %x-%x already in use\n",
213 cs->hw.avm.isac + 32,
214 cs->hw.avm.isac + 64);
215 release_ioregs(cs, 0);
218 request_region(cs->hw.avm.isac + 32, 32, "HiSax isac");
220 if (check_region((cs->hw.avm.isacfifo), 1)) {
222 "HiSax: %s isac fifo port %x already in use\n",
224 cs->hw.avm.isacfifo);
225 release_ioregs(cs, 1);
228 request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo");
230 if (check_region((cs->hw.avm.hscx[0]) + 32, 32)) {
232 "HiSax: %s hscx A ports %x-%x already in use\n",
234 cs->hw.avm.hscx[0] + 32,
235 cs->hw.avm.hscx[0] + 64);
236 release_ioregs(cs, 3);
239 request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A");
241 if (check_region(cs->hw.avm.hscxfifo[0], 1)) {
243 "HiSax: %s hscx A fifo port %x already in use\n",
245 cs->hw.avm.hscxfifo[0]);
246 release_ioregs(cs, 7);
249 request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo");
251 if (check_region(cs->hw.avm.hscx[1] + 32, 32)) {
253 "HiSax: %s hscx B ports %x-%x already in use\n",
255 cs->hw.avm.hscx[1] + 32,
256 cs->hw.avm.hscx[1] + 64);
257 release_ioregs(cs, 0xf);
260 request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B");
262 if (check_region(cs->hw.avm.hscxfifo[1], 1)) {
264 "HiSax: %s hscx B fifo port %x already in use\n",
266 cs->hw.avm.hscxfifo[1]);
267 release_ioregs(cs, 0x1f);
270 request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo");
273 byteout(cs->hw.avm.cfg_reg, 0x0);
276 byteout(cs->hw.avm.cfg_reg, 0x1);
278 byteout(cs->hw.avm.cfg_reg, 0x0);
283 byteout(cs->hw.avm.cfg_reg + 1, val);
285 byteout(cs->hw.avm.cfg_reg, 0x0);
287 restore_flags(flags);
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);
303 "HiSax: %s config irq:%d cfg:0x%X\n",
304 CardType[cs->typ], cs->irq,
307 "HiSax: isac:0x%X/0x%X\n",
308 cs->hw.avm.isac + 32, cs->hw.avm.isacfifo);
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]);
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:")) {
326 "AVM A1: wrong HSCX versions check IO address\n");
327 release_ioregs(cs, 0x3f);