import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / drivers / isdn / hisax / saphir.c
1 /* $Id: saphir.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
2  *
3  * low level stuff for HST Saphir 1
4  *
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.
10  *
11  * Thanks to    HST High Soft Tech GmbH
12  *
13  */
14
15 #define __NO_VERSION__
16 #include <linux/init.h>
17 #include "hisax.h"
18 #include "isac.h"
19 #include "hscx.h"
20 #include "isdnl1.h"
21
22 extern const char *CardType[];
23 static char *saphir_rev = "$Revision: 1.1.4.1 $";
24
25 #define byteout(addr,val) outb(val,addr)
26 #define bytein(addr) inb(addr)
27
28 #define ISAC_DATA       0
29 #define HSCX_DATA       1
30 #define ADDRESS_REG     2
31 #define IRQ_REG         3
32 #define SPARE_REG       4
33 #define RESET_REG       5
34
35 static inline u_char
36 readreg(unsigned int ale, unsigned int adr, u_char off)
37 {
38         register u_char ret;
39         long flags;
40
41         save_flags(flags);
42         cli();
43         byteout(ale, off);
44         ret = bytein(adr);
45         restore_flags(flags);
46         return (ret);
47 }
48
49 static inline void
50 readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
51 {
52         /* fifo read without cli because it's allready done  */
53
54         byteout(ale, off);
55         insb(adr, data, size);
56 }
57
58
59 static inline void
60 writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
61 {
62         long flags;
63
64         save_flags(flags);
65         cli();
66         byteout(ale, off);
67         byteout(adr, data);
68         restore_flags(flags);
69 }
70
71 static inline void
72 writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
73 {
74         /* fifo write without cli because it's allready done  */
75         byteout(ale, off);
76         outsb(adr, data, size);
77 }
78
79 /* Interface functions */
80
81 static u_char
82 ReadISAC(struct IsdnCardState *cs, u_char offset)
83 {
84         return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset));
85 }
86
87 static void
88 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
89 {
90         writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value);
91 }
92
93 static void
94 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
95 {
96         readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
97 }
98
99 static void
100 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
101 {
102         writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
103 }
104
105 static u_char
106 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
107 {
108         return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
109                 offset + (hscx ? 0x40 : 0)));
110 }
111
112 static void
113 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
114 {
115         writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
116                 offset + (hscx ? 0x40 : 0), value);
117 }
118
119 #define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale, \
120                 cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0))
121 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale, \
122                 cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data)
123
124 #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale, \
125                 cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
126
127 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale, \
128                 cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
129
130 #include "hscx_irq.c"
131
132 static void
133 saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs)
134 {
135         struct IsdnCardState *cs = dev_id;
136         u_char val;
137
138         if (!cs) {
139                 printk(KERN_WARNING "saphir: Spurious interrupt!\n");
140                 return;
141         }
142         val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
143       Start_HSCX:
144         if (val)
145                 hscx_int_main(cs, val);
146         val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
147       Start_ISAC:
148         if (val)
149                 isac_interrupt(cs, val);
150         val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
151         if (val) {
152                 if (cs->debug & L1_DEB_HSCX)
153                         debugl1(cs, "HSCX IntStat after IntRoutine");
154                 goto Start_HSCX;
155         }
156         val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
157         if (val) {
158                 if (cs->debug & L1_DEB_ISAC)
159                         debugl1(cs, "ISAC IntStat after IntRoutine");
160                 goto Start_ISAC;
161         }
162         /* Watchdog */
163         if (cs->hw.saphir.timer.function) 
164                 mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
165         else
166                 printk(KERN_WARNING "saphir: Spurious timer!\n");
167         writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF);
168         writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF);
169         writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF);
170         writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0);
171         writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0);
172         writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0);
173 }
174
175 static void
176 SaphirWatchDog(struct IsdnCardState *cs)
177 {
178         /* 5 sec WatchDog, so read at least every 4 sec */
179         cs->readisac(cs, ISAC_RBCH);
180         mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
181 }
182
183 void
184 release_io_saphir(struct IsdnCardState *cs)
185 {
186         long flags;
187         
188         save_flags(flags);
189         cli();
190         byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
191         del_timer(&cs->hw.saphir.timer);
192         cs->hw.saphir.timer.function = NULL;
193         restore_flags(flags);
194         if (cs->hw.saphir.cfg_reg)
195                 release_region(cs->hw.saphir.cfg_reg, 6);
196 }
197
198 static int
199 saphir_reset(struct IsdnCardState *cs)
200 {
201         long flags;
202         u_char irq_val;
203
204         switch(cs->irq) {
205                 case 5: irq_val = 0;
206                         break;
207                 case 3: irq_val = 1;
208                         break;
209                 case 11:
210                         irq_val = 2;
211                         break;
212                 case 12:
213                         irq_val = 3;
214                         break;
215                 case 15:
216                         irq_val = 4;
217                         break;
218                 default:
219                         printk(KERN_WARNING "HiSax: saphir wrong IRQ %d\n",
220                                 cs->irq);
221                         return (1);
222         }
223         byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
224         save_flags(flags);
225         sti();
226         byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1);
227         set_current_state(TASK_UNINTERRUPTIBLE);
228         schedule_timeout((30*HZ)/1000); /* Timeout 30ms */
229         byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0);
230         set_current_state(TASK_UNINTERRUPTIBLE);
231         schedule_timeout((30*HZ)/1000); /* Timeout 30ms */
232         restore_flags(flags);
233         byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
234         byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02);
235         return (0);
236 }
237
238 static int
239 saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
240 {
241         switch (mt) {
242                 case CARD_RESET:
243                         saphir_reset(cs);
244                         return(0);
245                 case CARD_RELEASE:
246                         release_io_saphir(cs);
247                         return(0);
248                 case CARD_INIT:
249                         inithscxisac(cs, 3);
250                         return(0);
251                 case CARD_TEST:
252                         return(0);
253         }
254         return(0);
255 }
256
257
258 int __init
259 setup_saphir(struct IsdnCard *card)
260 {
261         struct IsdnCardState *cs = card->cs;
262         char tmp[64];
263
264         strcpy(tmp, saphir_rev);
265         printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
266         if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
267                 return (0);
268
269         /* IO-Ports */
270         cs->hw.saphir.cfg_reg = card->para[1];
271         cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
272         cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
273         cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
274         cs->irq = card->para[0];
275         if (check_region((cs->hw.saphir.cfg_reg), 6)) {
276                 printk(KERN_WARNING
277                         "HiSax: %s config port %x-%x already in use\n",
278                         CardType[card->typ],
279                         cs->hw.saphir.cfg_reg,
280                         cs->hw.saphir.cfg_reg + 5);
281                 return (0);
282         } else
283                 request_region(cs->hw.saphir.cfg_reg,6, "saphir");
284
285         printk(KERN_INFO
286                "HiSax: %s config irq:%d io:0x%X\n",
287                CardType[cs->typ], cs->irq,
288                cs->hw.saphir.cfg_reg);
289
290         cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
291         cs->hw.saphir.timer.data = (long) cs;
292         init_timer(&cs->hw.saphir.timer);
293         cs->hw.saphir.timer.expires = jiffies + 4*HZ;
294         add_timer(&cs->hw.saphir.timer);
295         if (saphir_reset(cs)) {
296                 release_io_saphir(cs);
297                 return (0);
298         }
299         cs->readisac = &ReadISAC;
300         cs->writeisac = &WriteISAC;
301         cs->readisacfifo = &ReadISACfifo;
302         cs->writeisacfifo = &WriteISACfifo;
303         cs->BC_Read_Reg = &ReadHSCX;
304         cs->BC_Write_Reg = &WriteHSCX;
305         cs->BC_Send_Data = &hscx_fill_fifo;
306         cs->cardmsg = &saphir_card_msg;
307         cs->irq_func = &saphir_interrupt;
308         ISACVersion(cs, "saphir:");
309         if (HscxVersion(cs, "saphir:")) {
310                 printk(KERN_WARNING
311                     "saphir: wrong HSCX versions check IO address\n");
312                 release_io_saphir(cs);
313                 return (0);
314         }
315         return (1);
316 }