1 /* $Id: hfcscard.c,v 1.10.2.4 2004/01/14 16:04:48 keil Exp $
3 * low level stuff for hfcs based cards (Teles3c, ACER P10)
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.
13 #include <linux/init.h>
14 #include <linux/isapnp.h>
16 #include "hfc_2bds0.h"
19 static const char *hfcs_revision
= "$Revision: 1.10.2.4 $";
22 hfcs_interrupt(int intno
, void *dev_id
)
24 struct IsdnCardState
*cs
= dev_id
;
28 spin_lock_irqsave(&cs
->lock
, flags
);
29 if ((HFCD_ANYINT
| HFCD_BUSY_NBUSY
) &
30 (stat
= cs
->BC_Read_Reg(cs
, HFCD_DATA
, HFCD_STAT
))) {
31 val
= cs
->BC_Read_Reg(cs
, HFCD_DATA
, HFCD_INT_S1
);
32 if (cs
->debug
& L1_DEB_ISAC
)
33 debugl1(cs
, "HFCS: stat(%02x) s1(%02x)", stat
, val
);
34 hfc2bds0_interrupt(cs
, val
);
36 if (cs
->debug
& L1_DEB_ISAC
)
37 debugl1(cs
, "HFCS: irq_no_irq stat(%02x)", stat
);
39 spin_unlock_irqrestore(&cs
->lock
, flags
);
44 hfcs_Timer(struct IsdnCardState
*cs
)
46 cs
->hw
.hfcD
.timer
.expires
= jiffies
+ 75;
48 /* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
49 add_timer(&cs->hw.hfcD.timer);
54 release_io_hfcs(struct IsdnCardState
*cs
)
57 del_timer(&cs
->hw
.hfcD
.timer
);
59 release_region(cs
->hw
.hfcD
.addr
, 2);
63 reset_hfcs(struct IsdnCardState
*cs
)
65 printk(KERN_INFO
"HFCS: resetting card\n");
66 cs
->hw
.hfcD
.cirm
= HFCD_RESET
;
67 if (cs
->typ
== ISDN_CTYPE_TELES3C
)
68 cs
->hw
.hfcD
.cirm
|= HFCD_MEM8K
;
69 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CIRM
, cs
->hw
.hfcD
.cirm
); /* Reset On */
72 if (cs
->typ
== ISDN_CTYPE_TELES3C
)
73 cs
->hw
.hfcD
.cirm
|= HFCD_MEM8K
;
74 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CIRM
, cs
->hw
.hfcD
.cirm
); /* Reset Off */
76 if (cs
->typ
== ISDN_CTYPE_TELES3C
)
77 cs
->hw
.hfcD
.cirm
|= HFCD_INTB
;
78 else if (cs
->typ
== ISDN_CTYPE_ACERP10
)
79 cs
->hw
.hfcD
.cirm
|= HFCD_INTA
;
80 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CIRM
, cs
->hw
.hfcD
.cirm
);
81 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CLKDEL
, 0x0e);
82 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_TEST
, HFCD_AUTO_AWAKE
); /* S/T Auto awake */
83 cs
->hw
.hfcD
.ctmt
= HFCD_TIM25
| HFCD_AUTO_TIMER
;
84 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CTMT
, cs
->hw
.hfcD
.ctmt
);
85 cs
->hw
.hfcD
.int_m2
= HFCD_IRQ_ENABLE
;
86 cs
->hw
.hfcD
.int_m1
= HFCD_INTS_B1TRANS
| HFCD_INTS_B2TRANS
|
87 HFCD_INTS_DTRANS
| HFCD_INTS_B1REC
| HFCD_INTS_B2REC
|
88 HFCD_INTS_DREC
| HFCD_INTS_L1STATE
;
89 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_INT_M1
, cs
->hw
.hfcD
.int_m1
);
90 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_INT_M2
, cs
->hw
.hfcD
.int_m2
);
91 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_STATES
, HFCD_LOAD_STATE
| 2); /* HFC ST 2 */
93 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_STATES
, 2); /* HFC ST 2 */
94 cs
->hw
.hfcD
.mst_m
= HFCD_MASTER
;
95 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_MST_MODE
, cs
->hw
.hfcD
.mst_m
); /* HFC Master */
96 cs
->hw
.hfcD
.sctrl
= 0;
97 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_SCTRL
, cs
->hw
.hfcD
.sctrl
);
101 hfcs_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
106 if (cs
->debug
& L1_DEB_ISAC
)
107 debugl1(cs
, "HFCS: card_msg %x", mt
);
110 spin_lock_irqsave(&cs
->lock
, flags
);
112 spin_unlock_irqrestore(&cs
->lock
, flags
);
118 delay
= (75 * HZ
) / 100 + 1;
119 mod_timer(&cs
->hw
.hfcD
.timer
, jiffies
+ delay
);
120 spin_lock_irqsave(&cs
->lock
, flags
);
123 spin_unlock_irqrestore(&cs
->lock
, flags
);
124 delay
= (80 * HZ
) / 1000 + 1;
126 spin_lock_irqsave(&cs
->lock
, flags
);
127 cs
->hw
.hfcD
.ctmt
|= HFCD_TIM800
;
128 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CTMT
, cs
->hw
.hfcD
.ctmt
);
129 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_MST_MODE
, cs
->hw
.hfcD
.mst_m
);
130 spin_unlock_irqrestore(&cs
->lock
, flags
);
139 static struct isapnp_device_id hfc_ids
[] = {
140 { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
141 ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
142 (unsigned long) "Acer P10" },
143 { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
144 ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
145 (unsigned long) "Billion 2" },
146 { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
147 ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
148 (unsigned long) "Billion 1" },
149 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
150 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
151 (unsigned long) "IStar PnP" },
152 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
153 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
154 (unsigned long) "Teles 16.3c" },
155 { ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
156 ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
157 (unsigned long) "Tornado Tipa C" },
158 { ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
159 ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
160 (unsigned long) "Genius Speed Surfer" },
164 static struct isapnp_device_id
*ipid
= &hfc_ids
[0];
165 static struct pnp_card
*pnp_c
= NULL
;
168 int setup_hfcs(struct IsdnCard
*card
)
170 struct IsdnCardState
*cs
= card
->cs
;
173 strcpy(tmp
, hfcs_revision
);
174 printk(KERN_INFO
"HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp
));
177 if (!card
->para
[1] && isapnp_present()) {
178 struct pnp_dev
*pnp_d
;
179 while (ipid
->card_vendor
) {
180 if ((pnp_c
= pnp_find_card(ipid
->card_vendor
,
181 ipid
->card_device
, pnp_c
))) {
183 if ((pnp_d
= pnp_find_dev(pnp_c
,
184 ipid
->vendor
, ipid
->function
, pnp_d
))) {
187 printk(KERN_INFO
"HiSax: %s detected\n",
188 (char *)ipid
->driver_data
);
189 pnp_disable_dev(pnp_d
);
190 err
= pnp_activate_dev(pnp_d
);
192 printk(KERN_WARNING
"%s: pnp_activate_dev ret(%d)\n",
196 card
->para
[1] = pnp_port_start(pnp_d
, 0);
197 card
->para
[0] = pnp_irq(pnp_d
, 0);
198 if (!card
->para
[0] || !card
->para
[1]) {
199 printk(KERN_ERR
"HFC PnP:some resources are missing %ld/%lx\n",
200 card
->para
[0], card
->para
[1]);
201 pnp_disable_dev(pnp_d
);
206 printk(KERN_ERR
"HFC PnP: PnP error card found, no device\n");
212 if (!ipid
->card_vendor
) {
213 printk(KERN_INFO
"HFC PnP: no ISAPnP card found\n");
218 cs
->hw
.hfcD
.addr
= card
->para
[1] & 0xfffe;
219 cs
->irq
= card
->para
[0];
221 cs
->hw
.hfcD
.int_s1
= 0;
222 cs
->hw
.hfcD
.send
= NULL
;
223 cs
->bcs
[0].hw
.hfc
.send
= NULL
;
224 cs
->bcs
[1].hw
.hfc
.send
= NULL
;
225 cs
->hw
.hfcD
.dfifosize
= 512;
226 cs
->dc
.hfcd
.ph_state
= 0;
227 cs
->hw
.hfcD
.fifo
= 255;
228 if (cs
->typ
== ISDN_CTYPE_TELES3C
) {
229 cs
->hw
.hfcD
.bfifosize
= 1024 + 512;
230 } else if (cs
->typ
== ISDN_CTYPE_ACERP10
) {
231 cs
->hw
.hfcD
.bfifosize
= 7 * 1024 + 512;
234 if (!request_region(cs
->hw
.hfcD
.addr
, 2, "HFCS isdn")) {
236 "HiSax: %s config port %x-%x already in use\n",
239 cs
->hw
.hfcD
.addr
+ 2);
243 "HFCS: defined at 0x%x IRQ %d HZ %d\n",
246 if (cs
->typ
== ISDN_CTYPE_TELES3C
) {
247 /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
248 outb(0x00, cs
->hw
.hfcD
.addr
);
249 outb(0x56, cs
->hw
.hfcD
.addr
| 1);
250 } else if (cs
->typ
== ISDN_CTYPE_ACERP10
) {
251 /* Acer P10 IO ADR is 0x300 */
252 outb(0x00, cs
->hw
.hfcD
.addr
);
253 outb(0x57, cs
->hw
.hfcD
.addr
| 1);
256 cs
->hw
.hfcD
.timer
.function
= (void *) hfcs_Timer
;
257 cs
->hw
.hfcD
.timer
.data
= (long) cs
;
258 init_timer(&cs
->hw
.hfcD
.timer
);
259 cs
->cardmsg
= &hfcs_card_msg
;
260 cs
->irq_func
= &hfcs_interrupt
;