[PATCH] DVB: Update documentation and credits
[linux-2.6/history.git] / drivers / isdn / hisax / saphir.c
blob759ccb603b85946d4784b799fee1cdb236587869
1 /* $Id: saphir.c,v 1.8.6.2 2001/09/23 22:24:51 kai Exp $
3 * low level stuff for HST Saphir 1
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.
11 * Thanks to HST High Soft Tech GmbH
15 #include <linux/init.h>
16 #include "hisax.h"
17 #include "isac.h"
18 #include "hscx.h"
19 #include "isdnl1.h"
21 extern const char *CardType[];
22 static char *saphir_rev = "$Revision: 1.8.6.2 $";
23 static spinlock_t saphir_lock = SPIN_LOCK_UNLOCKED;
25 #define byteout(addr,val) outb(val,addr)
26 #define bytein(addr) inb(addr)
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
35 static inline u8
36 readreg(struct IsdnCardState *cs, unsigned int adr, u8 off)
38 u8 ret;
39 unsigned long flags;
41 spin_lock_irqsave(&saphir_lock, flags);
42 byteout(cs->hw.saphir.ale, off);
43 ret = bytein(adr);
44 spin_unlock_irqrestore(&saphir_lock, flags);
45 return ret;
48 static inline void
49 writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data)
51 unsigned long flags;
53 spin_lock_irqsave(&saphir_lock, flags);
54 byteout(cs->hw.saphir.ale, off);
55 byteout(adr, data);
56 spin_unlock_irqrestore(&saphir_lock, flags);
59 static inline void
60 readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 *data, int size)
62 byteout(cs->hw.saphir.ale, off);
63 insb(adr, data, size);
66 static inline void
67 writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 *data, int size)
69 byteout(cs->hw.saphir.ale, off);
70 outsb(adr, data, size);
73 static u8
74 isac_read(struct IsdnCardState *cs, u8 offset)
76 return readreg(cs, cs->hw.saphir.isac, offset);
79 static void
80 isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
82 writereg(cs, cs->hw.saphir.isac, offset, value);
85 static void
86 isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
88 readfifo(cs, cs->hw.saphir.isac, 0, data, size);
91 static void
92 isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
94 writefifo(cs, cs->hw.saphir.isac, 0, data, size);
97 static struct dc_hw_ops isac_ops = {
98 .read_reg = isac_read,
99 .write_reg = isac_write,
100 .read_fifo = isac_read_fifo,
101 .write_fifo = isac_write_fifo,
104 static u8
105 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
107 return readreg(cs, cs->hw.saphir.hscx, offset + (hscx ? 0x40 : 0));
110 static void
111 hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
113 writereg(cs, cs->hw.saphir.hscx, offset + (hscx ? 0x40 : 0), value);
116 static void
117 hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
119 readfifo(cs, cs->hw.saphir.hscx, hscx ? 0x40 : 0, data, size);
122 static void
123 hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
125 writefifo(cs, cs->hw.saphir.hscx, hscx ? 0x40 : 0, data, size);
128 static struct bc_hw_ops hscx_ops = {
129 .read_reg = hscx_read,
130 .write_reg = hscx_write,
131 .read_fifo = hscx_read_fifo,
132 .write_fifo = hscx_write_fifo,
135 static irqreturn_t
136 saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs)
138 struct IsdnCardState *cs = dev_id;
139 irqreturn_t ret;
141 ret = hscxisac_irq(intno, dev_id, regs);
142 mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
143 return ret;
146 static void
147 SaphirWatchDog(struct IsdnCardState *cs)
149 /* 5 sec WatchDog, so read at least every 4 sec */
150 isac_read(cs, ISAC_RBCH);
151 mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
154 static void
155 saphir_release(struct IsdnCardState *cs)
157 byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
158 del_timer_sync(&cs->hw.saphir.timer);
159 cs->hw.saphir.timer.function = NULL;
160 hisax_release_resources(cs);
163 static int
164 saphir_reset(struct IsdnCardState *cs)
166 u8 irq_val;
168 switch(cs->irq) {
169 case 5: irq_val = 0;
170 break;
171 case 3: irq_val = 1;
172 break;
173 case 11:
174 irq_val = 2;
175 break;
176 case 12:
177 irq_val = 3;
178 break;
179 case 15:
180 irq_val = 4;
181 break;
182 default:
183 printk(KERN_WARNING "HiSax: saphir wrong IRQ %d\n",
184 cs->irq);
185 return (1);
187 byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
188 byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1);
189 set_current_state(TASK_UNINTERRUPTIBLE);
190 schedule_timeout((30*HZ)/1000); /* Timeout 30ms */
191 byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0);
192 set_current_state(TASK_UNINTERRUPTIBLE);
193 schedule_timeout((30*HZ)/1000); /* Timeout 30ms */
194 byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
195 byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02);
196 return (0);
199 static struct card_ops saphir_ops = {
200 .init = inithscxisac,
201 .reset = saphir_reset,
202 .release = saphir_release,
203 .irq_func = saphir_interrupt,
206 static int __init
207 saphir_probe(struct IsdnCardState *cs, struct IsdnCard *card)
209 cs->hw.saphir.cfg_reg = card->para[1];
210 cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
211 cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
212 cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
213 cs->irq = card->para[0];
215 if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir"))
216 goto err;
218 printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
219 CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg);
221 if (saphir_reset(cs))
222 goto err;
224 cs->card_ops = &saphir_ops;
225 if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
226 goto err;
228 init_timer(&cs->hw.saphir.timer);
229 cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
230 cs->hw.saphir.timer.data = (long) cs;
231 cs->hw.saphir.timer.expires = jiffies + 4*HZ;
232 add_timer(&cs->hw.saphir.timer);
233 return 0;
234 err:
235 hisax_release_resources(cs);
236 return -EBUSY;
239 int __init
240 setup_saphir(struct IsdnCard *card)
242 char tmp[64];
244 strcpy(tmp, saphir_rev);
245 printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n",
246 HiSax_getrev(tmp));
248 if (saphir_probe(card->cs, card) < 0)
249 return 0;
250 return 1;