1 /* $Id: hfcscard.c,v 1.8.6.2 2001/09/23 22:24:48 kai 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.8.6.2 $";
24 hfcs_read_reg(struct IsdnCardState
*cs
, int data
, u8 reg
)
26 return cs
->bc_hw_ops
->read_reg(cs
, data
, reg
);
30 hfcs_write_reg(struct IsdnCardState
*cs
, int data
, u8 reg
, u8 val
)
32 cs
->bc_hw_ops
->write_reg(cs
, data
, reg
, val
);
36 hfcs_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
38 struct IsdnCardState
*cs
= dev_id
;
42 printk(KERN_WARNING
"HFCS: Spurious interrupt!\n");
45 if ((HFCD_ANYINT
| HFCD_BUSY_NBUSY
) &
46 (stat
= hfcs_read_reg(cs
, HFCD_DATA
, HFCD_STAT
))) {
47 val
= hfcs_read_reg(cs
, HFCD_DATA
, HFCD_INT_S1
);
48 if (cs
->debug
& L1_DEB_ISAC
)
49 debugl1(cs
, "HFCS: stat(%02x) s1(%02x)", stat
, val
);
50 hfc2bds0_interrupt(cs
, val
);
52 if (cs
->debug
& L1_DEB_ISAC
)
53 debugl1(cs
, "HFCS: irq_no_irq stat(%02x)", stat
);
59 hfcs_Timer(struct IsdnCardState
*cs
)
61 cs
->hw
.hfcD
.timer
.expires
= jiffies
+ 75;
63 /* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
64 add_timer(&cs->hw.hfcD.timer);
69 hfcs_release(struct IsdnCardState
*cs
)
72 del_timer(&cs
->hw
.hfcD
.timer
);
73 hisax_release_resources(cs
);
77 hfcs_reset(struct IsdnCardState
*cs
)
79 printk(KERN_INFO
"HFCS: resetting card\n");
80 cs
->hw
.hfcD
.cirm
= HFCD_RESET
;
81 if (cs
->typ
== ISDN_CTYPE_TELES3C
)
82 cs
->hw
.hfcD
.cirm
|= HFCD_MEM8K
;
83 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_CIRM
, cs
->hw
.hfcD
.cirm
); /* Reset On */
84 set_current_state(TASK_UNINTERRUPTIBLE
);
85 schedule_timeout((30*HZ
)/1000);
87 if (cs
->typ
== ISDN_CTYPE_TELES3C
)
88 cs
->hw
.hfcD
.cirm
|= HFCD_MEM8K
;
89 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_CIRM
, cs
->hw
.hfcD
.cirm
); /* Reset Off */
90 set_current_state(TASK_UNINTERRUPTIBLE
);
91 schedule_timeout((10*HZ
)/1000);
92 if (cs
->typ
== ISDN_CTYPE_TELES3C
)
93 cs
->hw
.hfcD
.cirm
|= HFCD_INTB
;
94 else if (cs
->typ
== ISDN_CTYPE_ACERP10
)
95 cs
->hw
.hfcD
.cirm
|= HFCD_INTA
;
96 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_CIRM
, cs
->hw
.hfcD
.cirm
);
97 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_CLKDEL
, 0x0e);
98 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_TEST
, HFCD_AUTO_AWAKE
); /* S/T Auto awake */
99 cs
->hw
.hfcD
.ctmt
= HFCD_TIM25
| HFCD_AUTO_TIMER
;
100 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_CTMT
, cs
->hw
.hfcD
.ctmt
);
101 cs
->hw
.hfcD
.int_m2
= HFCD_IRQ_ENABLE
;
102 cs
->hw
.hfcD
.int_m1
= HFCD_INTS_B1TRANS
| HFCD_INTS_B2TRANS
|
103 HFCD_INTS_DTRANS
| HFCD_INTS_B1REC
| HFCD_INTS_B2REC
|
104 HFCD_INTS_DREC
| HFCD_INTS_L1STATE
;
105 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_INT_M1
, cs
->hw
.hfcD
.int_m1
);
106 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_INT_M2
, cs
->hw
.hfcD
.int_m2
);
107 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_STATES
, HFCD_LOAD_STATE
| 2); /* HFC ST 2 */
109 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_STATES
, 2); /* HFC ST 2 */
110 cs
->hw
.hfcD
.mst_m
= HFCD_MASTER
;
111 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_MST_MODE
, cs
->hw
.hfcD
.mst_m
); /* HFC Master */
112 cs
->hw
.hfcD
.sctrl
= 0;
113 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_SCTRL
, cs
->hw
.hfcD
.sctrl
);
118 hfcs_init(struct IsdnCardState
*cs
)
120 cs
->hw
.hfcD
.timer
.expires
= jiffies
+ 75;
121 add_timer(&cs
->hw
.hfcD
.timer
);
123 set_current_state(TASK_UNINTERRUPTIBLE
);
124 schedule_timeout((80*HZ
)/1000);
125 cs
->hw
.hfcD
.ctmt
|= HFCD_TIM800
;
126 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_CTMT
, cs
->hw
.hfcD
.ctmt
);
127 hfcs_write_reg(cs
, HFCD_DATA
, HFCD_MST_MODE
, cs
->hw
.hfcD
.mst_m
);
130 static struct card_ops hfcs_ops
= {
133 .release
= hfcs_release
,
134 .irq_func
= hfcs_interrupt
,
138 hfcs_probe(struct IsdnCardState
*cs
, struct IsdnCard
*card
)
140 cs
->irq
= card
->para
[0];
141 cs
->hw
.hfcD
.addr
= card
->para
[1];
143 if (!request_io(&cs
->rs
, cs
->hw
.hfcD
.addr
, 2, "HFCS isdn"))
146 printk(KERN_INFO
"HFCS: defined at 0x%x IRQ %d\n",
147 cs
->hw
.hfcD
.addr
, cs
->irq
);
150 cs
->hw
.hfcD
.int_s1
= 0;
151 cs
->hw
.hfcD
.send
= NULL
;
152 cs
->bcs
[0].hw
.hfc
.send
= NULL
;
153 cs
->bcs
[1].hw
.hfc
.send
= NULL
;
154 cs
->hw
.hfcD
.dfifosize
= 512;
155 cs
->dc
.hfcd
.ph_state
= 0;
156 cs
->hw
.hfcD
.fifo
= 255;
158 if (cs
->typ
== ISDN_CTYPE_TELES3C
) {
159 cs
->hw
.hfcD
.bfifosize
= 1024 + 512;
160 /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
161 outb(0x00, cs
->hw
.hfcD
.addr
);
162 outb(0x56, cs
->hw
.hfcD
.addr
| 1);
163 } else if (cs
->typ
== ISDN_CTYPE_ACERP10
) {
164 cs
->hw
.hfcD
.bfifosize
= 7*1024 + 512;
165 /* Acer P10 IO ADR is 0x300 */
166 outb(0x00, cs
->hw
.hfcD
.addr
);
167 outb(0x57, cs
->hw
.hfcD
.addr
| 1);
170 init_timer(&cs
->hw
.hfcD
.timer
);
171 cs
->hw
.hfcD
.timer
.function
= (void *) hfcs_Timer
;
172 cs
->hw
.hfcD
.timer
.data
= (long) cs
;
174 cs
->card_ops
= &hfcs_ops
;
177 hisax_release_resources(cs
);
182 static struct isapnp_device_id hfc_ids
[] __initdata
= {
183 { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
184 ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
185 (unsigned long) "Acer P10" },
186 { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
187 ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
188 (unsigned long) "Billion 2" },
189 { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
190 ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
191 (unsigned long) "Billion 1" },
192 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
193 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
194 (unsigned long) "IStar PnP" },
195 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
196 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
197 (unsigned long) "Teles 16.3c" },
198 { ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
199 ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
200 (unsigned long) "Tornado Tipa C" },
201 { ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
202 ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
203 (unsigned long) "Genius Speed Surfer" },
207 static struct isapnp_device_id
*hdev
= &hfc_ids
[0];
208 static struct pnp_card
*pnp_c __devinitdata
= NULL
;
212 setup_hfcs(struct IsdnCard
*card
)
216 strcpy(tmp
, hfcs_revision
);
217 printk(KERN_INFO
"HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp
));
220 if (!card
->para
[1] && isapnp_present()) {
224 while(hdev
->card_vendor
) {
225 if ((pb
= pnp_find_card(hdev
->card_vendor
,
230 if ((pd
= pnp_find_dev(pnp_c
,
234 printk(KERN_INFO
"HiSax: %s detected\n",
235 (char *)hdev
->driver_data
);
236 if (pnp_device_attach(pd
) < 0) {
237 printk(KERN_ERR
"HFC PnP: attach failed\n");
240 if (pnp_activate_dev(pd
) < 0) {
241 printk(KERN_ERR
"HFC PnP: activate failed\n");
242 pnp_device_detach(pd
);
245 if (!pnp_irq_valid(pd
, 0) || !pnp_port_valid(pd
, 0)) {
246 printk(KERN_ERR
"HFC PnP:some resources are missing %ld/%lx\n",
247 pnp_irq(pd
, 0), pnp_port_start(pd
, 0));
248 pnp_device_detach(pd
);
251 card
->para
[1] = pnp_port_start(pd
, 0);
252 card
->para
[0] = pnp_irq(pd
, 0);
255 printk(KERN_ERR
"HFC PnP: PnP error card found, no device\n");
261 if (!hdev
->card_vendor
) {
262 printk(KERN_INFO
"HFC PnP: no ISAPnP card found\n");
267 if (hfcs_probe(card
->cs
, card
) < 0)