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
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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>
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)
36 readreg(struct IsdnCardState
*cs
, unsigned int adr
, u8 off
)
41 spin_lock_irqsave(&saphir_lock
, flags
);
42 byteout(cs
->hw
.saphir
.ale
, off
);
44 spin_unlock_irqrestore(&saphir_lock
, flags
);
49 writereg(struct IsdnCardState
*cs
, unsigned int adr
, u8 off
, u8 data
)
53 spin_lock_irqsave(&saphir_lock
, flags
);
54 byteout(cs
->hw
.saphir
.ale
, off
);
56 spin_unlock_irqrestore(&saphir_lock
, flags
);
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
);
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
);
74 isac_read(struct IsdnCardState
*cs
, u8 offset
)
76 return readreg(cs
, cs
->hw
.saphir
.isac
, offset
);
80 isac_write(struct IsdnCardState
*cs
, u8 offset
, u8 value
)
82 writereg(cs
, cs
->hw
.saphir
.isac
, offset
, value
);
86 isac_read_fifo(struct IsdnCardState
*cs
, u8
* data
, int size
)
88 readfifo(cs
, cs
->hw
.saphir
.isac
, 0, data
, size
);
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
,
105 hscx_read(struct IsdnCardState
*cs
, int hscx
, u8 offset
)
107 return readreg(cs
, cs
->hw
.saphir
.hscx
, offset
+ (hscx
? 0x40 : 0));
111 hscx_write(struct IsdnCardState
*cs
, int hscx
, u8 offset
, u8 value
)
113 writereg(cs
, cs
->hw
.saphir
.hscx
, offset
+ (hscx
? 0x40 : 0), value
);
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
);
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
,
136 saphir_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
138 struct IsdnCardState
*cs
= dev_id
;
141 ret
= hscxisac_irq(intno
, dev_id
, regs
);
142 mod_timer(&cs
->hw
.saphir
.timer
, jiffies
+1*HZ
);
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
);
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
);
164 saphir_reset(struct IsdnCardState
*cs
)
183 printk(KERN_WARNING
"HiSax: saphir wrong IRQ %d\n",
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);
199 static struct card_ops saphir_ops
= {
200 .init
= inithscxisac
,
201 .reset
= saphir_reset
,
202 .release
= saphir_release
,
203 .irq_func
= saphir_interrupt
,
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"))
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
))
224 cs
->card_ops
= &saphir_ops
;
225 if (hscxisac_setup(cs
, &isac_ops
, &hscx_ops
))
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
);
235 hisax_release_resources(cs
);
240 setup_saphir(struct IsdnCard
*card
)
244 strcpy(tmp
, saphir_rev
);
245 printk(KERN_INFO
"HiSax: HST Saphir driver Rev. %s\n",
248 if (saphir_probe(card
->cs
, card
) < 0)