Fix typos.
[linux-2.6/linux-mips.git] / drivers / isdn / hisax / hfcscard.c
blob475b1616a93d7664552dcbf9bb2ef47eafb2ba1e
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)
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
7 *
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>
15 #include "hisax.h"
16 #include "hfc_2bds0.h"
17 #include "isdnl1.h"
19 extern const char *CardType[];
21 static const char *hfcs_revision = "$Revision: 1.8.6.2 $";
23 static inline u8
24 hfcs_read_reg(struct IsdnCardState *cs, int data, u8 reg)
26 return cs->bc_hw_ops->read_reg(cs, data, reg);
29 static inline void
30 hfcs_write_reg(struct IsdnCardState *cs, int data, u8 reg, u8 val)
32 cs->bc_hw_ops->write_reg(cs, data, reg, val);
35 static irqreturn_t
36 hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
38 struct IsdnCardState *cs = dev_id;
39 u8 val, stat;
41 if (!cs) {
42 printk(KERN_WARNING "HFCS: Spurious interrupt!\n");
43 return IRQ_NONE;
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);
51 } else {
52 if (cs->debug & L1_DEB_ISAC)
53 debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat);
55 return IRQ_HANDLED;
58 static void
59 hfcs_Timer(struct IsdnCardState *cs)
61 cs->hw.hfcD.timer.expires = jiffies + 75;
62 /* WD RESET */
63 /* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
64 add_timer(&cs->hw.hfcD.timer);
68 static void
69 hfcs_release(struct IsdnCardState *cs)
71 release2bds0(cs);
72 del_timer(&cs->hw.hfcD.timer);
73 hisax_release_resources(cs);
76 static int
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);
86 cs->hw.hfcD.cirm = 0;
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 */
108 udelay(10);
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);
114 return 0;
117 static void
118 hfcs_init(struct IsdnCardState *cs)
120 cs->hw.hfcD.timer.expires = jiffies + 75;
121 add_timer(&cs->hw.hfcD.timer);
122 init2bds0(cs);
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 = {
131 .init = hfcs_init,
132 .reset = hfcs_reset,
133 .release = hfcs_release,
134 .irq_func = hfcs_interrupt,
137 static int __init
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"))
144 goto err;
146 printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d\n",
147 cs->hw.hfcD.addr, cs->irq);
149 cs->hw.hfcD.cip = 0;
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);
169 set_cs_func(cs);
170 init_timer(&cs->hw.hfcD.timer);
171 cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
172 cs->hw.hfcD.timer.data = (long) cs;
173 hfcs_reset(cs);
174 cs->card_ops = &hfcs_ops;
175 return 0;
176 err:
177 hisax_release_resources(cs);
178 return -EBUSY;
181 #ifdef __ISAPNP__
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" },
204 { 0, }
207 static struct isapnp_device_id *hdev = &hfc_ids[0];
208 static struct pnp_card *pnp_c __devinitdata = NULL;
209 #endif
211 int __init
212 setup_hfcs(struct IsdnCard *card)
214 char tmp[64];
216 strcpy(tmp, hfcs_revision);
217 printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
219 #ifdef __ISAPNP__
220 if (!card->para[1] && isapnp_present()) {
221 struct pnp_card *pb;
222 struct pnp_dev *pd;
224 while(hdev->card_vendor) {
225 if ((pb = pnp_find_card(hdev->card_vendor,
226 hdev->card_device,
227 pnp_c))) {
228 pnp_c = pb;
229 pd = NULL;
230 if ((pd = pnp_find_dev(pnp_c,
231 hdev->vendor,
232 hdev->function,
233 pd))) {
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");
238 return 0;
240 if (pnp_activate_dev(pd) < 0) {
241 printk(KERN_ERR "HFC PnP: activate failed\n");
242 pnp_device_detach(pd);
243 return 0;
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);
249 return(0);
251 card->para[1] = pnp_port_start(pd, 0);
252 card->para[0] = pnp_irq(pd, 0);
253 break;
254 } else {
255 printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
258 hdev++;
259 pnp_c=NULL;
261 if (!hdev->card_vendor) {
262 printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
263 return(0);
266 #endif
267 if (hfcs_probe(card->cs, card) < 0)
268 return 0;
269 return 1;