Fix typos.
[linux-2.6/linux-mips.git] / drivers / isdn / hisax / asuscom.c
blob7b2809b9e0b1653da8ada87d0b1054ac64cd5207
1 /* $Id: asuscom.c,v 1.11.6.3 2001/09/23 22:24:46 kai Exp $
3 * low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
11 * Thanks to ASUSCOM NETWORK INC. Taiwan and Dynalink NL for information
15 #include <linux/init.h>
16 #include <linux/isapnp.h>
17 #include "hisax.h"
18 #include "isac.h"
19 #include "ipac.h"
20 #include "hscx.h"
21 #include "isdnl1.h"
23 extern const char *CardType[];
25 const char *Asuscom_revision = "$Revision: 1.11.6.3 $";
27 static spinlock_t asuscom_lock = SPIN_LOCK_UNLOCKED;
28 #define byteout(addr,val) outb(val,addr)
29 #define bytein(addr) inb(addr)
31 #define ASUS_ISAC 0
32 #define ASUS_HSCX 1
33 #define ASUS_ADR 2
34 #define ASUS_CTRL_U7 3
35 #define ASUS_CTRL_POTS 5
37 #define ASUS_IPAC_ALE 0
38 #define ASUS_IPAC_DATA 1
40 #define ASUS_ISACHSCX 1
41 #define ASUS_IPAC 2
43 /* CARD_ADR (Write) */
44 #define ASUS_RESET 0x80 /* Bit 7 Reset-Leitung */
46 static inline u8
47 readreg(struct IsdnCardState *cs, unsigned int adr, u8 off)
49 u8 ret;
50 unsigned long flags;
52 spin_lock_irqsave(&asuscom_lock, flags);
53 byteout(cs->hw.asus.adr, off);
54 ret = bytein(adr);
55 spin_unlock_irqrestore(&asuscom_lock, flags);
56 return ret;
59 static inline void
60 writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data)
62 unsigned long flags;
64 spin_lock_irqsave(&asuscom_lock, flags);
65 byteout(cs->hw.asus.adr, off);
66 byteout(adr, data);
67 spin_unlock_irqrestore(&asuscom_lock, flags);
70 static inline void
71 readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
73 byteout(cs->hw.asus.adr, off);
74 insb(adr, data, size);
78 static inline void
79 writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
81 byteout(cs->hw.asus.adr, off);
82 outsb(adr, data, size);
85 static u8
86 isac_read(struct IsdnCardState *cs, u8 offset)
88 return readreg(cs, cs->hw.asus.isac, offset);
91 static void
92 isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
94 writereg(cs, cs->hw.asus.isac, offset, value);
97 static void
98 isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
100 readfifo(cs, cs->hw.asus.isac, 0, data, size);
103 static void
104 isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
106 writefifo(cs, cs->hw.asus.isac, 0, data, size);
109 static struct dc_hw_ops isac_ops = {
110 .read_reg = isac_read,
111 .write_reg = isac_write,
112 .read_fifo = isac_read_fifo,
113 .write_fifo = isac_write_fifo,
116 static u8
117 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
119 return readreg(cs, cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0));
122 static void
123 hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
125 writereg(cs, cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0), value);
128 static void
129 hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
131 readfifo(cs, cs->hw.asus.hscx, hscx ? 0x40 : 0, data, size);
134 static void
135 hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
137 writefifo(cs, cs->hw.asus.hscx, hscx ? 0x40 : 0, data, size);
140 static struct bc_hw_ops hscx_ops = {
141 .read_reg = hscx_read,
142 .write_reg = hscx_write,
143 .read_fifo = hscx_read_fifo,
144 .write_fifo = hscx_write_fifo,
147 static inline u8
148 ipac_read(struct IsdnCardState *cs, u8 off)
150 u8 ret;
151 unsigned long flags;
153 spin_lock_irqsave(&asuscom_lock, flags);
154 byteout(cs->hw.asus.adr, off);
155 ret = bytein(cs->hw.asus.isac);
156 spin_unlock_irqrestore(&asuscom_lock, flags);
157 return ret;
160 static inline void
161 ipac_write(struct IsdnCardState *cs, u8 off, u8 data)
163 unsigned long flags;
165 spin_lock_irqsave(&asuscom_lock, flags);
166 byteout(cs->hw.asus.adr, off);
167 byteout(cs->hw.asus.isac, data);
168 spin_unlock_irqrestore(&asuscom_lock, flags);
171 static inline void
172 ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
174 byteout(cs->hw.asus.adr, off);
175 insb(cs->hw.asus.isac, data, size);
179 static inline void
180 ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
182 byteout(cs->hw.asus.adr, off);
183 outsb(cs->hw.asus.isac, data, size);
186 /* This will generate ipac_dc_ops and ipac_bc_ops using the functions
187 * above */
189 BUILD_IPAC_OPS(ipac);
191 static int
192 asuscom_reset(struct IsdnCardState *cs)
194 byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */
195 set_current_state(TASK_UNINTERRUPTIBLE);
196 schedule_timeout((10*HZ)/1000);
197 byteout(cs->hw.asus.adr, 0); /* Reset Off */
198 set_current_state(TASK_UNINTERRUPTIBLE);
199 schedule_timeout((10*HZ)/1000);
200 return 0;
203 static int
204 asuscom_ipac_reset(struct IsdnCardState *cs)
206 writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x20);
207 set_current_state(TASK_UNINTERRUPTIBLE);
208 schedule_timeout((10*HZ)/1000);
209 writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x0);
210 set_current_state(TASK_UNINTERRUPTIBLE);
211 schedule_timeout((10*HZ)/1000);
212 writereg(cs, cs->hw.asus.isac, IPAC_CONF, 0x0);
213 writereg(cs, cs->hw.asus.isac, IPAC_ACFG, 0xff);
214 writereg(cs, cs->hw.asus.isac, IPAC_AOE, 0x0);
215 writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xc0);
216 writereg(cs, cs->hw.asus.isac, IPAC_PCFG, 0x12);
217 return 0;
220 static struct card_ops asuscom_ops = {
221 .init = inithscxisac,
222 .reset = asuscom_reset,
223 .release = hisax_release_resources,
224 .irq_func = hscxisac_irq,
227 static struct card_ops asuscom_ipac_ops = {
228 .init = ipac_init,
229 .reset = asuscom_ipac_reset,
230 .release = hisax_release_resources,
231 .irq_func = ipac_irq,
234 static int __init
235 asuscom_probe(struct IsdnCardState *cs, struct IsdnCard *card)
237 int rc;
238 u8 val;
240 printk(KERN_INFO "ISDNLink: defined at %#lx IRQ %lu\n",
241 card->para[1], card->para[0]);
243 cs->hw.asus.cfg_reg = card->para[1];
244 cs->irq = card->para[0];
246 rc = -EBUSY;
247 if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, 8, "asuscom isdn"))
248 goto err;
250 rc = -ENODEV;
251 cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
252 val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
253 if ((val == 1) || (val == 2)) {
254 cs->subtyp = ASUS_IPAC;
255 cs->card_ops = &asuscom_ipac_ops;
256 cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
257 if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
258 goto err;
259 } else {
260 cs->subtyp = ASUS_ISACHSCX;
261 cs->card_ops = &asuscom_ops;
262 cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
263 cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
264 cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
265 cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
266 cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
267 if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
268 goto err;
270 printk(KERN_INFO "ISDNLink: resetting card\n");
271 cs->card_ops->reset(cs);
272 return 0;
274 err:
275 hisax_release_resources(cs);
276 return rc;
279 #ifdef __ISAPNP__
280 static struct isapnp_device_id asus_ids[] __initdata = {
281 { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
282 ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
283 (unsigned long) "Asus1688 PnP" },
284 { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1690),
285 ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1690),
286 (unsigned long) "Asus1690 PnP" },
287 { ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0020),
288 ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0020),
289 (unsigned long) "Isurf2 PnP" },
290 { ISAPNP_VENDOR('E', 'L', 'F'), ISAPNP_FUNCTION(0x0000),
291 ISAPNP_VENDOR('E', 'L', 'F'), ISAPNP_FUNCTION(0x0000),
292 (unsigned long) "Iscas TE320" },
293 { 0, }
296 static struct isapnp_device_id *adev = &asus_ids[0];
297 static struct pnp_card *pnp_c __devinitdata = NULL;
298 #endif
300 int __init
301 setup_asuscom(struct IsdnCard *card)
303 char tmp[64];
305 strcpy(tmp, Asuscom_revision);
306 printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp));
307 #ifdef __ISAPNP__
308 if (!card->para[1] && isapnp_present()) {
309 struct pnp_card *pb;
310 struct pnp_dev *pd;
312 while(adev->card_vendor) {
313 if ((pb = pnp_find_card(adev->card_vendor,
314 adev->card_device,
315 pnp_c))) {
316 pnp_c = pb;
317 pd = NULL;
318 if ((pd = pnp_find_dev(pnp_c,
319 adev->vendor,
320 adev->function,
321 pd))) {
322 printk(KERN_INFO "HiSax: %s detected\n",
323 (char *)adev->driver_data);
324 if (pnp_device_attach(pd) < 0) {
325 printk(KERN_ERR "AsusPnP: attach failed\n");
326 return 0;
328 if (pnp_activate_dev(pd) < 0) {
329 printk(KERN_ERR "AsusPnP: activate failed\n");
330 pnp_device_detach(pd);
331 return 0;
333 if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
334 printk(KERN_ERR "AsusPnP:some resources are missing %ld/%lx\n",
335 pnp_irq(pd, 0), pnp_port_start(pd, 0));
336 pnp_device_detach(pd);
337 return(0);
339 card->para[1] = pnp_port_start(pd, 0);
340 card->para[0] = pnp_irq(pd, 0);
341 break;
342 } else {
343 printk(KERN_ERR "AsusPnP: PnP error card found, no device\n");
346 adev++;
347 pnp_c=NULL;
349 if (!adev->card_vendor) {
350 printk(KERN_INFO "AsusPnP: no ISAPnP card found\n");
351 return(0);
354 #endif
355 if (asuscom_probe(card->cs, card) < 0)
356 return 0;
357 return 1;