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