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 extern const char *CardType
[];
21 static const char *hfcs_revision
= "$Revision: 1.10.2.4 $";
24 hfcs_interrupt(int intno
, void *dev_id
)
26 struct IsdnCardState
*cs
= dev_id
;
30 spin_lock_irqsave(&cs
->lock
, flags
);
31 if ((HFCD_ANYINT
| HFCD_BUSY_NBUSY
) &
32 (stat
= cs
->BC_Read_Reg(cs
, HFCD_DATA
, HFCD_STAT
))) {
33 val
= cs
->BC_Read_Reg(cs
, HFCD_DATA
, HFCD_INT_S1
);
34 if (cs
->debug
& L1_DEB_ISAC
)
35 debugl1(cs
, "HFCS: stat(%02x) s1(%02x)", stat
, val
);
36 hfc2bds0_interrupt(cs
, val
);
38 if (cs
->debug
& L1_DEB_ISAC
)
39 debugl1(cs
, "HFCS: irq_no_irq stat(%02x)", stat
);
41 spin_unlock_irqrestore(&cs
->lock
, flags
);
46 hfcs_Timer(struct IsdnCardState
*cs
)
48 cs
->hw
.hfcD
.timer
.expires
= jiffies
+ 75;
50 /* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
51 add_timer(&cs->hw.hfcD.timer);
56 release_io_hfcs(struct IsdnCardState
*cs
)
59 del_timer(&cs
->hw
.hfcD
.timer
);
61 release_region(cs
->hw
.hfcD
.addr
, 2);
65 reset_hfcs(struct IsdnCardState
*cs
)
67 printk(KERN_INFO
"HFCS: resetting card\n");
68 cs
->hw
.hfcD
.cirm
= HFCD_RESET
;
69 if (cs
->typ
== ISDN_CTYPE_TELES3C
)
70 cs
->hw
.hfcD
.cirm
|= HFCD_MEM8K
;
71 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CIRM
, cs
->hw
.hfcD
.cirm
); /* Reset On */
74 if (cs
->typ
== ISDN_CTYPE_TELES3C
)
75 cs
->hw
.hfcD
.cirm
|= HFCD_MEM8K
;
76 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CIRM
, cs
->hw
.hfcD
.cirm
); /* Reset Off */
78 if (cs
->typ
== ISDN_CTYPE_TELES3C
)
79 cs
->hw
.hfcD
.cirm
|= HFCD_INTB
;
80 else if (cs
->typ
== ISDN_CTYPE_ACERP10
)
81 cs
->hw
.hfcD
.cirm
|= HFCD_INTA
;
82 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CIRM
, cs
->hw
.hfcD
.cirm
);
83 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CLKDEL
, 0x0e);
84 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_TEST
, HFCD_AUTO_AWAKE
); /* S/T Auto awake */
85 cs
->hw
.hfcD
.ctmt
= HFCD_TIM25
| HFCD_AUTO_TIMER
;
86 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CTMT
, cs
->hw
.hfcD
.ctmt
);
87 cs
->hw
.hfcD
.int_m2
= HFCD_IRQ_ENABLE
;
88 cs
->hw
.hfcD
.int_m1
= HFCD_INTS_B1TRANS
| HFCD_INTS_B2TRANS
|
89 HFCD_INTS_DTRANS
| HFCD_INTS_B1REC
| HFCD_INTS_B2REC
|
90 HFCD_INTS_DREC
| HFCD_INTS_L1STATE
;
91 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_INT_M1
, cs
->hw
.hfcD
.int_m1
);
92 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_INT_M2
, cs
->hw
.hfcD
.int_m2
);
93 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_STATES
, HFCD_LOAD_STATE
| 2); /* HFC ST 2 */
95 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_STATES
, 2); /* HFC ST 2 */
96 cs
->hw
.hfcD
.mst_m
= HFCD_MASTER
;
97 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_MST_MODE
, cs
->hw
.hfcD
.mst_m
); /* HFC Master */
98 cs
->hw
.hfcD
.sctrl
= 0;
99 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_SCTRL
, cs
->hw
.hfcD
.sctrl
);
103 hfcs_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
108 if (cs
->debug
& L1_DEB_ISAC
)
109 debugl1(cs
, "HFCS: card_msg %x", mt
);
112 spin_lock_irqsave(&cs
->lock
, flags
);
114 spin_unlock_irqrestore(&cs
->lock
, flags
);
120 delay
= (75*HZ
)/100 +1;
121 mod_timer(&cs
->hw
.hfcD
.timer
, jiffies
+ delay
);
122 spin_lock_irqsave(&cs
->lock
, flags
);
125 spin_unlock_irqrestore(&cs
->lock
, flags
);
126 delay
= (80*HZ
)/1000 +1;
128 spin_lock_irqsave(&cs
->lock
, flags
);
129 cs
->hw
.hfcD
.ctmt
|= HFCD_TIM800
;
130 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CTMT
, cs
->hw
.hfcD
.ctmt
);
131 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_MST_MODE
, cs
->hw
.hfcD
.mst_m
);
132 spin_unlock_irqrestore(&cs
->lock
, flags
);
141 static struct isapnp_device_id hfc_ids
[] __devinitdata
= {
142 { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
143 ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
144 (unsigned long) "Acer P10" },
145 { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
146 ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
147 (unsigned long) "Billion 2" },
148 { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
149 ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
150 (unsigned long) "Billion 1" },
151 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
152 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
153 (unsigned long) "IStar PnP" },
154 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
155 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
156 (unsigned long) "Teles 16.3c" },
157 { ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
158 ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
159 (unsigned long) "Tornado Tipa C" },
160 { ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
161 ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
162 (unsigned long) "Genius Speed Surfer" },
166 static struct isapnp_device_id
*ipid __devinitdata
= &hfc_ids
[0];
167 static struct pnp_card
*pnp_c __devinitdata
= NULL
;
171 setup_hfcs(struct IsdnCard
*card
)
173 struct IsdnCardState
*cs
= card
->cs
;
176 strcpy(tmp
, hfcs_revision
);
177 printk(KERN_INFO
"HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp
));
180 if (!card
->para
[1] && isapnp_present()) {
181 struct pnp_dev
*pnp_d
;
182 while(ipid
->card_vendor
) {
183 if ((pnp_c
= pnp_find_card(ipid
->card_vendor
,
184 ipid
->card_device
, pnp_c
))) {
186 if ((pnp_d
= pnp_find_dev(pnp_c
,
187 ipid
->vendor
, ipid
->function
, pnp_d
))) {
190 printk(KERN_INFO
"HiSax: %s detected\n",
191 (char *)ipid
->driver_data
);
192 pnp_disable_dev(pnp_d
);
193 err
= pnp_activate_dev(pnp_d
);
195 printk(KERN_WARNING
"%s: pnp_activate_dev ret(%d)\n",
199 card
->para
[1] = pnp_port_start(pnp_d
, 0);
200 card
->para
[0] = pnp_irq(pnp_d
, 0);
201 if (!card
->para
[0] || !card
->para
[1]) {
202 printk(KERN_ERR
"HFC PnP:some resources are missing %ld/%lx\n",
203 card
->para
[0], card
->para
[1]);
204 pnp_disable_dev(pnp_d
);
209 printk(KERN_ERR
"HFC PnP: PnP error card found, no device\n");
215 if (!ipid
->card_vendor
) {
216 printk(KERN_INFO
"HFC PnP: no ISAPnP card found\n");
221 cs
->hw
.hfcD
.addr
= card
->para
[1] & 0xfffe;
222 cs
->irq
= card
->para
[0];
224 cs
->hw
.hfcD
.int_s1
= 0;
225 cs
->hw
.hfcD
.send
= NULL
;
226 cs
->bcs
[0].hw
.hfc
.send
= NULL
;
227 cs
->bcs
[1].hw
.hfc
.send
= NULL
;
228 cs
->hw
.hfcD
.dfifosize
= 512;
229 cs
->dc
.hfcd
.ph_state
= 0;
230 cs
->hw
.hfcD
.fifo
= 255;
231 if (cs
->typ
== ISDN_CTYPE_TELES3C
) {
232 cs
->hw
.hfcD
.bfifosize
= 1024 + 512;
233 } else if (cs
->typ
== ISDN_CTYPE_ACERP10
) {
234 cs
->hw
.hfcD
.bfifosize
= 7*1024 + 512;
237 if (!request_region(cs
->hw
.hfcD
.addr
, 2, "HFCS isdn")) {
239 "HiSax: %s config port %x-%x already in use\n",
242 cs
->hw
.hfcD
.addr
+ 2);
246 "HFCS: defined at 0x%x IRQ %d HZ %d\n",
249 if (cs
->typ
== ISDN_CTYPE_TELES3C
) {
250 /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
251 outb(0x00, cs
->hw
.hfcD
.addr
);
252 outb(0x56, cs
->hw
.hfcD
.addr
| 1);
253 } else if (cs
->typ
== ISDN_CTYPE_ACERP10
) {
254 /* Acer P10 IO ADR is 0x300 */
255 outb(0x00, cs
->hw
.hfcD
.addr
);
256 outb(0x57, cs
->hw
.hfcD
.addr
| 1);
259 cs
->hw
.hfcD
.timer
.function
= (void *) hfcs_Timer
;
260 cs
->hw
.hfcD
.timer
.data
= (long) cs
;
261 init_timer(&cs
->hw
.hfcD
.timer
);
262 cs
->cardmsg
= &hfcs_card_msg
;
263 cs
->irq_func
= &hfcs_interrupt
;