1 /* $Id: asuscom.c,v 1.11 2000/11/24 17:05:37 kai Exp $
3 * asuscom.c low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
5 * Author Karsten Keil (keil@isdn4linux.de)
7 * Thanks to ASUSCOM NETWORK INC. Taiwan and Dynalink NL for informations
9 * This file is (c) under GNU PUBLIC LICENSE
13 #define __NO_VERSION__
14 #include <linux/init.h>
21 extern const char *CardType
[];
23 const char *Asuscom_revision
= "$Revision: 1.11 $";
25 #define byteout(addr,val) outb(val,addr)
26 #define bytein(addr) inb(addr)
31 #define ASUS_CTRL_U7 3
32 #define ASUS_CTRL_POTS 5
34 #define ASUS_IPAC_ALE 0
35 #define ASUS_IPAC_DATA 1
37 #define ASUS_ISACHSCX 1
40 /* CARD_ADR (Write) */
41 #define ASUS_RESET 0x80 /* Bit 7 Reset-Leitung */
44 readreg(unsigned int ale
, unsigned int adr
, u_char off
)
58 readfifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
* data
, int size
)
60 /* fifo read without cli because it's allready done */
63 insb(adr
, data
, size
);
68 writereg(unsigned int ale
, unsigned int adr
, u_char off
, u_char data
)
80 writefifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
* data
, int size
)
82 /* fifo write without cli because it's allready done */
84 outsb(adr
, data
, size
);
87 /* Interface functions */
90 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
92 return (readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, offset
));
96 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
98 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, offset
, value
);
102 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
104 readfifo(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, 0, data
, size
);
108 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
110 writefifo(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, 0, data
, size
);
114 ReadISAC_IPAC(struct IsdnCardState
*cs
, u_char offset
)
116 return (readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, offset
|0x80));
120 WriteISAC_IPAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
122 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, offset
|0x80, value
);
126 ReadISACfifo_IPAC(struct IsdnCardState
*cs
, u_char
* data
, int size
)
128 readfifo(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, 0x80, data
, size
);
132 WriteISACfifo_IPAC(struct IsdnCardState
*cs
, u_char
* data
, int size
)
134 writefifo(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, 0x80, data
, size
);
138 ReadHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
)
140 return (readreg(cs
->hw
.asus
.adr
,
141 cs
->hw
.asus
.hscx
, offset
+ (hscx
? 0x40 : 0)));
145 WriteHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
, u_char value
)
147 writereg(cs
->hw
.asus
.adr
,
148 cs
->hw
.asus
.hscx
, offset
+ (hscx
? 0x40 : 0), value
);
152 * fast interrupt HSCX stuff goes here
155 #define READHSCX(cs, nr, reg) readreg(cs->hw.asus.adr, \
156 cs->hw.asus.hscx, reg + (nr ? 0x40 : 0))
157 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.asus.adr, \
158 cs->hw.asus.hscx, reg + (nr ? 0x40 : 0), data)
160 #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.asus.adr, \
161 cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt)
163 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.asus.adr, \
164 cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt)
166 #include "hscx_irq.c"
169 asuscom_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
171 struct IsdnCardState
*cs
= dev_id
;
175 printk(KERN_WARNING
"ISDNLink: Spurious interrupt!\n");
178 val
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_ISTA
+ 0x40);
181 hscx_int_main(cs
, val
);
182 val
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, ISAC_ISTA
);
185 isac_interrupt(cs
, val
);
186 val
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_ISTA
+ 0x40);
188 if (cs
->debug
& L1_DEB_HSCX
)
189 debugl1(cs
, "HSCX IntStat after IntRoutine");
192 val
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, ISAC_ISTA
);
194 if (cs
->debug
& L1_DEB_ISAC
)
195 debugl1(cs
, "ISAC IntStat after IntRoutine");
198 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_MASK
, 0xFF);
199 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_MASK
+ 0x40, 0xFF);
200 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, ISAC_MASK
, 0xFF);
201 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, ISAC_MASK
, 0x0);
202 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_MASK
, 0x0);
203 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_MASK
+ 0x40, 0x0);
207 asuscom_interrupt_ipac(int intno
, void *dev_id
, struct pt_regs
*regs
)
209 struct IsdnCardState
*cs
= dev_id
;
210 u_char ista
, val
, icnt
= 5;
213 printk(KERN_WARNING
"ISDNLink: Spurious interrupt!\n");
216 ista
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_ISTA
);
218 if (cs
->debug
& L1_DEB_IPAC
)
219 debugl1(cs
, "IPAC ISTA %02X", ista
);
221 val
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_ISTA
+ 0x40);
229 hscx_int_main(cs
, val
);
232 val
= 0xfe & readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, ISAC_ISTA
| 0x80);
234 isac_interrupt(cs
, val
);
239 isac_interrupt(cs
, val
);
241 ista
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_ISTA
);
242 if ((ista
& 0x3f) && icnt
) {
247 printk(KERN_WARNING
"ASUS IRQ LOOP\n");
248 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_MASK
, 0xFF);
249 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_MASK
, 0xC0);
253 release_io_asuscom(struct IsdnCardState
*cs
)
257 if (cs
->hw
.asus
.cfg_reg
)
258 release_region(cs
->hw
.asus
.cfg_reg
, bytecnt
);
262 reset_asuscom(struct IsdnCardState
*cs
)
266 if (cs
->subtyp
== ASUS_IPAC
)
267 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_POTA2
, 0x20);
269 byteout(cs
->hw
.asus
.adr
, ASUS_RESET
); /* Reset On */
272 set_current_state(TASK_UNINTERRUPTIBLE
);
273 schedule_timeout((10*HZ
)/1000);
274 if (cs
->subtyp
== ASUS_IPAC
)
275 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_POTA2
, 0x0);
277 byteout(cs
->hw
.asus
.adr
, 0); /* Reset Off */
278 set_current_state(TASK_UNINTERRUPTIBLE
);
279 schedule_timeout((10*HZ
)/1000);
280 if (cs
->subtyp
== ASUS_IPAC
) {
281 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_CONF
, 0x0);
282 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_ACFG
, 0xff);
283 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_AOE
, 0x0);
284 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_MASK
, 0xc0);
285 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_PCFG
, 0x12);
287 restore_flags(flags
);
291 Asus_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
298 release_io_asuscom(cs
);
301 cs
->debug
|= L1_DEB_IPAC
;
311 setup_asuscom(struct IsdnCard
*card
)
314 struct IsdnCardState
*cs
= card
->cs
;
318 strcpy(tmp
, Asuscom_revision
);
319 printk(KERN_INFO
"HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp
));
320 if (cs
->typ
!= ISDN_CTYPE_ASUSCOM
)
324 cs
->hw
.asus
.cfg_reg
= card
->para
[1];
325 cs
->irq
= card
->para
[0];
326 if (check_region((cs
->hw
.asus
.cfg_reg
), bytecnt
)) {
328 "HiSax: %s config port %x-%x already in use\n",
331 cs
->hw
.asus
.cfg_reg
+ bytecnt
);
334 request_region(cs
->hw
.asus
.cfg_reg
, bytecnt
, "asuscom isdn");
336 printk(KERN_INFO
"ISDNLink: defined at 0x%x IRQ %d\n",
337 cs
->hw
.asus
.cfg_reg
, cs
->irq
);
338 cs
->BC_Read_Reg
= &ReadHSCX
;
339 cs
->BC_Write_Reg
= &WriteHSCX
;
340 cs
->BC_Send_Data
= &hscx_fill_fifo
;
341 cs
->cardmsg
= &Asus_card_msg
;
342 val
= readreg(cs
->hw
.asus
.cfg_reg
+ ASUS_IPAC_ALE
,
343 cs
->hw
.asus
.cfg_reg
+ ASUS_IPAC_DATA
, IPAC_ID
);
345 cs
->subtyp
= ASUS_IPAC
;
346 cs
->hw
.asus
.adr
= cs
->hw
.asus
.cfg_reg
+ ASUS_IPAC_ALE
;
347 cs
->hw
.asus
.isac
= cs
->hw
.asus
.cfg_reg
+ ASUS_IPAC_DATA
;
348 cs
->hw
.asus
.hscx
= cs
->hw
.asus
.cfg_reg
+ ASUS_IPAC_DATA
;
349 test_and_set_bit(HW_IPAC
, &cs
->HW_Flags
);
350 cs
->readisac
= &ReadISAC_IPAC
;
351 cs
->writeisac
= &WriteISAC_IPAC
;
352 cs
->readisacfifo
= &ReadISACfifo_IPAC
;
353 cs
->writeisacfifo
= &WriteISACfifo_IPAC
;
354 cs
->irq_func
= &asuscom_interrupt_ipac
;
355 printk(KERN_INFO
"Asus: IPAC version %x\n", val
);
357 cs
->subtyp
= ASUS_ISACHSCX
;
358 cs
->hw
.asus
.adr
= cs
->hw
.asus
.cfg_reg
+ ASUS_ADR
;
359 cs
->hw
.asus
.isac
= cs
->hw
.asus
.cfg_reg
+ ASUS_ISAC
;
360 cs
->hw
.asus
.hscx
= cs
->hw
.asus
.cfg_reg
+ ASUS_HSCX
;
361 cs
->hw
.asus
.u7
= cs
->hw
.asus
.cfg_reg
+ ASUS_CTRL_U7
;
362 cs
->hw
.asus
.pots
= cs
->hw
.asus
.cfg_reg
+ ASUS_CTRL_POTS
;
363 cs
->readisac
= &ReadISAC
;
364 cs
->writeisac
= &WriteISAC
;
365 cs
->readisacfifo
= &ReadISACfifo
;
366 cs
->writeisacfifo
= &WriteISACfifo
;
367 cs
->irq_func
= &asuscom_interrupt
;
368 ISACVersion(cs
, "ISDNLink:");
369 if (HscxVersion(cs
, "ISDNLink:")) {
371 "ISDNLink: wrong HSCX versions check IO address\n");
372 release_io_asuscom(cs
);
376 printk(KERN_INFO
"ISDNLink: resetting card\n");