Import 2.3.10pre5
[davej-history.git] / drivers / isdn / hisax / avm_a1p.c
blobc11ac41e4448f4190c136d1a2e6735851d17cf63
1 /* $Id: avm_a1p.c,v 2.3 1998/11/15 23:54:22 keil Exp $
3 * avm_a1p.c low level stuff for the following AVM cards:
4 * A1 PCMCIA
5 * FRITZ!Card PCMCIA
6 * FRITZ!Card PCMCIA 2.0
8 * Author Carsten Paeth (calle@calle.in-berlin.de)
10 * $Log: avm_a1p.c,v $
11 * Revision 2.3 1998/11/15 23:54:22 keil
12 * changes from 2.0
14 * Revision 2.2 1998/08/13 23:36:13 keil
15 * HiSax 3.1 - don't work stable with current LinkLevel
17 * Revision 2.1 1998/07/15 15:01:23 calle
18 * Support for AVM passive PCMCIA cards:
19 * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
21 * Revision 1.1.2.1 1998/07/15 14:43:26 calle
22 * Support for AVM passive PCMCIA cards:
23 * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
27 #define __NO_VERSION__
28 #include "hisax.h"
29 #include "isac.h"
30 #include "hscx.h"
31 #include "isdnl1.h"
33 /* register offsets */
34 #define ADDRREG_OFFSET 0x02
35 #define DATAREG_OFFSET 0x03
36 #define ASL0_OFFSET 0x04
37 #define ASL1_OFFSET 0x05
38 #define MODREG_OFFSET 0x06
39 #define VERREG_OFFSET 0x07
41 /* address offsets */
42 #define ISAC_FIFO_OFFSET 0x00
43 #define ISAC_REG_OFFSET 0x20
44 #define HSCX_CH_DIFF 0x40
45 #define HSCX_FIFO_OFFSET 0x80
46 #define HSCX_REG_OFFSET 0xa0
48 /* read bits ASL0 */
49 #define ASL0_R_TIMER 0x10 /* active low */
50 #define ASL0_R_ISAC 0x20 /* active low */
51 #define ASL0_R_HSCX 0x40 /* active low */
52 #define ASL0_R_TESTBIT 0x80
53 #define ASL0_R_IRQPENDING (ASL0_R_ISAC|ASL0_R_HSCX|ASL0_R_TIMER)
55 /* write bits ASL0 */
56 #define ASL0_W_RESET 0x01
57 #define ASL0_W_TDISABLE 0x02
58 #define ASL0_W_TRESET 0x04
59 #define ASL0_W_IRQENABLE 0x08
60 #define ASL0_W_TESTBIT 0x80
62 /* write bits ASL1 */
63 #define ASL1_W_LED0 0x10
64 #define ASL1_W_LED1 0x20
65 #define ASL1_W_ENABLE_S0 0xC0
67 #define byteout(addr,val) outb(val,addr)
68 #define bytein(addr) inb(addr)
70 static const char *avm_revision = "$Revision: 2.3 $";
72 static inline u_char
73 ReadISAC(struct IsdnCardState *cs, u_char offset)
75 long flags;
76 u_char ret;
78 offset -= 0x20;
79 save_flags(flags);
80 cli();
81 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
82 ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
83 restore_flags(flags);
84 return ret;
87 static inline void
88 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
90 long flags;
92 offset -= 0x20;
94 save_flags(flags);
95 cli();
96 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
97 byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
98 restore_flags(flags);
101 static inline void
102 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
104 long flags;
106 save_flags(flags);
107 cli();
108 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
109 insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
110 restore_flags(flags);
113 static inline void
114 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
116 long flags;
118 save_flags(flags);
119 cli();
120 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
121 outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
122 restore_flags(flags);
125 static inline u_char
126 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
128 u_char ret;
129 long flags;
131 offset -= 0x20;
133 save_flags(flags);
134 cli();
135 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
136 HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
137 ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
138 restore_flags(flags);
139 return ret;
142 static inline void
143 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
145 long flags;
147 offset -= 0x20;
149 save_flags(flags);
150 cli();
151 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
152 HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
153 byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
154 restore_flags(flags);
157 static inline void
158 ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
160 long flags;
162 save_flags(flags);
163 cli();
164 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
165 HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
166 insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
167 restore_flags(flags);
170 static inline void
171 WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
173 long flags;
175 save_flags(flags);
176 cli();
177 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
178 HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
179 outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
180 restore_flags(flags);
184 * fast interrupt HSCX stuff goes here
187 #define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
188 #define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
189 #define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt)
190 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
192 #include "hscx_irq.c"
194 static void
195 avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs)
197 struct IsdnCardState *cs = dev_id;
198 u_char val, sval, stat = 0;
200 if (!cs) {
201 printk(KERN_WARNING "AVM A1 PCMCIA: Spurious interrupt!\n");
202 return;
204 while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) {
205 if (cs->debug & L1_DEB_INTSTAT)
206 debugl1(cs, "avm IntStatus %x", sval);
207 if (sval & ASL0_R_HSCX) {
208 val = ReadHSCX(cs, 1, HSCX_ISTA);
209 if (val) {
210 hscx_int_main(cs, val);
211 stat |= 1;
214 if (sval & ASL0_R_ISAC) {
215 val = ReadISAC(cs, ISAC_ISTA);
216 if (val) {
217 isac_interrupt(cs, val);
218 stat |= 2;
222 if (stat & 1) {
223 WriteHSCX(cs, 0, HSCX_MASK, 0xff);
224 WriteHSCX(cs, 1, HSCX_MASK, 0xff);
225 WriteHSCX(cs, 0, HSCX_MASK, 0x00);
226 WriteHSCX(cs, 1, HSCX_MASK, 0x00);
228 if (stat & 2) {
229 WriteISAC(cs, ISAC_MASK, 0xff);
230 WriteISAC(cs, ISAC_MASK, 0x00);
234 static int
235 AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
237 int ret;
238 switch (mt) {
239 case CARD_RESET:
240 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
241 HZDELAY(HZ / 5 + 1);
242 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
243 HZDELAY(HZ / 5 + 1);
244 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
245 return 0;
247 case CARD_RELEASE:
248 /* free_irq is done in HiSax_closecard(). */
249 /* free_irq(cs->irq, cs); */
250 return 0;
252 case CARD_SETIRQ:
253 ret = request_irq(cs->irq, &avm_a1p_interrupt,
254 I4L_IRQ_FLAG, "HiSax", cs);
255 if (ret)
256 return ret;
257 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,
258 ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
259 return 0;
261 case CARD_INIT:
262 clear_pending_isac_ints(cs);
263 clear_pending_hscx_ints(cs);
264 inithscxisac(cs, 1);
265 inithscxisac(cs, 2);
266 return 0;
268 case CARD_TEST:
269 /* we really don't need it for the PCMCIA Version */
270 return 0;
272 default:
273 /* all card drivers ignore others, so we do the same */
274 return 0;
276 return 0;
279 __initfunc(int
280 setup_avm_a1_pcmcia(struct IsdnCard *card))
282 u_char model, vers;
283 struct IsdnCardState *cs = card->cs;
284 long flags;
285 char tmp[64];
288 strcpy(tmp, avm_revision);
289 printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
290 HiSax_getrev(tmp));
291 if (cs->typ != ISDN_CTYPE_A1_PCMCIA)
292 return (0);
294 cs->hw.avm.cfg_reg = card->para[1];
295 cs->irq = card->para[0];
298 save_flags(flags);
299 outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
300 sti();
302 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
303 HZDELAY(HZ / 5 + 1);
304 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
305 HZDELAY(HZ / 5 + 1);
306 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
308 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET, ASL0_W_TDISABLE|ASL0_W_TRESET);
310 restore_flags(flags);
312 model = bytein(cs->hw.avm.cfg_reg+MODREG_OFFSET);
313 vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
315 printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
316 cs->hw.avm.cfg_reg, cs->irq, model, vers);
318 cs->readisac = &ReadISAC;
319 cs->writeisac = &WriteISAC;
320 cs->readisacfifo = &ReadISACfifo;
321 cs->writeisacfifo = &WriteISACfifo;
322 cs->BC_Read_Reg = &ReadHSCX;
323 cs->BC_Write_Reg = &WriteHSCX;
324 cs->BC_Send_Data = &hscx_fill_fifo;
325 cs->cardmsg = &AVM_card_msg;
327 ISACVersion(cs, "AVM A1 PCMCIA:");
328 if (HscxVersion(cs, "AVM A1 PCMCIA:")) {
329 printk(KERN_WARNING
330 "AVM A1 PCMCIA: wrong HSCX versions check IO address\n");
331 return (0);
333 return (1);