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
readreg(unsigned int ale,unsigned int adr,u_char off)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
readfifo(unsigned int ale,unsigned int adr,u_char off,u_char * data,int size)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
writereg(unsigned int ale,unsigned int adr,u_char off,u_char data)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
writefifo(unsigned int ale,unsigned int adr,u_char off,u_char * data,int size)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
ReadISAC(struct IsdnCardState * cs,u_char offset)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
WriteISAC(struct IsdnCardState * cs,u_char offset,u_char value)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
ReadISACfifo(struct IsdnCardState * cs,u_char * data,int size)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
WriteISACfifo(struct IsdnCardState * cs,u_char * data,int size)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
ReadHSCX(struct IsdnCardState * cs,int hscx,u_char offset)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
WriteHSCX(struct IsdnCardState * cs,int hscx,u_char offset,u_char value)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
saphir_interrupt(int intno,void * dev_id,struct pt_regs * regs)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
SaphirWatchDog(struct IsdnCardState * cs)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
release_io_saphir(struct IsdnCardState * cs)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
saphir_reset(struct IsdnCardState * cs)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
saphir_card_msg(struct IsdnCardState * cs,int mt,void * arg)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
setup_saphir(struct IsdnCard * card)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 }
317