1 /* $Id: avm_a1.c,v 2.10 1998/11/15 23:54:21 keil Exp $
3 * avm_a1.c low level stuff for AVM A1 (Fritz) isdn cards
5 * Author Karsten Keil (keil@isdn4linux.de)
9 * Revision 2.10 1998/11/15 23:54:21 keil
12 * Revision 2.9 1998/08/13 23:36:12 keil
13 * HiSax 3.1 - don't work stable with current LinkLevel
15 * Revision 2.8 1998/04/15 16:44:27 keil
18 * Revision 2.7 1998/02/02 13:29:37 keil
21 * Revision 2.6 1998/01/13 23:09:46 keil
22 * really disable timer
24 * Revision 2.5 1998/01/02 06:50:29 calle
25 * Perodic timer of A1 now disabled, no need for linux driver.
27 * Revision 2.4 1997/11/08 21:35:42 keil
30 * Revision 2.3 1997/11/06 17:13:32 keil
33 * Revision 2.2 1997/10/29 18:55:48 keil
34 * changes for 2.1.60 (irq2dev_map)
36 * Revision 2.1 1997/07/27 21:47:13 keil
37 * new interface structures
39 * Revision 2.0 1997/06/26 11:02:48 keil
40 * New Layer and card interface
42 * Revision 1.6 1997/04/13 19:54:07 keil
43 * Change in IRQ check delay for SMP
45 * Revision 1.5 1997/04/06 22:54:10 keil
48 * Revision 1.4 1997/01/27 15:50:21 keil
51 * Revision 1.3 1997/01/21 22:14:20 keil
54 * Revision 1.2 1996/10/27 22:07:31 keil
57 * Revision 1.1 1996/10/13 20:04:49 keil
62 #define __NO_VERSION__
68 extern const char *CardType
[];
69 static const char *avm_revision
= "$Revision: 2.10 $";
71 #define AVM_A1_STAT_ISAC 0x01
72 #define AVM_A1_STAT_HSCX 0x02
73 #define AVM_A1_STAT_TIMER 0x04
75 #define byteout(addr,val) outb(val,addr)
76 #define bytein(addr) inb(addr)
79 readreg(unsigned int adr
, u_char off
)
81 return (bytein(adr
+ off
));
85 writereg(unsigned int adr
, u_char off
, u_char data
)
87 byteout(adr
+ off
, data
);
92 read_fifo(unsigned int adr
, u_char
* data
, int size
)
94 insb(adr
, data
, size
);
98 write_fifo(unsigned int adr
, u_char
* data
, int size
)
100 outsb(adr
, data
, size
);
103 /* Interface functions */
106 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
108 return (readreg(cs
->hw
.avm
.isac
, offset
));
112 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
114 writereg(cs
->hw
.avm
.isac
, offset
, value
);
118 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
120 read_fifo(cs
->hw
.avm
.isacfifo
, data
, size
);
124 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
126 write_fifo(cs
->hw
.avm
.isacfifo
, data
, size
);
130 ReadHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
)
132 return (readreg(cs
->hw
.avm
.hscx
[hscx
], offset
));
136 WriteHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
, u_char value
)
138 writereg(cs
->hw
.avm
.hscx
[hscx
], offset
, value
);
142 * fast interrupt HSCX stuff goes here
145 #define READHSCX(cs, nr, reg) readreg(cs->hw.avm.hscx[nr], reg)
146 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.avm.hscx[nr], reg, data)
147 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
148 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
150 #include "hscx_irq.c"
153 avm_a1_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
155 struct IsdnCardState
*cs
= dev_id
;
156 u_char val
, sval
, stat
= 0;
159 printk(KERN_WARNING
"AVM A1: Spurious interrupt!\n");
162 while (((sval
= bytein(cs
->hw
.avm
.cfg_reg
)) & 0xf) != 0x7) {
163 if (!(sval
& AVM_A1_STAT_TIMER
)) {
164 byteout(cs
->hw
.avm
.cfg_reg
, 0x1E);
165 sval
= bytein(cs
->hw
.avm
.cfg_reg
);
166 } else if (cs
->debug
& L1_DEB_INTSTAT
)
167 debugl1(cs
, "avm IntStatus %x", sval
);
168 if (!(sval
& AVM_A1_STAT_HSCX
)) {
169 val
= readreg(cs
->hw
.avm
.hscx
[1], HSCX_ISTA
);
171 hscx_int_main(cs
, val
);
175 if (!(sval
& AVM_A1_STAT_ISAC
)) {
176 val
= readreg(cs
->hw
.avm
.isac
, ISAC_ISTA
);
178 isac_interrupt(cs
, val
);
184 writereg(cs
->hw
.avm
.hscx
[0], HSCX_MASK
, 0xFF);
185 writereg(cs
->hw
.avm
.hscx
[1], HSCX_MASK
, 0xFF);
186 writereg(cs
->hw
.avm
.hscx
[0], HSCX_MASK
, 0x0);
187 writereg(cs
->hw
.avm
.hscx
[1], HSCX_MASK
, 0x0);
190 writereg(cs
->hw
.avm
.isac
, ISAC_MASK
, 0xFF);
191 writereg(cs
->hw
.avm
.isac
, ISAC_MASK
, 0x0);
196 release_ioregs(struct IsdnCardState
*cs
, int mask
)
198 release_region(cs
->hw
.avm
.cfg_reg
, 8);
200 release_region(cs
->hw
.avm
.isac
+ 32, 32);
202 release_region(cs
->hw
.avm
.isacfifo
, 1);
204 release_region(cs
->hw
.avm
.hscx
[0] + 32, 32);
206 release_region(cs
->hw
.avm
.hscxfifo
[0], 1);
208 release_region(cs
->hw
.avm
.hscx
[1] + 32, 32);
210 release_region(cs
->hw
.avm
.hscxfifo
[1], 1);
214 AVM_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
220 release_ioregs(cs
, 0x3f);
223 return(request_irq(cs
->irq
, &avm_a1_interrupt
,
224 I4L_IRQ_FLAG
, "HiSax", cs
));
227 byteout(cs
->hw
.avm
.cfg_reg
, 0x16);
228 byteout(cs
->hw
.avm
.cfg_reg
, 0x1E);
238 setup_avm_a1(struct IsdnCard
*card
)
241 struct IsdnCardState
*cs
= card
->cs
;
245 strcpy(tmp
, avm_revision
);
246 printk(KERN_INFO
"HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp
));
247 if (cs
->typ
!= ISDN_CTYPE_A1
)
250 cs
->hw
.avm
.cfg_reg
= card
->para
[1] + 0x1800;
251 cs
->hw
.avm
.isac
= card
->para
[1] + 0x1400 - 0x20;
252 cs
->hw
.avm
.hscx
[0] = card
->para
[1] + 0x400 - 0x20;
253 cs
->hw
.avm
.hscx
[1] = card
->para
[1] + 0xc00 - 0x20;
254 cs
->hw
.avm
.isacfifo
= card
->para
[1] + 0x1000;
255 cs
->hw
.avm
.hscxfifo
[0] = card
->para
[1];
256 cs
->hw
.avm
.hscxfifo
[1] = card
->para
[1] + 0x800;
257 cs
->irq
= card
->para
[0];
258 if (check_region((cs
->hw
.avm
.cfg_reg
), 8)) {
260 "HiSax: %s config port %x-%x already in use\n",
263 cs
->hw
.avm
.cfg_reg
+ 8);
266 request_region(cs
->hw
.avm
.cfg_reg
, 8, "avm cfg");
268 if (check_region((cs
->hw
.avm
.isac
+ 32), 32)) {
270 "HiSax: %s isac ports %x-%x already in use\n",
272 cs
->hw
.avm
.isac
+ 32,
273 cs
->hw
.avm
.isac
+ 64);
274 release_ioregs(cs
, 0);
277 request_region(cs
->hw
.avm
.isac
+ 32, 32, "HiSax isac");
279 if (check_region((cs
->hw
.avm
.isacfifo
), 1)) {
281 "HiSax: %s isac fifo port %x already in use\n",
283 cs
->hw
.avm
.isacfifo
);
284 release_ioregs(cs
, 1);
287 request_region(cs
->hw
.avm
.isacfifo
, 1, "HiSax isac fifo");
289 if (check_region((cs
->hw
.avm
.hscx
[0]) + 32, 32)) {
291 "HiSax: %s hscx A ports %x-%x already in use\n",
293 cs
->hw
.avm
.hscx
[0] + 32,
294 cs
->hw
.avm
.hscx
[0] + 64);
295 release_ioregs(cs
, 3);
298 request_region(cs
->hw
.avm
.hscx
[0] + 32, 32, "HiSax hscx A");
300 if (check_region(cs
->hw
.avm
.hscxfifo
[0], 1)) {
302 "HiSax: %s hscx A fifo port %x already in use\n",
304 cs
->hw
.avm
.hscxfifo
[0]);
305 release_ioregs(cs
, 7);
308 request_region(cs
->hw
.avm
.hscxfifo
[0], 1, "HiSax hscx A fifo");
310 if (check_region(cs
->hw
.avm
.hscx
[1] + 32, 32)) {
312 "HiSax: %s hscx B ports %x-%x already in use\n",
314 cs
->hw
.avm
.hscx
[1] + 32,
315 cs
->hw
.avm
.hscx
[1] + 64);
316 release_ioregs(cs
, 0xf);
319 request_region(cs
->hw
.avm
.hscx
[1] + 32, 32, "HiSax hscx B");
321 if (check_region(cs
->hw
.avm
.hscxfifo
[1], 1)) {
323 "HiSax: %s hscx B fifo port %x already in use\n",
325 cs
->hw
.avm
.hscxfifo
[1]);
326 release_ioregs(cs
, 0x1f);
329 request_region(cs
->hw
.avm
.hscxfifo
[1], 1, "HiSax hscx B fifo");
332 byteout(cs
->hw
.avm
.cfg_reg
, 0x0);
335 byteout(cs
->hw
.avm
.cfg_reg
, 0x1);
337 byteout(cs
->hw
.avm
.cfg_reg
, 0x0);
342 byteout(cs
->hw
.avm
.cfg_reg
+ 1, val
);
344 byteout(cs
->hw
.avm
.cfg_reg
, 0x0);
346 restore_flags(flags
);
348 val
= bytein(cs
->hw
.avm
.cfg_reg
);
349 printk(KERN_INFO
"AVM A1: Byte at %x is %x\n",
350 cs
->hw
.avm
.cfg_reg
, val
);
351 val
= bytein(cs
->hw
.avm
.cfg_reg
+ 3);
352 printk(KERN_INFO
"AVM A1: Byte at %x is %x\n",
353 cs
->hw
.avm
.cfg_reg
+ 3, val
);
354 val
= bytein(cs
->hw
.avm
.cfg_reg
+ 2);
355 printk(KERN_INFO
"AVM A1: Byte at %x is %x\n",
356 cs
->hw
.avm
.cfg_reg
+ 2, val
);
357 val
= bytein(cs
->hw
.avm
.cfg_reg
);
358 printk(KERN_INFO
"AVM A1: Byte at %x is %x\n",
359 cs
->hw
.avm
.cfg_reg
, val
);
362 "HiSax: %s config irq:%d cfg:0x%X\n",
363 CardType
[cs
->typ
], cs
->irq
,
366 "HiSax: isac:0x%X/0x%X\n",
367 cs
->hw
.avm
.isac
+ 32, cs
->hw
.avm
.isacfifo
);
369 "HiSax: hscx A:0x%X/0x%X hscx B:0x%X/0x%X\n",
370 cs
->hw
.avm
.hscx
[0] + 32, cs
->hw
.avm
.hscxfifo
[0],
371 cs
->hw
.avm
.hscx
[1] + 32, cs
->hw
.avm
.hscxfifo
[1]);
373 cs
->readisac
= &ReadISAC
;
374 cs
->writeisac
= &WriteISAC
;
375 cs
->readisacfifo
= &ReadISACfifo
;
376 cs
->writeisacfifo
= &WriteISACfifo
;
377 cs
->BC_Read_Reg
= &ReadHSCX
;
378 cs
->BC_Write_Reg
= &WriteHSCX
;
379 cs
->BC_Send_Data
= &hscx_fill_fifo
;
380 cs
->cardmsg
= &AVM_card_msg
;
381 ISACVersion(cs
, "AVM A1:");
382 if (HscxVersion(cs
, "AVM A1:")) {
384 "AVM A1: wrong HSCX versions check IO address\n");
385 release_ioregs(cs
, 0x3f);