1 /* $Id: teles3.c,v 1.1.1.1 2005/04/11 02:50:24 jack 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 #define __NO_VERSION__
17 #include <linux/init.h>
18 #include <linux/isapnp.h>
24 extern const char *CardType[];
25 const char *teles3_revision = "$Revision: 1.1.1.1 $";
27 #define byteout(addr,val) outb(val,addr)
28 #define bytein(addr) inb(addr)
31 readreg(unsigned int adr, u_char off)
33 return (bytein(adr + off));
37 writereg(unsigned int adr, u_char off, u_char data)
39 byteout(adr + off, data);
44 read_fifo(unsigned int adr, u_char * data, int size)
46 insb(adr, data, size);
50 write_fifo(unsigned int adr, u_char * data, int size)
52 outsb(adr, data, size);
55 /* Interface functions */
58 ReadISAC(struct IsdnCardState *cs, u_char offset)
60 return (readreg(cs->hw.teles3.isac, offset));
64 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
66 writereg(cs->hw.teles3.isac, offset, value);
70 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
72 read_fifo(cs->hw.teles3.isacfifo, data, size);
76 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
78 write_fifo(cs->hw.teles3.isacfifo, data, size);
82 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
84 return (readreg(cs->hw.teles3.hscx[hscx], offset));
88 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
90 writereg(cs->hw.teles3.hscx[hscx], offset, value);
94 * fast interrupt HSCX stuff goes here
97 #define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.hscx[nr], reg)
98 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.hscx[nr], reg, data)
99 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.hscxfifo[nr], ptr, cnt)
100 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.hscxfifo[nr], ptr, cnt)
102 #include "hscx_irq.c"
105 teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs)
108 struct IsdnCardState *cs = dev_id;
113 printk(KERN_WARNING "Teles: Spurious interrupt!\n");
116 val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
119 hscx_int_main(cs, val);
120 val = readreg(cs->hw.teles3.isac, ISAC_ISTA);
123 isac_interrupt(cs, val);
125 val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
126 if (val && count < MAXCOUNT) {
127 if (cs->debug & L1_DEB_HSCX)
128 debugl1(cs, "HSCX IntStat after IntRoutine");
131 val = readreg(cs->hw.teles3.isac, ISAC_ISTA);
132 if (val && count < MAXCOUNT) {
133 if (cs->debug & L1_DEB_ISAC)
134 debugl1(cs, "ISAC IntStat after IntRoutine");
137 if (count >= MAXCOUNT)
138 printk(KERN_WARNING "Teles3: more than %d loops in teles3_interrupt\n", count);
139 writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
140 writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
141 writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF);
142 writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0);
143 writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
144 writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
148 release_ioregs(struct IsdnCardState *cs, int mask)
151 release_region(cs->hw.teles3.isac + 32, 32);
153 release_region(cs->hw.teles3.hscx[0] + 32, 32);
155 release_region(cs->hw.teles3.hscx[1] + 32, 32);
159 release_io_teles3(struct IsdnCardState *cs)
161 if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
162 release_region(cs->hw.teles3.hscx[1], 96);
164 if (cs->hw.teles3.cfg_reg) {
165 if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
166 release_region(cs->hw.teles3.cfg_reg, 1);
168 release_region(cs->hw.teles3.cfg_reg, 8);
171 release_ioregs(cs, 0x7);
176 reset_teles3(struct IsdnCardState *cs)
181 if (cs->typ != ISDN_CTYPE_TELESPCMCIA) {
182 if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
213 byteout(cs->hw.teles3.cfg_reg + 4, irqcfg);
215 HZDELAY(HZ / 10 + 1);
216 byteout(cs->hw.teles3.cfg_reg + 4, irqcfg | 1);
217 HZDELAY(HZ / 10 + 1);
218 restore_flags(flags);
219 } else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
221 byteout(cs->hw.teles3.cfg_reg, 0xff);
223 byteout(cs->hw.teles3.cfg_reg, 0x00);
225 restore_flags(flags);
227 /* Reset off for 16.3 PnP , thanks to Georg Acher */
229 byteout(cs->hw.teles3.isac + 0x3c, 0);
231 byteout(cs->hw.teles3.isac + 0x3c, 1);
233 restore_flags(flags);
240 Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
247 release_io_teles3(cs);
259 static struct isapnp_device_id teles_ids[] __initdata = {
260 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
261 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
262 (unsigned long) "Teles 16.3 PnP" },
263 { ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
264 ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
265 (unsigned long) "Creatix 16.3 PnP" },
266 { ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
267 ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
268 (unsigned long) "Compaq ISDN S0" },
272 static struct isapnp_device_id *tdev = &teles_ids[0];
273 static struct pci_bus *pnp_c __devinitdata = NULL;
277 setup_teles3(struct IsdnCard *card)
280 struct IsdnCardState *cs = card->cs;
283 strcpy(tmp, teles3_revision);
284 printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp));
285 if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP)
286 && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA))
290 if (!card->para[1] && isapnp_present()) {
294 while(tdev->card_vendor) {
295 if ((pb = isapnp_find_card(tdev->card_vendor,
296 tdev->card_device, pnp_c))) {
299 if ((pd = isapnp_find_dev(pnp_c,
300 tdev->vendor, tdev->function, pd))) {
301 printk(KERN_INFO "HiSax: %s detected\n",
302 (char *)tdev->driver_data);
306 card->para[3] = pd->resource[2].start;
307 card->para[2] = pd->resource[1].start;
308 card->para[1] = pd->resource[0].start;
309 card->para[0] = pd->irq_resource[0].start;
310 if (!card->para[0] || !card->para[1] || !card->para[2]) {
311 printk(KERN_ERR "Teles PnP:some resources are missing %ld/%lx/%lx\n",
312 card->para[0], card->para[1], card->para[2]);
318 printk(KERN_ERR "Teles PnP: PnP error card found, no device\n");
324 if (!tdev->card_vendor) {
325 printk(KERN_INFO "Teles PnP: no ISAPnP card found\n");
330 if (cs->typ == ISDN_CTYPE_16_3) {
331 cs->hw.teles3.cfg_reg = card->para[1];
332 switch (cs->hw.teles3.cfg_reg) {
336 cs->hw.teles3.cfg_reg |= 0xc00;
339 cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
340 cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
341 cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
342 } else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
343 cs->hw.teles3.cfg_reg = 0;
344 cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
345 cs->hw.teles3.hscx[1] = card->para[1];
346 cs->hw.teles3.isac = card->para[1] + 0x20;
347 } else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
348 cs->hw.teles3.cfg_reg = card->para[3];
349 cs->hw.teles3.isac = card->para[2] - 32;
350 cs->hw.teles3.hscx[0] = card->para[1] - 32;
351 cs->hw.teles3.hscx[1] = card->para[1];
353 cs->hw.teles3.cfg_reg = 0;
354 cs->hw.teles3.isac = card->para[1] - 32;
355 cs->hw.teles3.hscx[0] = card->para[2] - 32;
356 cs->hw.teles3.hscx[1] = card->para[2];
358 cs->irq = card->para[0];
359 cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
360 cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
361 cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
362 if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
363 if (check_region((cs->hw.teles3.hscx[1]), 96 )) {
365 "HiSax: %s ports %x-%x already in use\n",
367 cs->hw.teles3.hscx[1],
368 cs->hw.teles3.hscx[1] + 96);
371 request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA");
373 if (cs->hw.teles3.cfg_reg) {
374 if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
375 if (check_region((cs->hw.teles3.cfg_reg), 1)) {
377 "HiSax: %s config port %x already in use\n",
379 cs->hw.teles3.cfg_reg);
382 request_region(cs->hw.teles3.cfg_reg, 1, "teles3 cfg");
384 if (check_region((cs->hw.teles3.cfg_reg), 8)) {
386 "HiSax: %s config port %x-%x already in use\n",
388 cs->hw.teles3.cfg_reg,
389 cs->hw.teles3.cfg_reg + 8);
392 request_region(cs->hw.teles3.cfg_reg, 8, "teles3 cfg");
395 if (check_region((cs->hw.teles3.isac + 32), 32)) {
397 "HiSax: %s isac ports %x-%x already in use\n",
399 cs->hw.teles3.isac + 32,
400 cs->hw.teles3.isac + 64);
401 if (cs->hw.teles3.cfg_reg) {
402 if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
403 release_region(cs->hw.teles3.cfg_reg, 1);
405 release_region(cs->hw.teles3.cfg_reg, 8);
410 request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac");
411 if (check_region((cs->hw.teles3.hscx[0] + 32), 32)) {
413 "HiSax: %s hscx A ports %x-%x already in use\n",
415 cs->hw.teles3.hscx[0] + 32,
416 cs->hw.teles3.hscx[0] + 64);
417 if (cs->hw.teles3.cfg_reg) {
418 if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
419 release_region(cs->hw.teles3.cfg_reg, 1);
421 release_region(cs->hw.teles3.cfg_reg, 8);
424 release_ioregs(cs, 1);
427 request_region(cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A");
428 if (check_region((cs->hw.teles3.hscx[1] + 32), 32)) {
430 "HiSax: %s hscx B ports %x-%x already in use\n",
432 cs->hw.teles3.hscx[1] + 32,
433 cs->hw.teles3.hscx[1] + 64);
434 if (cs->hw.teles3.cfg_reg) {
435 if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
436 release_region(cs->hw.teles3.cfg_reg, 1);
438 release_region(cs->hw.teles3.cfg_reg, 8);
441 release_ioregs(cs, 3);
444 request_region(cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B");
446 if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
447 if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
448 printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
449 cs->hw.teles3.cfg_reg + 0, val);
450 release_io_teles3(cs);
453 if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
454 printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
455 cs->hw.teles3.cfg_reg + 1, val);
456 release_io_teles3(cs);
459 val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB
464 * 0x46 16.3 with AB + Video (Teles-Vision)
466 if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) {
467 printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
468 cs->hw.teles3.cfg_reg + 2, val);
469 release_io_teles3(cs);
474 "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n",
475 CardType[cs->typ], cs->irq,
476 cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
478 "HiSax: hscx A:0x%X hscx B:0x%X\n",
479 cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
481 if (reset_teles3(cs)) {
482 printk(KERN_WARNING "Teles3: wrong IRQ\n");
483 release_io_teles3(cs);
486 cs->readisac = &ReadISAC;
487 cs->writeisac = &WriteISAC;
488 cs->readisacfifo = &ReadISACfifo;
489 cs->writeisacfifo = &WriteISACfifo;
490 cs->BC_Read_Reg = &ReadHSCX;
491 cs->BC_Write_Reg = &WriteHSCX;
492 cs->BC_Send_Data = &hscx_fill_fifo;
493 cs->cardmsg = &Teles_card_msg;
494 cs->irq_func = &teles3_interrupt;
495 ISACVersion(cs, "Teles3:");
496 if (HscxVersion(cs, "Teles3:")) {
498 "Teles3: wrong HSCX versions check IO address\n");
499 release_io_teles3(cs);