1 /* $Id: asuscom.c,v 1.5 1998/11/15 23:54:19 keil 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
11 * Revision 1.5 1998/11/15 23:54:19 keil
14 * Revision 1.4 1998/06/18 23:18:20 keil
15 * Support for new IPAC card
17 * Revision 1.3 1998/04/15 16:46:53 keil
20 * Revision 1.2 1998/02/02 13:27:06 keil
26 #define __NO_VERSION__
33 extern const char *CardType
[];
35 const char *Asuscom_revision
= "$Revision: 1.5 $";
37 #define byteout(addr,val) outb(val,addr)
38 #define bytein(addr) inb(addr)
43 #define ASUS_CTRL_U7 3
44 #define ASUS_CTRL_POTS 5
46 #define ASUS_IPAC_ALE 0
47 #define ASUS_IPAC_DATA 1
49 #define ASUS_ISACHSCX 1
52 /* CARD_ADR (Write) */
53 #define ASUS_RESET 0x80 /* Bit 7 Reset-Leitung */
56 readreg(unsigned int ale
, unsigned int adr
, u_char off
)
70 readfifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
* data
, int size
)
72 /* fifo read without cli because it's allready done */
75 insb(adr
, data
, size
);
80 writereg(unsigned int ale
, unsigned int adr
, u_char off
, u_char data
)
92 writefifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
* data
, int size
)
94 /* fifo write without cli because it's allready done */
96 outsb(adr
, data
, size
);
99 /* Interface functions */
102 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
104 return (readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, offset
));
108 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
110 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, offset
, value
);
114 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
116 readfifo(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, 0, data
, size
);
120 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
122 writefifo(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, 0, data
, size
);
126 ReadISAC_IPAC(struct IsdnCardState
*cs
, u_char offset
)
128 return (readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, offset
|0x80));
132 WriteISAC_IPAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
134 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, offset
|0x80, value
);
138 ReadISACfifo_IPAC(struct IsdnCardState
*cs
, u_char
* data
, int size
)
140 readfifo(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, 0x80, data
, size
);
144 WriteISACfifo_IPAC(struct IsdnCardState
*cs
, u_char
* data
, int size
)
146 writefifo(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, 0x80, data
, size
);
150 ReadHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
)
152 return (readreg(cs
->hw
.asus
.adr
,
153 cs
->hw
.asus
.hscx
, offset
+ (hscx
? 0x40 : 0)));
157 WriteHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
, u_char value
)
159 writereg(cs
->hw
.asus
.adr
,
160 cs
->hw
.asus
.hscx
, offset
+ (hscx
? 0x40 : 0), value
);
164 * fast interrupt HSCX stuff goes here
167 #define READHSCX(cs, nr, reg) readreg(cs->hw.asus.adr, \
168 cs->hw.asus.hscx, reg + (nr ? 0x40 : 0))
169 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.asus.adr, \
170 cs->hw.asus.hscx, reg + (nr ? 0x40 : 0), data)
172 #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.asus.adr, \
173 cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt)
175 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.asus.adr, \
176 cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt)
178 #include "hscx_irq.c"
181 asuscom_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
183 struct IsdnCardState
*cs
= dev_id
;
184 u_char val
, stat
= 0;
187 printk(KERN_WARNING
"ISDNLink: Spurious interrupt!\n");
190 val
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_ISTA
+ 0x40);
193 hscx_int_main(cs
, val
);
196 val
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, ISAC_ISTA
);
199 isac_interrupt(cs
, val
);
202 val
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_ISTA
+ 0x40);
204 if (cs
->debug
& L1_DEB_HSCX
)
205 debugl1(cs
, "HSCX IntStat after IntRoutine");
208 val
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, ISAC_ISTA
);
210 if (cs
->debug
& L1_DEB_ISAC
)
211 debugl1(cs
, "ISAC IntStat after IntRoutine");
215 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_MASK
, 0xFF);
216 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_MASK
+ 0x40, 0xFF);
217 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_MASK
, 0x0);
218 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_MASK
+ 0x40, 0x0);
221 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, ISAC_MASK
, 0xFF);
222 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, ISAC_MASK
, 0x0);
227 asuscom_interrupt_ipac(int intno
, void *dev_id
, struct pt_regs
*regs
)
229 struct IsdnCardState
*cs
= dev_id
;
230 u_char ista
, val
, icnt
= 20;
233 printk(KERN_WARNING
"ISDNLink: Spurious interrupt!\n");
236 ista
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_ISTA
);
238 if (cs
->debug
& L1_DEB_IPAC
)
239 debugl1(cs
, "IPAC ISTA %02X", ista
);
241 val
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.hscx
, HSCX_ISTA
+ 0x40);
249 hscx_int_main(cs
, val
);
252 val
= 0xfe & readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, ISAC_ISTA
| 0x80);
254 isac_interrupt(cs
, val
);
259 isac_interrupt(cs
, val
);
261 ista
= readreg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_ISTA
);
262 if ((ista
& 0x3f) && icnt
) {
267 printk(KERN_WARNING
"ASUS IRQ LOOP\n");
268 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_MASK
, 0xFF);
269 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_MASK
, 0xC0);
273 release_io_asuscom(struct IsdnCardState
*cs
)
277 if (cs
->hw
.asus
.cfg_reg
)
278 release_region(cs
->hw
.asus
.cfg_reg
, bytecnt
);
282 reset_asuscom(struct IsdnCardState
*cs
)
286 if (cs
->subtyp
== ASUS_IPAC
)
287 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_POTA2
, 0x20);
289 byteout(cs
->hw
.asus
.adr
, ASUS_RESET
); /* Reset On */
292 current
->state
= TASK_INTERRUPTIBLE
;
294 if (cs
->subtyp
== ASUS_IPAC
)
295 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_POTA2
, 0x0);
297 byteout(cs
->hw
.asus
.adr
, 0); /* Reset Off */
298 current
->state
= TASK_INTERRUPTIBLE
;
300 if (cs
->subtyp
== ASUS_IPAC
) {
301 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_CONF
, 0x0);
302 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_ACFG
, 0xff);
303 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_AOE
, 0x0);
304 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_MASK
, 0xc0);
305 writereg(cs
->hw
.asus
.adr
, cs
->hw
.asus
.isac
, IPAC_PCFG
, 0x12);
307 restore_flags(flags
);
311 Asus_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
318 release_io_asuscom(cs
);
321 if (cs
->subtyp
== ASUS_IPAC
)
322 return(request_irq(cs
->irq
, &asuscom_interrupt_ipac
,
323 I4L_IRQ_FLAG
, "HiSax", cs
));
325 return(request_irq(cs
->irq
, &asuscom_interrupt
,
326 I4L_IRQ_FLAG
, "HiSax", cs
));
328 cs
->debug
|= L1_DEB_IPAC
;
338 setup_asuscom(struct IsdnCard
*card
)
341 struct IsdnCardState
*cs
= card
->cs
;
345 strcpy(tmp
, Asuscom_revision
);
346 printk(KERN_INFO
"HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp
));
347 if (cs
->typ
!= ISDN_CTYPE_ASUSCOM
)
351 cs
->hw
.asus
.cfg_reg
= card
->para
[1];
352 cs
->irq
= card
->para
[0];
353 if (check_region((cs
->hw
.asus
.cfg_reg
), bytecnt
)) {
355 "HiSax: %s config port %x-%x already in use\n",
358 cs
->hw
.asus
.cfg_reg
+ bytecnt
);
361 request_region(cs
->hw
.asus
.cfg_reg
, bytecnt
, "asuscom isdn");
363 printk(KERN_INFO
"ISDNLink: defined at 0x%x IRQ %d\n",
364 cs
->hw
.asus
.cfg_reg
, cs
->irq
);
365 cs
->BC_Read_Reg
= &ReadHSCX
;
366 cs
->BC_Write_Reg
= &WriteHSCX
;
367 cs
->BC_Send_Data
= &hscx_fill_fifo
;
368 cs
->cardmsg
= &Asus_card_msg
;
369 val
= readreg(cs
->hw
.asus
.cfg_reg
+ ASUS_IPAC_ALE
,
370 cs
->hw
.asus
.cfg_reg
+ ASUS_IPAC_DATA
, IPAC_ID
);
372 cs
->subtyp
= ASUS_IPAC
;
373 cs
->hw
.asus
.adr
= cs
->hw
.asus
.cfg_reg
+ ASUS_IPAC_ALE
;
374 cs
->hw
.asus
.isac
= cs
->hw
.asus
.cfg_reg
+ ASUS_IPAC_DATA
;
375 cs
->hw
.asus
.hscx
= cs
->hw
.asus
.cfg_reg
+ ASUS_IPAC_DATA
;
376 test_and_set_bit(HW_IPAC
, &cs
->HW_Flags
);
377 cs
->readisac
= &ReadISAC_IPAC
;
378 cs
->writeisac
= &WriteISAC_IPAC
;
379 cs
->readisacfifo
= &ReadISACfifo_IPAC
;
380 cs
->writeisacfifo
= &WriteISACfifo_IPAC
;
381 printk(KERN_INFO
"Asus: IPAC version %x\n", val
);
383 cs
->subtyp
= ASUS_ISACHSCX
;
384 cs
->hw
.asus
.adr
= cs
->hw
.asus
.cfg_reg
+ ASUS_ADR
;
385 cs
->hw
.asus
.isac
= cs
->hw
.asus
.cfg_reg
+ ASUS_ISAC
;
386 cs
->hw
.asus
.hscx
= cs
->hw
.asus
.cfg_reg
+ ASUS_HSCX
;
387 cs
->hw
.asus
.u7
= cs
->hw
.asus
.cfg_reg
+ ASUS_CTRL_U7
;
388 cs
->hw
.asus
.pots
= cs
->hw
.asus
.cfg_reg
+ ASUS_CTRL_POTS
;
389 cs
->readisac
= &ReadISAC
;
390 cs
->writeisac
= &WriteISAC
;
391 cs
->readisacfifo
= &ReadISACfifo
;
392 cs
->writeisacfifo
= &WriteISACfifo
;
393 ISACVersion(cs
, "ISDNLink:");
394 if (HscxVersion(cs
, "ISDNLink:")) {
396 "ISDNLink: wrong HSCX versions check IO address\n");
397 release_io_asuscom(cs
);
401 printk(KERN_INFO
"ISDNLink: resetting card\n");