Fix typos.
[linux-2.6/linux-mips.git] / drivers / isdn / hisax / teles3.c
blobed07413798b6d22b251be2101ee20fc6a4e319e5
1 /* $Id: teles3.c,v 2.17.6.2 2001/09/23 22:24:52 kai Exp $
3 * low level stuff for Teles 16.3 & PNP isdn cards
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
7 *
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 Jan den Ouden
12 * Fritz Elfert
13 * Beat Doebeli
16 #include <linux/init.h>
17 #include <linux/isapnp.h>
18 #include "hisax.h"
19 #include "isac.h"
20 #include "hscx.h"
21 #include "isdnl1.h"
23 extern const char *CardType[];
24 const char *teles3_revision = "$Revision: 2.17.6.2 $";
26 #define byteout(addr,val) outb(val,addr)
27 #define bytein(addr) inb(addr)
29 static inline u8
30 readreg(unsigned int adr, u8 off)
32 return (bytein(adr + off));
35 static inline void
36 writereg(unsigned int adr, u8 off, u8 data)
38 byteout(adr + off, data);
42 static inline void
43 read_fifo(unsigned int adr, u8 * data, int size)
45 insb(adr, data, size);
48 static void
49 write_fifo(unsigned int adr, u8 * data, int size)
51 outsb(adr, data, size);
54 static u8
55 isac_read(struct IsdnCardState *cs, u8 offset)
57 return readreg(cs->hw.teles3.isac, offset);
60 static void
61 isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
63 writereg(cs->hw.teles3.isac, offset, value);
66 static void
67 isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
69 read_fifo(cs->hw.teles3.isacfifo, data, size);
72 static void
73 isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
75 write_fifo(cs->hw.teles3.isacfifo, data, size);
78 static struct dc_hw_ops isac_ops = {
79 .read_reg = isac_read,
80 .write_reg = isac_write,
81 .read_fifo = isac_read_fifo,
82 .write_fifo = isac_write_fifo,
85 static u8
86 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
88 return readreg(cs->hw.teles3.hscx[hscx], offset);
91 static void
92 hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
94 writereg(cs->hw.teles3.hscx[hscx], offset, value);
97 static void
98 hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
100 read_fifo(cs->hw.teles3.hscxfifo[hscx], data, size);
103 static void
104 hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
106 write_fifo(cs->hw.teles3.hscxfifo[hscx], data, size);
109 static struct bc_hw_ops hscx_ops = {
110 .read_reg = hscx_read,
111 .write_reg = hscx_write,
112 .read_fifo = hscx_read_fifo,
113 .write_fifo = hscx_write_fifo,
116 static int
117 teles3_reset(struct IsdnCardState *cs)
119 u8 irqcfg;
121 if (cs->typ != ISDN_CTYPE_TELESPCMCIA) {
122 if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
123 switch (cs->irq) {
124 case 2:
125 case 9:
126 irqcfg = 0x00;
127 break;
128 case 3:
129 irqcfg = 0x02;
130 break;
131 case 4:
132 irqcfg = 0x04;
133 break;
134 case 5:
135 irqcfg = 0x06;
136 break;
137 case 10:
138 irqcfg = 0x08;
139 break;
140 case 11:
141 irqcfg = 0x0A;
142 break;
143 case 12:
144 irqcfg = 0x0C;
145 break;
146 case 15:
147 irqcfg = 0x0E;
148 break;
149 default:
150 return(1);
152 byteout(cs->hw.teles3.cfg_reg + 4, irqcfg);
153 HZDELAY(HZ / 10 + 1);
154 byteout(cs->hw.teles3.cfg_reg + 4, irqcfg | 1);
155 HZDELAY(HZ / 10 + 1);
156 } else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
157 byteout(cs->hw.teles3.cfg_reg, 0xff);
158 HZDELAY(2);
159 byteout(cs->hw.teles3.cfg_reg, 0x00);
160 HZDELAY(2);
161 } else {
162 /* Reset off for 16.3 PnP , thanks to Georg Acher */
163 byteout(cs->hw.teles3.isac + 0x3c, 0);
164 HZDELAY(2);
165 byteout(cs->hw.teles3.isac + 0x3c, 1);
166 HZDELAY(2);
169 return(0);
172 static struct card_ops teles3_ops = {
173 .init = inithscxisac,
174 .reset = teles3_reset,
175 .release = hisax_release_resources,
176 .irq_func = hscxisac_irq,
179 static int
180 teles_hw_init(struct IsdnCardState *cs)
183 printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n",
184 CardType[cs->typ], cs->irq,
185 cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
186 printk(KERN_INFO "HiSax: hscx A:0x%X hscx B:0x%X\n",
187 cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
189 if (teles3_reset(cs)) {
190 printk(KERN_WARNING "Teles3: wrong IRQ\n");
191 return -EBUSY;
193 cs->card_ops = &teles3_ops;
194 if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
195 return -EBUSY;
196 return 0;
199 static void __init
200 teles_setup_io(struct IsdnCardState *cs, struct IsdnCard *card)
202 cs->irq = card->para[0];
203 cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
204 cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
205 cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
208 static int __init
209 telespcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
211 cs->hw.teles3.cfg_reg = 0;
212 cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
213 cs->hw.teles3.hscx[1] = card->para[1];
214 cs->hw.teles3.isac = card->para[1] + 0x20;
215 teles_setup_io(cs, card);
216 if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96,
217 "HiSax Teles PCMCIA"))
218 goto err;
219 if (teles_hw_init(cs) < 0)
220 goto err;
221 return 0;
222 err:
223 hisax_release_resources(cs);
224 return -EBUSY;
227 static int __init
228 teles_request_io(struct IsdnCardState *cs)
230 if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
231 return -EBUSY;
232 if (!request_io(&cs->rs, cs->hw.teles3.hscx[0]+32, 32, "HiSax hscx A"))
233 return -EBUSY;
234 if (!request_io(&cs->rs, cs->hw.teles3.hscx[1]+32, 32, "HiSax hscx B"))
235 return -EBUSY;
236 return 0;
239 static int __init
240 teles16_3_probe(struct IsdnCardState *cs, struct IsdnCard *card)
242 u8 val;
244 cs->hw.teles3.cfg_reg = card->para[1];
245 switch (cs->hw.teles3.cfg_reg) {
246 case 0x180:
247 case 0x280:
248 case 0x380:
249 cs->hw.teles3.cfg_reg |= 0xc00;
250 break;
252 cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
253 cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
254 cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
255 teles_setup_io(cs, card);
256 if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
257 goto err;
258 if (teles_request_io(cs) < 0)
259 goto err;
260 if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
261 printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
262 cs->hw.teles3.cfg_reg + 0, val);
263 goto err;
265 if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
266 printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
267 cs->hw.teles3.cfg_reg + 1, val);
268 goto err;
270 /* 0x1e without AB, 0x1f with AB, 0x1c 16.3 ???,
271 * 0x39 16.3 1.1, 0x38 16.3 1.3, 0x46 16.3 with AB + Video */
272 val = bytein(cs->hw.teles3.cfg_reg + 2);
273 if (val != 0x46 && val != 0x39 && val != 0x38 &&
274 val != 0x1c && val != 0x1e && val != 0x1f) {
275 printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
276 cs->hw.teles3.cfg_reg + 2, val);
277 goto err;
279 if (teles_hw_init(cs) < 0)
280 goto err;
281 return 0;
282 err:
283 hisax_release_resources(cs);
284 return -EBUSY;
287 static int __init
288 compaq_probe(struct IsdnCardState *cs, struct IsdnCard *card)
290 cs->hw.teles3.cfg_reg = card->para[3];
291 cs->hw.teles3.isac = card->para[2] - 32;
292 cs->hw.teles3.hscx[0] = card->para[1] - 32;
293 cs->hw.teles3.hscx[1] = card->para[1];
294 teles_setup_io(cs, card);
295 if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
296 goto err;
297 if (teles_request_io(cs) < 0)
298 goto err;
299 if (teles_hw_init(cs) < 0)
300 goto err;
301 return 0;
302 err:
303 hisax_release_resources(cs);
304 return -EBUSY;
307 static int __init
308 telespnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
310 cs->hw.teles3.cfg_reg = 0;
311 cs->hw.teles3.isac = card->para[1] - 32;
312 cs->hw.teles3.hscx[0] = card->para[2] - 32;
313 cs->hw.teles3.hscx[1] = card->para[2];
314 teles_setup_io(cs, card);
315 if (teles_request_io(cs) < 0)
316 goto err;
317 if (teles_hw_init(cs) < 0)
318 goto err;
319 return 0;
320 err:
321 hisax_release_resources(cs);
322 return -EBUSY;
325 #ifdef __ISAPNP__
326 static struct isapnp_device_id teles_ids[] __initdata = {
327 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
328 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
329 (unsigned long) "Teles 16.3 PnP" },
330 { ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
331 ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
332 (unsigned long) "Creatix 16.3 PnP" },
333 { ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
334 ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
335 (unsigned long) "Compaq ISDN S0" },
336 { 0, }
339 static struct isapnp_device_id *tdev = &teles_ids[0];
340 static struct pnp_card *pnp_c __devinitdata = NULL;
341 #endif
343 int __devinit
344 setup_teles3(struct IsdnCard *card)
346 char tmp[64];
348 strcpy(tmp, teles3_revision);
349 printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp));
350 #ifdef __ISAPNP__
351 if (!card->para[1] && isapnp_present()) {
352 struct pnp_card *pnp_card;
353 struct pnp_dev *pnp_dev;
355 while(tdev->card_vendor) {
356 if ((pnp_card = pnp_find_card(tdev->card_vendor,
357 tdev->card_device, pnp_c))) {
358 pnp_c = pnp_card;
359 pnp_dev = NULL;
360 if ((pnp_dev = pnp_find_dev(pnp_card,
361 tdev->vendor,
362 tdev->function,
363 pnp_dev))) {
364 printk(KERN_INFO "HiSax: %s detected\n",
365 (char *)tdev->driver_data);
366 if (pnp_device_attach(pnp_dev) < 0) {
367 printk(KERN_ERR "Teles PnP: attach failed\n");
368 return 0;
370 if (pnp_activate_dev(pnp_dev) < 0) {
371 printk(KERN_ERR "Teles PnP: activate failed\n");
372 pnp_device_detach(pnp_dev);
373 return 0;
375 if (!pnp_irq_valid(pnp_dev, 0) ||
376 !pnp_port_valid(pnp_dev, 0) ||
377 !pnp_port_valid(pnp_dev, 1)) {
378 printk(KERN_ERR "Teles PnP: some resources are missing %ld/%lx/%lx\n",
379 pnp_irq(pnp_dev, 0), pnp_port_start(pnp_dev, 0), pnp_port_start(pnp_dev, 1));
380 pnp_device_detach(pnp_dev);
381 return 0;
383 card->para[3] = pnp_port_start(pnp_dev, 2);
384 card->para[2] = pnp_port_start(pnp_dev, 1);
385 card->para[1] = pnp_port_start(pnp_dev, 0);
386 card->para[0] = pnp_irq(pnp_dev, 0);
387 break;
388 } else {
389 printk(KERN_ERR "Teles PnP: PnP error card found, no device\n");
392 tdev++;
393 pnp_c=NULL;
395 if (!tdev->card_vendor) {
396 printk(KERN_INFO "Teles PnP: no ISAPnP card found\n");
397 return(0);
400 #endif
401 if (card->cs->typ == ISDN_CTYPE_16_3) {
402 if (teles16_3_probe(card->cs, card) < 0)
403 return 0;
404 } else if (card->cs->typ == ISDN_CTYPE_TELESPCMCIA) {
405 if (telespcmcia_probe(card->cs, card) < 0)
406 return 0;
407 } else if (card->cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
408 if (compaq_probe(card->cs, card) < 0)
409 return 0;
410 } else { /* PNP */
411 if (telespnp_probe(card->cs, card) < 0)
412 return 0;
414 return 1;