Import 2.3.10pre5
[davej-history.git] / drivers / isdn / hisax / teleint.c
blobb37aded8921e9b76607185d8b7ac800e9844638e
1 /* $Id: teleint.c,v 1.7 1998/11/15 23:55:26 keil Exp $
3 * teleint.c low level stuff for TeleInt isdn cards
5 * Author Karsten Keil (keil@isdn4linux.de)
8 * $Log: teleint.c,v $
9 * Revision 1.7 1998/11/15 23:55:26 keil
10 * changes from 2.0
12 * Revision 1.6 1998/04/15 16:45:31 keil
13 * new init code
15 * Revision 1.5 1998/02/02 13:40:47 keil
16 * fast io
18 * Revision 1.4 1997/11/08 21:35:53 keil
19 * new l1 init
21 * Revision 1.3 1997/11/06 17:09:30 keil
22 * New 2.1 init code
24 * Revision 1.2 1997/10/29 18:55:53 keil
25 * changes for 2.1.60 (irq2dev_map)
27 * Revision 1.1 1997/09/11 17:32:32 keil
28 * new
33 #define __NO_VERSION__
34 #include "hisax.h"
35 #include "isac.h"
36 #include "hfc_2bs0.h"
37 #include "isdnl1.h"
39 extern const char *CardType[];
41 const char *TeleInt_revision = "$Revision: 1.7 $";
43 #define byteout(addr,val) outb(val,addr)
44 #define bytein(addr) inb(addr)
46 static inline u_char
47 readreg(unsigned int ale, unsigned int adr, u_char off)
49 register u_char ret;
50 int max_delay = 2000;
51 long flags;
53 save_flags(flags);
54 cli();
55 byteout(ale, off);
56 ret = HFC_BUSY & bytein(ale);
57 while (ret && --max_delay)
58 ret = HFC_BUSY & bytein(ale);
59 if (!max_delay) {
60 printk(KERN_WARNING "TeleInt Busy not inaktive\n");
61 restore_flags(flags);
62 return (0);
64 ret = bytein(adr);
65 restore_flags(flags);
66 return (ret);
69 static inline void
70 readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
72 register u_char ret;
73 register int max_delay = 20000;
74 register int i;
76 byteout(ale, off);
77 for (i = 0; i<size; i++) {
78 ret = HFC_BUSY & bytein(ale);
79 while (ret && --max_delay)
80 ret = HFC_BUSY & bytein(ale);
81 if (!max_delay) {
82 printk(KERN_WARNING "TeleInt Busy not inaktive\n");
83 return;
85 data[i] = bytein(adr);
90 static inline void
91 writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
93 register u_char ret;
94 int max_delay = 2000;
95 long flags;
97 save_flags(flags);
98 cli();
99 byteout(ale, off);
100 ret = HFC_BUSY & bytein(ale);
101 while (ret && --max_delay)
102 ret = HFC_BUSY & bytein(ale);
103 if (!max_delay) {
104 printk(KERN_WARNING "TeleInt Busy not inaktive\n");
105 restore_flags(flags);
106 return;
108 byteout(adr, data);
109 restore_flags(flags);
112 static inline void
113 writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
115 register u_char ret;
116 register int max_delay = 20000;
117 register int i;
119 /* fifo write without cli because it's allready done */
120 byteout(ale, off);
121 for (i = 0; i<size; i++) {
122 ret = HFC_BUSY & bytein(ale);
123 while (ret && --max_delay)
124 ret = HFC_BUSY & bytein(ale);
125 if (!max_delay) {
126 printk(KERN_WARNING "TeleInt Busy not inaktive\n");
127 return;
129 byteout(adr, data[i]);
133 /* Interface functions */
135 static u_char
136 ReadISAC(struct IsdnCardState *cs, u_char offset)
138 cs->hw.hfc.cip = offset;
139 return (readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset));
142 static void
143 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
145 cs->hw.hfc.cip = offset;
146 writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset, value);
149 static void
150 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
152 cs->hw.hfc.cip = 0;
153 readfifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size);
156 static void
157 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
159 cs->hw.hfc.cip = 0;
160 writefifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size);
163 static u_char
164 ReadHFC(struct IsdnCardState *cs, int data, u_char reg)
166 register u_char ret;
168 if (data) {
169 cs->hw.hfc.cip = reg;
170 byteout(cs->hw.hfc.addr | 1, reg);
171 ret = bytein(cs->hw.hfc.addr);
172 if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
173 debugl1(cs, "hfc RD %02x %02x", reg, ret);
174 } else
175 ret = bytein(cs->hw.hfc.addr | 1);
176 return (ret);
179 static void
180 WriteHFC(struct IsdnCardState *cs, int data, u_char reg, u_char value)
182 byteout(cs->hw.hfc.addr | 1, reg);
183 cs->hw.hfc.cip = reg;
184 if (data)
185 byteout(cs->hw.hfc.addr, value);
186 if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
187 debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
190 static void
191 TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs)
193 struct IsdnCardState *cs = dev_id;
194 u_char val, stat = 0;
196 if (!cs) {
197 printk(KERN_WARNING "TeleInt: Spurious interrupt!\n");
198 return;
200 val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
201 Start_ISAC:
202 if (val) {
203 isac_interrupt(cs, val);
204 stat |= 2;
206 val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
207 if (val) {
208 if (cs->debug & L1_DEB_ISAC)
209 debugl1(cs, "ISAC IntStat after IntRoutine");
210 goto Start_ISAC;
212 if (stat & 2) {
213 writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
214 writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
218 static void
219 TeleInt_Timer(struct IsdnCardState *cs)
221 int stat = 0;
223 if (cs->bcs[0].mode) {
224 stat |= 1;
225 main_irq_hfc(&cs->bcs[0]);
227 if (cs->bcs[1].mode) {
228 stat |= 2;
229 main_irq_hfc(&cs->bcs[1]);
231 cs->hw.hfc.timer.expires = jiffies + 1;
232 add_timer(&cs->hw.hfc.timer);
235 void
236 release_io_TeleInt(struct IsdnCardState *cs)
238 del_timer(&cs->hw.hfc.timer);
239 releasehfc(cs);
240 if (cs->hw.hfc.addr)
241 release_region(cs->hw.hfc.addr, 2);
244 static void
245 reset_TeleInt(struct IsdnCardState *cs)
247 long flags;
249 printk(KERN_INFO "TeleInt: resetting card\n");
250 cs->hw.hfc.cirm |= HFC_RESET;
251 byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset On */
252 save_flags(flags);
253 sti();
254 current->state = TASK_INTERRUPTIBLE;
255 schedule_timeout(3);
256 cs->hw.hfc.cirm &= ~HFC_RESET;
257 byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */
258 current->state = TASK_INTERRUPTIBLE;
259 schedule_timeout(1);
260 restore_flags(flags);
263 static int
264 TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
266 switch (mt) {
267 case CARD_RESET:
268 reset_TeleInt(cs);
269 return(0);
270 case CARD_RELEASE:
271 release_io_TeleInt(cs);
272 return(0);
273 case CARD_SETIRQ:
274 return(request_irq(cs->irq, &TeleInt_interrupt,
275 I4L_IRQ_FLAG, "HiSax", cs));
276 case CARD_INIT:
277 inithfc(cs);
278 clear_pending_isac_ints(cs);
279 initisac(cs);
280 /* Reenable all IRQ */
281 cs->writeisac(cs, ISAC_MASK, 0);
282 cs->writeisac(cs, ISAC_CMDR, 0x41);
283 cs->hw.hfc.timer.expires = jiffies + 1;
284 add_timer(&cs->hw.hfc.timer);
285 return(0);
286 case CARD_TEST:
287 return(0);
289 return(0);
292 int __init
293 setup_TeleInt(struct IsdnCard *card)
295 struct IsdnCardState *cs = card->cs;
296 char tmp[64];
298 strcpy(tmp, TeleInt_revision);
299 printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
300 if (cs->typ != ISDN_CTYPE_TELEINT)
301 return (0);
303 cs->hw.hfc.addr = card->para[1] & 0x3fe;
304 cs->irq = card->para[0];
305 cs->hw.hfc.cirm = HFC_CIRM;
306 cs->hw.hfc.isac_spcr = 0x00;
307 cs->hw.hfc.cip = 0;
308 cs->hw.hfc.ctmt = HFC_CTMT | HFC_CLTIMER;
309 cs->bcs[0].hw.hfc.send = NULL;
310 cs->bcs[1].hw.hfc.send = NULL;
311 cs->hw.hfc.fifosize = 7 * 1024 + 512;
312 cs->hw.hfc.timer.function = (void *) TeleInt_Timer;
313 cs->hw.hfc.timer.data = (long) cs;
314 init_timer(&cs->hw.hfc.timer);
315 if (check_region((cs->hw.hfc.addr), 2)) {
316 printk(KERN_WARNING
317 "HiSax: %s config port %x-%x already in use\n",
318 CardType[card->typ],
319 cs->hw.hfc.addr,
320 cs->hw.hfc.addr + 2);
321 return (0);
322 } else {
323 request_region(cs->hw.hfc.addr, 2, "TeleInt isdn");
325 /* HW IO = IO */
326 byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
327 byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54);
328 switch (cs->irq) {
329 case 3:
330 cs->hw.hfc.cirm |= HFC_INTA;
331 break;
332 case 4:
333 cs->hw.hfc.cirm |= HFC_INTB;
334 break;
335 case 5:
336 cs->hw.hfc.cirm |= HFC_INTC;
337 break;
338 case 7:
339 cs->hw.hfc.cirm |= HFC_INTD;
340 break;
341 case 10:
342 cs->hw.hfc.cirm |= HFC_INTE;
343 break;
344 case 11:
345 cs->hw.hfc.cirm |= HFC_INTF;
346 break;
347 default:
348 printk(KERN_WARNING "TeleInt: wrong IRQ\n");
349 release_io_TeleInt(cs);
350 return (0);
352 byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
353 byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
355 printk(KERN_INFO
356 "TeleInt: defined at 0x%x IRQ %d\n",
357 cs->hw.hfc.addr,
358 cs->irq);
360 reset_TeleInt(cs);
361 cs->readisac = &ReadISAC;
362 cs->writeisac = &WriteISAC;
363 cs->readisacfifo = &ReadISACfifo;
364 cs->writeisacfifo = &WriteISACfifo;
365 cs->BC_Read_Reg = &ReadHFC;
366 cs->BC_Write_Reg = &WriteHFC;
367 cs->cardmsg = &TeleInt_card_msg;
368 ISACVersion(cs, "TeleInt:");
369 return (1);