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
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 Jan den Ouden
16 #include <linux/init.h>
17 #include <linux/isapnp.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)
30 readreg(unsigned int adr
, u8 off
)
32 return (bytein(adr
+ off
));
36 writereg(unsigned int adr
, u8 off
, u8 data
)
38 byteout(adr
+ off
, data
);
43 read_fifo(unsigned int adr
, u8
* data
, int size
)
45 insb(adr
, data
, size
);
49 write_fifo(unsigned int adr
, u8
* data
, int size
)
51 outsb(adr
, data
, size
);
55 isac_read(struct IsdnCardState
*cs
, u8 offset
)
57 return readreg(cs
->hw
.teles3
.isac
, offset
);
61 isac_write(struct IsdnCardState
*cs
, u8 offset
, u8 value
)
63 writereg(cs
->hw
.teles3
.isac
, offset
, value
);
67 isac_read_fifo(struct IsdnCardState
*cs
, u8
* data
, int size
)
69 read_fifo(cs
->hw
.teles3
.isacfifo
, data
, size
);
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
,
86 hscx_read(struct IsdnCardState
*cs
, int hscx
, u8 offset
)
88 return readreg(cs
->hw
.teles3
.hscx
[hscx
], offset
);
92 hscx_write(struct IsdnCardState
*cs
, int hscx
, u8 offset
, u8 value
)
94 writereg(cs
->hw
.teles3
.hscx
[hscx
], offset
, value
);
98 hscx_read_fifo(struct IsdnCardState
*cs
, int hscx
, u8
*data
, int size
)
100 read_fifo(cs
->hw
.teles3
.hscxfifo
[hscx
], data
, size
);
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
,
117 teles3_reset(struct IsdnCardState
*cs
)
121 if (cs
->typ
!= ISDN_CTYPE_TELESPCMCIA
) {
122 if ((cs
->hw
.teles3
.cfg_reg
) && (cs
->typ
!= ISDN_CTYPE_COMPAQ_ISA
)) {
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);
159 byteout(cs
->hw
.teles3
.cfg_reg
, 0x00);
162 /* Reset off for 16.3 PnP , thanks to Georg Acher */
163 byteout(cs
->hw
.teles3
.isac
+ 0x3c, 0);
165 byteout(cs
->hw
.teles3
.isac
+ 0x3c, 1);
172 static struct card_ops teles3_ops
= {
173 .init
= inithscxisac
,
174 .reset
= teles3_reset
,
175 .release
= hisax_release_resources
,
176 .irq_func
= hscxisac_irq
,
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");
193 cs
->card_ops
= &teles3_ops
;
194 if (hscxisac_setup(cs
, &isac_ops
, &hscx_ops
))
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;
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"))
219 if (teles_hw_init(cs
) < 0)
223 hisax_release_resources(cs
);
228 teles_request_io(struct IsdnCardState
*cs
)
230 if (!request_io(&cs
->rs
, cs
->hw
.teles3
.isac
+ 32, 32, "HiSax isac"))
232 if (!request_io(&cs
->rs
, cs
->hw
.teles3
.hscx
[0]+32, 32, "HiSax hscx A"))
234 if (!request_io(&cs
->rs
, cs
->hw
.teles3
.hscx
[1]+32, 32, "HiSax hscx B"))
240 teles16_3_probe(struct IsdnCardState
*cs
, struct IsdnCard
*card
)
244 cs
->hw
.teles3
.cfg_reg
= card
->para
[1];
245 switch (cs
->hw
.teles3
.cfg_reg
) {
249 cs
->hw
.teles3
.cfg_reg
|= 0xc00;
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"))
258 if (teles_request_io(cs
) < 0)
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
);
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
);
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
);
279 if (teles_hw_init(cs
) < 0)
283 hisax_release_resources(cs
);
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"))
297 if (teles_request_io(cs
) < 0)
299 if (teles_hw_init(cs
) < 0)
303 hisax_release_resources(cs
);
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)
317 if (teles_hw_init(cs
) < 0)
321 hisax_release_resources(cs
);
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" },
339 static struct isapnp_device_id
*tdev
= &teles_ids
[0];
340 static struct pnp_card
*pnp_c __devinitdata
= NULL
;
344 setup_teles3(struct IsdnCard
*card
)
348 strcpy(tmp
, teles3_revision
);
349 printk(KERN_INFO
"HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp
));
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
))) {
360 if ((pnp_dev
= pnp_find_dev(pnp_card
,
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");
370 if (pnp_activate_dev(pnp_dev
) < 0) {
371 printk(KERN_ERR
"Teles PnP: activate failed\n");
372 pnp_device_detach(pnp_dev
);
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
);
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);
389 printk(KERN_ERR
"Teles PnP: PnP error card found, no device\n");
395 if (!tdev
->card_vendor
) {
396 printk(KERN_INFO
"Teles PnP: no ISAPnP card found\n");
401 if (card
->cs
->typ
== ISDN_CTYPE_16_3
) {
402 if (teles16_3_probe(card
->cs
, card
) < 0)
404 } else if (card
->cs
->typ
== ISDN_CTYPE_TELESPCMCIA
) {
405 if (telespcmcia_probe(card
->cs
, card
) < 0)
407 } else if (card
->cs
->typ
== ISDN_CTYPE_COMPAQ_ISA
) {
408 if (compaq_probe(card
->cs
, card
) < 0)
411 if (telespnp_probe(card
->cs
, card
) < 0)