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
, struct pt_regs
*regs
)
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 cs
->hw
.hfcD
.timer
.expires
= jiffies
+ delay
;
122 add_timer(&cs
->hw
.hfcD
.timer
);
123 spin_lock_irqsave(&cs
->lock
, flags
);
126 spin_unlock_irqrestore(&cs
->lock
, flags
);
127 delay
= (80*HZ
)/1000 +1;
128 set_current_state(TASK_UNINTERRUPTIBLE
);
129 schedule_timeout((80*HZ
)/1000);
130 spin_lock_irqsave(&cs
->lock
, flags
);
131 cs
->hw
.hfcD
.ctmt
|= HFCD_TIM800
;
132 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_CTMT
, cs
->hw
.hfcD
.ctmt
);
133 cs
->BC_Write_Reg(cs
, HFCD_DATA
, HFCD_MST_MODE
, cs
->hw
.hfcD
.mst_m
);
134 spin_unlock_irqrestore(&cs
->lock
, flags
);
143 static struct isapnp_device_id hfc_ids
[] __initdata
= {
144 { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
145 ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
146 (unsigned long) "Acer P10" },
147 { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
148 ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
149 (unsigned long) "Billion 2" },
150 { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
151 ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
152 (unsigned long) "Billion 1" },
153 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
154 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
155 (unsigned long) "IStar PnP" },
156 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
157 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
158 (unsigned long) "Teles 16.3c" },
159 { ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
160 ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
161 (unsigned long) "Tornado Tipa C" },
162 { ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
163 ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
164 (unsigned long) "Genius Speed Surfer" },
168 static struct isapnp_device_id
*ipid __initdata
= &hfc_ids
[0];
169 static struct pnp_card
*pnp_c __devinitdata
= NULL
;
173 setup_hfcs(struct IsdnCard
*card
)
175 struct IsdnCardState
*cs
= card
->cs
;
178 strcpy(tmp
, hfcs_revision
);
179 printk(KERN_INFO
"HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp
));
182 if (!card
->para
[1] && isapnp_present()) {
183 struct pnp_dev
*pnp_d
;
184 while(ipid
->card_vendor
) {
185 if ((pnp_c
= pnp_find_card(ipid
->card_vendor
,
186 ipid
->card_device
, pnp_c
))) {
188 if ((pnp_d
= pnp_find_dev(pnp_c
,
189 ipid
->vendor
, ipid
->function
, pnp_d
))) {
192 printk(KERN_INFO
"HiSax: %s detected\n",
193 (char *)ipid
->driver_data
);
194 pnp_disable_dev(pnp_d
);
195 err
= pnp_activate_dev(pnp_d
);
197 printk(KERN_WARNING
"%s: pnp_activate_dev ret(%d)\n",
201 card
->para
[1] = pnp_port_start(pnp_d
, 0);
202 card
->para
[0] = pnp_irq(pnp_d
, 0);
203 if (!card
->para
[0] || !card
->para
[1]) {
204 printk(KERN_ERR
"HFC PnP:some resources are missing %ld/%lx\n",
205 card
->para
[0], card
->para
[1]);
206 pnp_disable_dev(pnp_d
);
211 printk(KERN_ERR
"HFC PnP: PnP error card found, no device\n");
217 if (!ipid
->card_vendor
) {
218 printk(KERN_INFO
"HFC PnP: no ISAPnP card found\n");
223 cs
->hw
.hfcD
.addr
= card
->para
[1] & 0xfffe;
224 cs
->irq
= card
->para
[0];
226 cs
->hw
.hfcD
.int_s1
= 0;
227 cs
->hw
.hfcD
.send
= NULL
;
228 cs
->bcs
[0].hw
.hfc
.send
= NULL
;
229 cs
->bcs
[1].hw
.hfc
.send
= NULL
;
230 cs
->hw
.hfcD
.dfifosize
= 512;
231 cs
->dc
.hfcd
.ph_state
= 0;
232 cs
->hw
.hfcD
.fifo
= 255;
233 if (cs
->typ
== ISDN_CTYPE_TELES3C
) {
234 cs
->hw
.hfcD
.bfifosize
= 1024 + 512;
235 } else if (cs
->typ
== ISDN_CTYPE_ACERP10
) {
236 cs
->hw
.hfcD
.bfifosize
= 7*1024 + 512;
239 if (!request_region(cs
->hw
.hfcD
.addr
, 2, "HFCS isdn")) {
241 "HiSax: %s config port %x-%x already in use\n",
244 cs
->hw
.hfcD
.addr
+ 2);
248 "HFCS: defined at 0x%x IRQ %d HZ %d\n",
251 if (cs
->typ
== ISDN_CTYPE_TELES3C
) {
252 /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
253 outb(0x00, cs
->hw
.hfcD
.addr
);
254 outb(0x56, cs
->hw
.hfcD
.addr
| 1);
255 } else if (cs
->typ
== ISDN_CTYPE_ACERP10
) {
256 /* Acer P10 IO ADR is 0x300 */
257 outb(0x00, cs
->hw
.hfcD
.addr
);
258 outb(0x57, cs
->hw
.hfcD
.addr
| 1);
261 cs
->hw
.hfcD
.timer
.function
= (void *) hfcs_Timer
;
262 cs
->hw
.hfcD
.timer
.data
= (long) cs
;
263 init_timer(&cs
->hw
.hfcD
.timer
);
264 cs
->cardmsg
= &hfcs_card_msg
;
265 cs
->irq_func
= &hfcs_interrupt
;