1 /* $Id: teleint.c,v 1.13 2000/06/26 08:59:14 keil Exp $
3 * teleint.c low level stuff for TeleInt isdn cards
5 * Author Karsten Keil (keil@isdn4linux.de)
7 * This file is (c) under GNU PUBLIC LICENSE
11 #define __NO_VERSION__
17 extern const char *CardType
[];
19 const char *TeleInt_revision
= "$Revision: 1.13 $";
21 #define byteout(addr,val) outb(val,addr)
22 #define bytein(addr) inb(addr)
25 readreg(unsigned int ale
, unsigned int adr
, u_char off
)
34 ret
= HFC_BUSY
& bytein(ale
);
35 while (ret
&& --max_delay
)
36 ret
= HFC_BUSY
& bytein(ale
);
38 printk(KERN_WARNING
"TeleInt Busy not inactive\n");
48 readfifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
* data
, int size
)
51 register int max_delay
= 20000;
55 for (i
= 0; i
<size
; i
++) {
56 ret
= HFC_BUSY
& bytein(ale
);
57 while (ret
&& --max_delay
)
58 ret
= HFC_BUSY
& bytein(ale
);
60 printk(KERN_WARNING
"TeleInt Busy not inactive\n");
63 data
[i
] = bytein(adr
);
69 writereg(unsigned int ale
, unsigned int adr
, u_char off
, u_char data
)
78 ret
= HFC_BUSY
& bytein(ale
);
79 while (ret
&& --max_delay
)
80 ret
= HFC_BUSY
& bytein(ale
);
82 printk(KERN_WARNING
"TeleInt Busy not inactive\n");
91 writefifo(unsigned int ale
, unsigned int adr
, u_char off
, u_char
* data
, int size
)
94 register int max_delay
= 20000;
97 /* fifo write without cli because it's allready done */
99 for (i
= 0; i
<size
; i
++) {
100 ret
= HFC_BUSY
& bytein(ale
);
101 while (ret
&& --max_delay
)
102 ret
= HFC_BUSY
& bytein(ale
);
104 printk(KERN_WARNING
"TeleInt Busy not inactive\n");
107 byteout(adr
, data
[i
]);
111 /* Interface functions */
114 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
116 cs
->hw
.hfc
.cip
= offset
;
117 return (readreg(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.addr
, offset
));
121 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
123 cs
->hw
.hfc
.cip
= offset
;
124 writereg(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.addr
, offset
, value
);
128 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
131 readfifo(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.addr
, 0, data
, size
);
135 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
138 writefifo(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.addr
, 0, data
, size
);
142 ReadHFC(struct IsdnCardState
*cs
, int data
, u_char reg
)
147 cs
->hw
.hfc
.cip
= reg
;
148 byteout(cs
->hw
.hfc
.addr
| 1, reg
);
149 ret
= bytein(cs
->hw
.hfc
.addr
);
150 if (cs
->debug
& L1_DEB_HSCX_FIFO
&& (data
!= 2))
151 debugl1(cs
, "hfc RD %02x %02x", reg
, ret
);
153 ret
= bytein(cs
->hw
.hfc
.addr
| 1);
158 WriteHFC(struct IsdnCardState
*cs
, int data
, u_char reg
, u_char value
)
160 byteout(cs
->hw
.hfc
.addr
| 1, reg
);
161 cs
->hw
.hfc
.cip
= reg
;
163 byteout(cs
->hw
.hfc
.addr
, value
);
164 if (cs
->debug
& L1_DEB_HSCX_FIFO
&& (data
!= 2))
165 debugl1(cs
, "hfc W%c %02x %02x", data
? 'D' : 'C', reg
, value
);
169 TeleInt_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
171 struct IsdnCardState
*cs
= dev_id
;
175 printk(KERN_WARNING
"TeleInt: Spurious interrupt!\n");
178 val
= readreg(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.addr
, ISAC_ISTA
);
181 isac_interrupt(cs
, val
);
182 val
= readreg(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.addr
, ISAC_ISTA
);
184 if (cs
->debug
& L1_DEB_ISAC
)
185 debugl1(cs
, "ISAC IntStat after IntRoutine");
188 writereg(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.addr
, ISAC_MASK
, 0xFF);
189 writereg(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.addr
, ISAC_MASK
, 0x0);
193 TeleInt_Timer(struct IsdnCardState
*cs
)
197 if (cs
->bcs
[0].mode
) {
199 main_irq_hfc(&cs
->bcs
[0]);
201 if (cs
->bcs
[1].mode
) {
203 main_irq_hfc(&cs
->bcs
[1]);
205 cs
->hw
.hfc
.timer
.expires
= jiffies
+ 1;
206 add_timer(&cs
->hw
.hfc
.timer
);
210 release_io_TeleInt(struct IsdnCardState
*cs
)
212 del_timer(&cs
->hw
.hfc
.timer
);
215 release_region(cs
->hw
.hfc
.addr
, 2);
219 reset_TeleInt(struct IsdnCardState
*cs
)
223 printk(KERN_INFO
"TeleInt: resetting card\n");
224 cs
->hw
.hfc
.cirm
|= HFC_RESET
;
225 byteout(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.cirm
); /* Reset On */
228 set_current_state(TASK_UNINTERRUPTIBLE
);
229 schedule_timeout((30*HZ
)/1000);
230 cs
->hw
.hfc
.cirm
&= ~HFC_RESET
;
231 byteout(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.cirm
); /* Reset Off */
232 set_current_state(TASK_UNINTERRUPTIBLE
);
233 schedule_timeout((10*HZ
)/1000);
234 restore_flags(flags
);
238 TeleInt_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
245 release_io_TeleInt(cs
);
249 clear_pending_isac_ints(cs
);
251 /* Reenable all IRQ */
252 cs
->writeisac(cs
, ISAC_MASK
, 0);
253 cs
->writeisac(cs
, ISAC_CMDR
, 0x41);
254 cs
->hw
.hfc
.timer
.expires
= jiffies
+ 1;
255 add_timer(&cs
->hw
.hfc
.timer
);
264 setup_TeleInt(struct IsdnCard
*card
))
266 struct IsdnCardState
*cs
= card
->cs
;
269 strcpy(tmp
, TeleInt_revision
);
270 printk(KERN_INFO
"HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp
));
271 if (cs
->typ
!= ISDN_CTYPE_TELEINT
)
274 cs
->hw
.hfc
.addr
= card
->para
[1] & 0x3fe;
275 cs
->irq
= card
->para
[0];
276 cs
->hw
.hfc
.cirm
= HFC_CIRM
;
277 cs
->hw
.hfc
.isac_spcr
= 0x00;
279 cs
->hw
.hfc
.ctmt
= HFC_CTMT
| HFC_CLTIMER
;
280 cs
->bcs
[0].hw
.hfc
.send
= NULL
;
281 cs
->bcs
[1].hw
.hfc
.send
= NULL
;
282 cs
->hw
.hfc
.fifosize
= 7 * 1024 + 512;
283 cs
->hw
.hfc
.timer
.function
= (void *) TeleInt_Timer
;
284 cs
->hw
.hfc
.timer
.data
= (long) cs
;
285 init_timer(&cs
->hw
.hfc
.timer
);
286 if (check_region((cs
->hw
.hfc
.addr
), 2)) {
288 "HiSax: %s config port %x-%x already in use\n",
291 cs
->hw
.hfc
.addr
+ 2);
294 request_region(cs
->hw
.hfc
.addr
, 2, "TeleInt isdn");
297 byteout(cs
->hw
.hfc
.addr
, cs
->hw
.hfc
.addr
& 0xff);
298 byteout(cs
->hw
.hfc
.addr
| 1, ((cs
->hw
.hfc
.addr
& 0x300) >> 8) | 0x54);
301 cs
->hw
.hfc
.cirm
|= HFC_INTA
;
304 cs
->hw
.hfc
.cirm
|= HFC_INTB
;
307 cs
->hw
.hfc
.cirm
|= HFC_INTC
;
310 cs
->hw
.hfc
.cirm
|= HFC_INTD
;
313 cs
->hw
.hfc
.cirm
|= HFC_INTE
;
316 cs
->hw
.hfc
.cirm
|= HFC_INTF
;
319 printk(KERN_WARNING
"TeleInt: wrong IRQ\n");
320 release_io_TeleInt(cs
);
323 byteout(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.cirm
);
324 byteout(cs
->hw
.hfc
.addr
| 1, cs
->hw
.hfc
.ctmt
);
327 "TeleInt: defined at 0x%x IRQ %d\n",
332 cs
->readisac
= &ReadISAC
;
333 cs
->writeisac
= &WriteISAC
;
334 cs
->readisacfifo
= &ReadISACfifo
;
335 cs
->writeisacfifo
= &WriteISACfifo
;
336 cs
->BC_Read_Reg
= &ReadHFC
;
337 cs
->BC_Write_Reg
= &WriteHFC
;
338 cs
->cardmsg
= &TeleInt_card_msg
;
339 cs
->irq_func
= &TeleInt_interrupt
;
340 ISACVersion(cs
, "TeleInt:");