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