Import 2.3.10pre5
[davej-history.git] / drivers / isdn / hisax / asuscom.c
blobeeaad83f5ddcecd2301c758c13cfc74256ac17ab
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
10 * $Log: asuscom.c,v $
11 * Revision 1.5 1998/11/15 23:54:19 keil
12 * changes from 2.0
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
18 * new init code
20 * Revision 1.2 1998/02/02 13:27:06 keil
21 * New
26 #define __NO_VERSION__
27 #include "hisax.h"
28 #include "isac.h"
29 #include "ipac.h"
30 #include "hscx.h"
31 #include "isdnl1.h"
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)
40 #define ASUS_ISAC 0
41 #define ASUS_HSCX 1
42 #define ASUS_ADR 2
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
50 #define ASUS_IPAC 2
52 /* CARD_ADR (Write) */
53 #define ASUS_RESET 0x80 /* Bit 7 Reset-Leitung */
55 static inline u_char
56 readreg(unsigned int ale, unsigned int adr, u_char off)
58 register u_char ret;
59 long flags;
61 save_flags(flags);
62 cli();
63 byteout(ale, off);
64 ret = bytein(adr);
65 restore_flags(flags);
66 return (ret);
69 static inline void
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 */
74 byteout(ale, off);
75 insb(adr, data, size);
79 static inline void
80 writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
82 long flags;
84 save_flags(flags);
85 cli();
86 byteout(ale, off);
87 byteout(adr, data);
88 restore_flags(flags);
91 static inline void
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 */
95 byteout(ale, off);
96 outsb(adr, data, size);
99 /* Interface functions */
101 static u_char
102 ReadISAC(struct IsdnCardState *cs, u_char offset)
104 return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset));
107 static void
108 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
110 writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset, value);
113 static void
114 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
116 readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size);
119 static void
120 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
122 writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size);
125 static u_char
126 ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
128 return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80));
131 static void
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);
137 static void
138 ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
140 readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
143 static void
144 WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
146 writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
149 static u_char
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)));
156 static void
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"
180 static void
181 asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs)
183 struct IsdnCardState *cs = dev_id;
184 u_char val, stat = 0;
186 if (!cs) {
187 printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
188 return;
190 val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
191 Start_HSCX:
192 if (val) {
193 hscx_int_main(cs, val);
194 stat |= 1;
196 val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA);
197 Start_ISAC:
198 if (val) {
199 isac_interrupt(cs, val);
200 stat |= 2;
202 val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
203 if (val) {
204 if (cs->debug & L1_DEB_HSCX)
205 debugl1(cs, "HSCX IntStat after IntRoutine");
206 goto Start_HSCX;
208 val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA);
209 if (val) {
210 if (cs->debug & L1_DEB_ISAC)
211 debugl1(cs, "ISAC IntStat after IntRoutine");
212 goto Start_ISAC;
214 if (stat & 1) {
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);
220 if (stat & 2) {
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);
226 static void
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;
232 if (!cs) {
233 printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
234 return;
236 ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
237 Start_IPAC:
238 if (cs->debug & L1_DEB_IPAC)
239 debugl1(cs, "IPAC ISTA %02X", ista);
240 if (ista & 0x0f) {
241 val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
242 if (ista & 0x01)
243 val |= 0x01;
244 if (ista & 0x04)
245 val |= 0x02;
246 if (ista & 0x08)
247 val |= 0x04;
248 if (val)
249 hscx_int_main(cs, val);
251 if (ista & 0x20) {
252 val = 0xfe & readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA | 0x80);
253 if (val) {
254 isac_interrupt(cs, val);
257 if (ista & 0x10) {
258 val = 0x01;
259 isac_interrupt(cs, val);
261 ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
262 if ((ista & 0x3f) && icnt) {
263 icnt--;
264 goto Start_IPAC;
266 if (!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);
272 void
273 release_io_asuscom(struct IsdnCardState *cs)
275 int bytecnt = 8;
277 if (cs->hw.asus.cfg_reg)
278 release_region(cs->hw.asus.cfg_reg, bytecnt);
281 static void
282 reset_asuscom(struct IsdnCardState *cs)
284 long flags;
286 if (cs->subtyp == ASUS_IPAC)
287 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x20);
288 else
289 byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */
290 save_flags(flags);
291 sti();
292 current->state = TASK_INTERRUPTIBLE;
293 schedule_timeout(1);
294 if (cs->subtyp == ASUS_IPAC)
295 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0);
296 else
297 byteout(cs->hw.asus.adr, 0); /* Reset Off */
298 current->state = TASK_INTERRUPTIBLE;
299 schedule_timeout(1);
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);
310 static int
311 Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
313 switch (mt) {
314 case CARD_RESET:
315 reset_asuscom(cs);
316 return(0);
317 case CARD_RELEASE:
318 release_io_asuscom(cs);
319 return(0);
320 case CARD_SETIRQ:
321 if (cs->subtyp == ASUS_IPAC)
322 return(request_irq(cs->irq, &asuscom_interrupt_ipac,
323 I4L_IRQ_FLAG, "HiSax", cs));
324 else
325 return(request_irq(cs->irq, &asuscom_interrupt,
326 I4L_IRQ_FLAG, "HiSax", cs));
327 case CARD_INIT:
328 cs->debug |= L1_DEB_IPAC;
329 inithscxisac(cs, 3);
330 return(0);
331 case CARD_TEST:
332 return(0);
334 return(0);
337 int __init
338 setup_asuscom(struct IsdnCard *card)
340 int bytecnt;
341 struct IsdnCardState *cs = card->cs;
342 u_char val;
343 char tmp[64];
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)
348 return (0);
350 bytecnt = 8;
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)) {
354 printk(KERN_WARNING
355 "HiSax: %s config port %x-%x already in use\n",
356 CardType[card->typ],
357 cs->hw.asus.cfg_reg,
358 cs->hw.asus.cfg_reg + bytecnt);
359 return (0);
360 } else {
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);
371 if (val == 1) {
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);
382 } else {
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:")) {
395 printk(KERN_WARNING
396 "ISDNLink: wrong HSCX versions check IO address\n");
397 release_io_asuscom(cs);
398 return (0);
401 printk(KERN_INFO "ISDNLink: resetting card\n");
402 reset_asuscom(cs);
403 return (1);