Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / isdn / hisax / asuscom.c
blob01b668d8ef307e909f6d42f66ce743299d95bdc2
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>
15 #include "hisax.h"
16 #include "isac.h"
17 #include "ipac.h"
18 #include "hscx.h"
19 #include "isdnl1.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)
28 #define ASUS_ISAC 0
29 #define ASUS_HSCX 1
30 #define ASUS_ADR 2
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
38 #define ASUS_IPAC 2
40 /* CARD_ADR (Write) */
41 #define ASUS_RESET 0x80 /* Bit 7 Reset-Leitung */
43 static inline u_char
44 readreg(unsigned int ale, unsigned int adr, u_char off)
46 register u_char ret;
47 long flags;
49 save_flags(flags);
50 cli();
51 byteout(ale, off);
52 ret = bytein(adr);
53 restore_flags(flags);
54 return (ret);
57 static inline void
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 */
62 byteout(ale, off);
63 insb(adr, data, size);
67 static inline void
68 writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
70 long flags;
72 save_flags(flags);
73 cli();
74 byteout(ale, off);
75 byteout(adr, data);
76 restore_flags(flags);
79 static inline void
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 */
83 byteout(ale, off);
84 outsb(adr, data, size);
87 /* Interface functions */
89 static u_char
90 ReadISAC(struct IsdnCardState *cs, u_char offset)
92 return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset));
95 static void
96 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
98 writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset, value);
101 static void
102 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
104 readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size);
107 static void
108 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
110 writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size);
113 static u_char
114 ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
116 return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80));
119 static void
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);
125 static void
126 ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
128 readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
131 static void
132 WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
134 writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
137 static u_char
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)));
144 static void
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"
168 static void
169 asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs)
171 struct IsdnCardState *cs = dev_id;
172 u_char val;
174 if (!cs) {
175 printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
176 return;
178 val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
179 Start_HSCX:
180 if (val)
181 hscx_int_main(cs, val);
182 val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA);
183 Start_ISAC:
184 if (val)
185 isac_interrupt(cs, val);
186 val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
187 if (val) {
188 if (cs->debug & L1_DEB_HSCX)
189 debugl1(cs, "HSCX IntStat after IntRoutine");
190 goto Start_HSCX;
192 val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA);
193 if (val) {
194 if (cs->debug & L1_DEB_ISAC)
195 debugl1(cs, "ISAC IntStat after IntRoutine");
196 goto Start_ISAC;
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);
206 static void
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;
212 if (!cs) {
213 printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
214 return;
216 ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
217 Start_IPAC:
218 if (cs->debug & L1_DEB_IPAC)
219 debugl1(cs, "IPAC ISTA %02X", ista);
220 if (ista & 0x0f) {
221 val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
222 if (ista & 0x01)
223 val |= 0x01;
224 if (ista & 0x04)
225 val |= 0x02;
226 if (ista & 0x08)
227 val |= 0x04;
228 if (val)
229 hscx_int_main(cs, val);
231 if (ista & 0x20) {
232 val = 0xfe & readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA | 0x80);
233 if (val) {
234 isac_interrupt(cs, val);
237 if (ista & 0x10) {
238 val = 0x01;
239 isac_interrupt(cs, val);
241 ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
242 if ((ista & 0x3f) && icnt) {
243 icnt--;
244 goto Start_IPAC;
246 if (!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);
252 void
253 release_io_asuscom(struct IsdnCardState *cs)
255 int bytecnt = 8;
257 if (cs->hw.asus.cfg_reg)
258 release_region(cs->hw.asus.cfg_reg, bytecnt);
261 static void
262 reset_asuscom(struct IsdnCardState *cs)
264 long flags;
266 if (cs->subtyp == ASUS_IPAC)
267 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x20);
268 else
269 byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */
270 save_flags(flags);
271 sti();
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);
276 else
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);
290 static int
291 Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
293 switch (mt) {
294 case CARD_RESET:
295 reset_asuscom(cs);
296 return(0);
297 case CARD_RELEASE:
298 release_io_asuscom(cs);
299 return(0);
300 case CARD_INIT:
301 cs->debug |= L1_DEB_IPAC;
302 inithscxisac(cs, 3);
303 return(0);
304 case CARD_TEST:
305 return(0);
307 return(0);
310 int __init
311 setup_asuscom(struct IsdnCard *card)
313 int bytecnt;
314 struct IsdnCardState *cs = card->cs;
315 u_char val;
316 char tmp[64];
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)
321 return (0);
323 bytecnt = 8;
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)) {
327 printk(KERN_WARNING
328 "HiSax: %s config port %x-%x already in use\n",
329 CardType[card->typ],
330 cs->hw.asus.cfg_reg,
331 cs->hw.asus.cfg_reg + bytecnt);
332 return (0);
333 } else {
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);
344 if (val == 1) {
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);
356 } else {
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:")) {
370 printk(KERN_WARNING
371 "ISDNLink: wrong HSCX versions check IO address\n");
372 release_io_asuscom(cs);
373 return (0);
376 printk(KERN_INFO "ISDNLink: resetting card\n");
377 reset_asuscom(cs);
378 return (1);