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 extern const char *CardType
[];
21 static const char *mic_revision
= "$Revision: 1.12.2.4 $";
23 #define byteout(addr,val) outb(val,addr)
24 #define bytein(addr) inb(addr)
30 /* CARD_ADR (Write) */
31 #define MIC_RESET 0x3 /* same as DOS driver */
34 readreg(unsigned int ale
, unsigned int adr
, u_char off
)
44 readfifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
* data
, int size
)
47 insb(adr
, data
, size
);
52 writereg(unsigned int ale
, unsigned int adr
, u_char off
, u_char data
)
59 writefifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
* data
, int size
)
62 outsb(adr
, data
, size
);
65 /* Interface functions */
68 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
70 return (readreg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, offset
));
74 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
76 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, offset
, value
);
80 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
82 readfifo(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, 0, data
, size
);
86 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
88 writefifo(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, 0, data
, size
);
92 ReadHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
)
94 return (readreg(cs
->hw
.mic
.adr
,
95 cs
->hw
.mic
.hscx
, offset
+ (hscx
? 0x40 : 0)));
99 WriteHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
, u_char value
)
101 writereg(cs
->hw
.mic
.adr
,
102 cs
->hw
.mic
.hscx
, offset
+ (hscx
? 0x40 : 0), value
);
106 * fast interrupt HSCX stuff goes here
109 #define READHSCX(cs, nr, reg) readreg(cs->hw.mic.adr, \
110 cs->hw.mic.hscx, reg + (nr ? 0x40 : 0))
111 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.mic.adr, \
112 cs->hw.mic.hscx, reg + (nr ? 0x40 : 0), data)
114 #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.mic.adr, \
115 cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt)
117 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.mic.adr, \
118 cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt)
120 #include "hscx_irq.c"
123 mic_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
125 struct IsdnCardState
*cs
= dev_id
;
129 spin_lock_irqsave(&cs
->lock
, flags
);
130 val
= readreg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_ISTA
+ 0x40);
133 hscx_int_main(cs
, val
);
134 val
= readreg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, ISAC_ISTA
);
137 isac_interrupt(cs
, val
);
138 val
= readreg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_ISTA
+ 0x40);
140 if (cs
->debug
& L1_DEB_HSCX
)
141 debugl1(cs
, "HSCX IntStat after IntRoutine");
144 val
= readreg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, ISAC_ISTA
);
146 if (cs
->debug
& L1_DEB_ISAC
)
147 debugl1(cs
, "ISAC IntStat after IntRoutine");
150 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_MASK
, 0xFF);
151 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_MASK
+ 0x40, 0xFF);
152 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, ISAC_MASK
, 0xFF);
153 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.isac
, ISAC_MASK
, 0x0);
154 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_MASK
, 0x0);
155 writereg(cs
->hw
.mic
.adr
, cs
->hw
.mic
.hscx
, HSCX_MASK
+ 0x40, 0x0);
156 spin_unlock_irqrestore(&cs
->lock
, flags
);
161 release_io_mic(struct IsdnCardState
*cs
)
165 if (cs
->hw
.mic
.cfg_reg
)
166 release_region(cs
->hw
.mic
.cfg_reg
, bytecnt
);
170 mic_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
181 spin_lock_irqsave(&cs
->lock
, flags
);
182 inithscx(cs
); /* /RTSA := ISAC RST */
184 spin_unlock_irqrestore(&cs
->lock
, flags
);
193 setup_mic(struct IsdnCard
*card
)
196 struct IsdnCardState
*cs
= card
->cs
;
199 strcpy(tmp
, mic_revision
);
200 printk(KERN_INFO
"HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp
));
201 if (cs
->typ
!= ISDN_CTYPE_MIC
)
205 cs
->hw
.mic
.cfg_reg
= card
->para
[1];
206 cs
->irq
= card
->para
[0];
207 cs
->hw
.mic
.adr
= cs
->hw
.mic
.cfg_reg
+ MIC_ADR
;
208 cs
->hw
.mic
.isac
= cs
->hw
.mic
.cfg_reg
+ MIC_ISAC
;
209 cs
->hw
.mic
.hscx
= cs
->hw
.mic
.cfg_reg
+ MIC_HSCX
;
211 if (!request_region(cs
->hw
.mic
.cfg_reg
, bytecnt
, "mic isdn")) {
213 "HiSax: %s config port %x-%x already in use\n",
216 cs
->hw
.mic
.cfg_reg
+ bytecnt
);
219 printk(KERN_INFO
"mic: defined at 0x%x IRQ %d\n",
220 cs
->hw
.mic
.cfg_reg
, cs
->irq
);
222 cs
->readisac
= &ReadISAC
;
223 cs
->writeisac
= &WriteISAC
;
224 cs
->readisacfifo
= &ReadISACfifo
;
225 cs
->writeisacfifo
= &WriteISACfifo
;
226 cs
->BC_Read_Reg
= &ReadHSCX
;
227 cs
->BC_Write_Reg
= &WriteHSCX
;
228 cs
->BC_Send_Data
= &hscx_fill_fifo
;
229 cs
->cardmsg
= &mic_card_msg
;
230 cs
->irq_func
= &mic_interrupt
;
231 ISACVersion(cs
, "mic:");
232 if (HscxVersion(cs
, "mic:")) {
234 "mic: wrong HSCX versions check IO address\n");