1 /* $Id: mic.c,v 1.12.2.4 2004/01/13 23:48:39 keil Exp $
3 * low level stuff for mic cards
5 * Author Stephan von Krawczynski
6 * Copyright by Stephan von Krawczynski <skraw@ithnet.com>
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
13 #include <linux/init.h>
19 static const char *mic_revision
= "$Revision: 1.12.2.4 $";
21 #define byteout(addr, val) outb(val, addr)
22 #define bytein(addr) inb(addr)
28 /* CARD_ADR (Write) */
29 #define MIC_RESET 0x3 /* same as DOS driver */
32 readreg(unsigned int ale
, unsigned int adr
, u_char off
)
42 readfifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
*data
, int size
)
45 insb(adr
, data
, size
);
50 writereg(unsigned int ale
, unsigned int adr
, u_char off
, u_char data
)
57 writefifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
*data
, int size
)
60 outsb(adr
, data
, size
);
63 /* Interface functions */
66 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
68 return (readreg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, offset
));
72 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
74 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, offset
, value
);
78 ReadISACfifo(struct IsdnCardState
*cs
, u_char
*data
, int size
)
80 readfifo(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, 0, data
, size
);
84 WriteISACfifo(struct IsdnCardState
*cs
, u_char
*data
, int size
)
86 writefifo(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, 0, data
, size
);
90 ReadHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
)
92 return (readreg(cs
->hw
.mic
.adr
,
93 cs
->hw
.mic
.hscx
, offset
+ (hscx
? 0x40 : 0)));
97 WriteHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
, u_char value
)
99 writereg(cs
->hw
.mic
.adr
,
100 cs
->hw
.mic
.hscx
, offset
+ (hscx
? 0x40 : 0), value
);
104 * fast interrupt HSCX stuff goes here
107 #define READHSCX(cs, nr, reg) readreg(cs->hw.mic.adr, \
108 cs->hw.mic.hscx, reg + (nr ? 0x40 : 0))
109 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.mic.adr, \
110 cs->hw.mic.hscx, reg + (nr ? 0x40 : 0), data)
112 #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.mic.adr, \
113 cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt)
115 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.mic.adr, \
116 cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt)
118 #include "hscx_irq.c"
121 mic_interrupt(int intno
, void *dev_id
)
123 struct IsdnCardState
*cs
= dev_id
;
127 spin_lock_irqsave(&cs
->lock
, flags
);
128 val
= readreg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_ISTA
+ 0x40);
131 hscx_int_main(cs
, val
);
132 val
= readreg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, ISAC_ISTA
);
135 isac_interrupt(cs
, val
);
136 val
= readreg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_ISTA
+ 0x40);
138 if (cs
->debug
& L1_DEB_HSCX
)
139 debugl1(cs
, "HSCX IntStat after IntRoutine");
142 val
= readreg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, ISAC_ISTA
);
144 if (cs
->debug
& L1_DEB_ISAC
)
145 debugl1(cs
, "ISAC IntStat after IntRoutine");
148 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_MASK
, 0xFF);
149 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_MASK
+ 0x40, 0xFF);
150 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, ISAC_MASK
, 0xFF);
151 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, ISAC_MASK
, 0x0);
152 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_MASK
, 0x0);
153 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_MASK
+ 0x40, 0x0);
154 spin_unlock_irqrestore(&cs
->lock
, flags
);
159 release_io_mic(struct IsdnCardState
*cs
)
163 if (cs
->hw
.mic
.cfg_reg
)
164 release_region(cs
->hw
.mic
.cfg_reg
, bytecnt
);
168 mic_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
179 spin_lock_irqsave(&cs
->lock
, flags
);
180 inithscx(cs
); /* /RTSA := ISAC RST */
182 spin_unlock_irqrestore(&cs
->lock
, flags
);
190 int setup_mic(struct IsdnCard
*card
)
193 struct IsdnCardState
*cs
= card
->cs
;
196 strcpy(tmp
, mic_revision
);
197 printk(KERN_INFO
"HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp
));
198 if (cs
->typ
!= ISDN_CTYPE_MIC
)
202 cs
->hw
.mic
.cfg_reg
= card
->para
[1];
203 cs
->irq
= card
->para
[0];
204 cs
->hw
.mic
.adr
= cs
->hw
.mic
.cfg_reg
+ MIC_ADR
;
205 cs
->hw
.mic
.isac
= cs
->hw
.mic
.cfg_reg
+ MIC_ISAC
;
206 cs
->hw
.mic
.hscx
= cs
->hw
.mic
.cfg_reg
+ MIC_HSCX
;
208 if (!request_region(cs
->hw
.mic
.cfg_reg
, bytecnt
, "mic isdn")) {
210 "HiSax: ith mic config port %x-%x already in use\n",
212 cs
->hw
.mic
.cfg_reg
+ bytecnt
);
215 printk(KERN_INFO
"mic: defined at 0x%x IRQ %d\n",
216 cs
->hw
.mic
.cfg_reg
, cs
->irq
);
218 cs
->readisac
= &ReadISAC
;
219 cs
->writeisac
= &WriteISAC
;
220 cs
->readisacfifo
= &ReadISACfifo
;
221 cs
->writeisacfifo
= &WriteISACfifo
;
222 cs
->BC_Read_Reg
= &ReadHSCX
;
223 cs
->BC_Write_Reg
= &WriteHSCX
;
224 cs
->BC_Send_Data
= &hscx_fill_fifo
;
225 cs
->cardmsg
= &mic_card_msg
;
226 cs
->irq_func
= &mic_interrupt
;
227 ISACVersion(cs
, "mic:");
228 if (HscxVersion(cs
, "mic:")) {
230 "mic: wrong HSCX versions check IO address\n");