Merge with Linu 2.4.0-test6-pre6.
[linux-2.6/linux-mips.git] / drivers / isdn / hisax / hfcscard.c
blob18993bf0d89e3a6d2fd82797b2454764174f6c97
1 /* $Id: hfcscard.c,v 1.7 2000/06/26 08:59:13 keil Exp $
3 * hfcscard.c low level stuff for hfcs based cards (Teles3c, ACER P10)
5 * Author Karsten Keil (keil@isdn4linux.de)
7 * This file is (c) under GNU PUBLIC LICENSE
9 */
11 #define __NO_VERSION__
12 #include "hisax.h"
13 #include "hfc_2bds0.h"
14 #include "isdnl1.h"
16 extern const char *CardType[];
18 static const char *hfcs_revision = "$Revision: 1.7 $";
20 static void
21 hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
23 struct IsdnCardState *cs = dev_id;
24 u_char val, stat;
26 if (!cs) {
27 printk(KERN_WARNING "HFCS: Spurious interrupt!\n");
28 return;
30 if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) &
31 (stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
32 val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
33 if (cs->debug & L1_DEB_ISAC)
34 debugl1(cs, "HFCS: stat(%02x) s1(%02x)", stat, val);
35 hfc2bds0_interrupt(cs, val);
36 } else {
37 if (cs->debug & L1_DEB_ISAC)
38 debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat);
42 static void
43 hfcs_Timer(struct IsdnCardState *cs)
45 cs->hw.hfcD.timer.expires = jiffies + 75;
46 /* WD RESET */
47 /* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
48 add_timer(&cs->hw.hfcD.timer);
52 void
53 release_io_hfcs(struct IsdnCardState *cs)
55 release2bds0(cs);
56 del_timer(&cs->hw.hfcD.timer);
57 if (cs->hw.hfcD.addr)
58 release_region(cs->hw.hfcD.addr, 2);
61 static void
62 reset_hfcs(struct IsdnCardState *cs)
64 long flags;
66 printk(KERN_INFO "HFCS: resetting card\n");
67 cs->hw.hfcD.cirm = HFCD_RESET;
68 if (cs->typ == ISDN_CTYPE_TELES3C)
69 cs->hw.hfcD.cirm |= HFCD_MEM8K;
70 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */
71 save_flags(flags);
72 sti();
73 set_current_state(TASK_UNINTERRUPTIBLE);
74 schedule_timeout((30*HZ)/1000);
75 cs->hw.hfcD.cirm = 0;
76 if (cs->typ == ISDN_CTYPE_TELES3C)
77 cs->hw.hfcD.cirm |= HFCD_MEM8K;
78 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */
79 set_current_state(TASK_UNINTERRUPTIBLE);
80 schedule_timeout((10*HZ)/1000);
81 if (cs->typ == ISDN_CTYPE_TELES3C)
82 cs->hw.hfcD.cirm |= HFCD_INTB;
83 else if (cs->typ == ISDN_CTYPE_ACERP10)
84 cs->hw.hfcD.cirm |= HFCD_INTA;
85 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);
86 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e);
87 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */
88 cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER;
89 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
90 cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE;
91 cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS |
92 HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC |
93 HFCD_INTS_DREC | HFCD_INTS_L1STATE;
94 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1);
95 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2);
96 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */
97 udelay(10);
98 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */
99 cs->hw.hfcD.mst_m = HFCD_MASTER;
100 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */
101 cs->hw.hfcD.sctrl = 0;
102 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl);
103 restore_flags(flags);
106 static int
107 hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
109 long flags;
111 if (cs->debug & L1_DEB_ISAC)
112 debugl1(cs, "HFCS: card_msg %x", mt);
113 switch (mt) {
114 case CARD_RESET:
115 reset_hfcs(cs);
116 return(0);
117 case CARD_RELEASE:
118 release_io_hfcs(cs);
119 return(0);
120 case CARD_INIT:
121 cs->hw.hfcD.timer.expires = jiffies + 75;
122 add_timer(&cs->hw.hfcD.timer);
123 init2bds0(cs);
124 save_flags(flags);
125 sti();
126 set_current_state(TASK_UNINTERRUPTIBLE);
127 schedule_timeout((80*HZ)/1000);
128 cs->hw.hfcD.ctmt |= HFCD_TIM800;
129 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
130 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
131 restore_flags(flags);
132 return(0);
133 case CARD_TEST:
134 return(0);
136 return(0);
139 __initfunc(int
140 setup_hfcs(struct IsdnCard *card))
142 struct IsdnCardState *cs = card->cs;
143 char tmp[64];
145 strcpy(tmp, hfcs_revision);
146 printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
147 cs->hw.hfcD.addr = card->para[1] & 0xfffe;
148 cs->irq = card->para[0];
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;
157 if (cs->typ == ISDN_CTYPE_TELES3C) {
158 cs->hw.hfcD.bfifosize = 1024 + 512;
159 } else if (cs->typ == ISDN_CTYPE_ACERP10) {
160 cs->hw.hfcD.bfifosize = 7*1024 + 512;
161 } else
162 return (0);
163 if (check_region((cs->hw.hfcD.addr), 2)) {
164 printk(KERN_WARNING
165 "HiSax: %s config port %x-%x already in use\n",
166 CardType[card->typ],
167 cs->hw.hfcD.addr,
168 cs->hw.hfcD.addr + 2);
169 return (0);
170 } else {
171 request_region(cs->hw.hfcD.addr, 2, "HFCS isdn");
173 printk(KERN_INFO
174 "HFCS: defined at 0x%x IRQ %d HZ %d\n",
175 cs->hw.hfcD.addr,
176 cs->irq, HZ);
177 if (cs->typ == ISDN_CTYPE_TELES3C) {
178 /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
179 outb(0x00, cs->hw.hfcD.addr);
180 outb(0x56, cs->hw.hfcD.addr | 1);
181 } else if (cs->typ == ISDN_CTYPE_ACERP10) {
182 /* Acer P10 IO ADR is 0x300 */
183 outb(0x00, cs->hw.hfcD.addr);
184 outb(0x57, cs->hw.hfcD.addr | 1);
186 set_cs_func(cs);
187 cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
188 cs->hw.hfcD.timer.data = (long) cs;
189 init_timer(&cs->hw.hfcD.timer);
190 reset_hfcs(cs);
191 cs->cardmsg = &hfcs_card_msg;
192 cs->irq_func = &hfcs_interrupt;
193 return (1);