1 /* $Id: isurf.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
3 * low level stuff for Siemens I-Surf/I-Talk cards
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.
13 #define __NO_VERSION__
14 #include <linux/init.h>
19 #include <linux/isapnp.h>
21 extern const char *CardType[];
23 static const char *ISurf_revision = "$Revision: 1.1.4.1 $";
25 #define byteout(addr,val) outb(val,addr)
26 #define bytein(addr) inb(addr)
28 #define ISURF_ISAR_RESET 1
29 #define ISURF_ISAC_RESET 2
30 #define ISURF_ISAR_EA 4
31 #define ISURF_ARCOFI_RESET 8
32 #define ISURF_RESET (ISURF_ISAR_RESET | ISURF_ISAC_RESET | ISURF_ARCOFI_RESET)
34 #define ISURF_ISAR_OFFSET 0
35 #define ISURF_ISAC_OFFSET 0x100
36 #define ISURF_IOMEM_SIZE 0x400
37 /* Interface functions */
40 ReadISAC(struct IsdnCardState *cs, u_char offset)
42 return (readb(cs->hw.isurf.isac + offset));
46 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
48 writeb(value, cs->hw.isurf.isac + offset); mb();
52 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
55 for (i = 0; i < size; i++)
56 data[i] = readb(cs->hw.isurf.isac);
60 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
63 for (i = 0; i < size; i++){
64 writeb(data[i], cs->hw.isurf.isac);mb();
68 /* ISAR access routines
69 * mode = 0 access with IRQ on
70 * mode = 1 access with IRQ off
71 * mode = 2 access with IRQ off and using last offset
75 ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
77 return(readb(cs->hw.isurf.isar + offset));
81 WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
83 writeb(value, cs->hw.isurf.isar + offset);mb();
87 isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs)
89 struct IsdnCardState *cs = dev_id;
94 printk(KERN_WARNING "ISurf: Spurious interrupt!\n");
98 val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
100 if (val & ISAR_IRQSTA)
102 val = readb(cs->hw.isurf.isac + ISAC_ISTA);
105 isac_interrupt(cs, val);
106 val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
107 if ((val & ISAR_IRQSTA) && --cnt) {
108 if (cs->debug & L1_DEB_HSCX)
109 debugl1(cs, "ISAR IntStat after IntRoutine");
112 val = readb(cs->hw.isurf.isac + ISAC_ISTA);
114 if (cs->debug & L1_DEB_ISAC)
115 debugl1(cs, "ISAC IntStat after IntRoutine");
119 printk(KERN_WARNING "ISurf IRQ LOOP\n");
121 writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
122 writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb();
123 writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb();
124 writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
128 release_io_isurf(struct IsdnCardState *cs)
130 release_region(cs->hw.isurf.reset, 1);
131 iounmap((unsigned char *)cs->hw.isurf.isar);
132 release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
136 reset_isurf(struct IsdnCardState *cs, u_char chips)
140 printk(KERN_INFO "ISurf: resetting card\n");
142 byteout(cs->hw.isurf.reset, chips); /* Reset On */
145 set_current_state(TASK_UNINTERRUPTIBLE);
146 schedule_timeout((10*HZ)/1000);
147 byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */
148 set_current_state(TASK_UNINTERRUPTIBLE);
149 schedule_timeout((10*HZ)/1000);
150 restore_flags(flags);
154 ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg)
158 reset_isurf(cs, ISURF_RESET);
161 release_io_isurf(cs);
164 clear_pending_isac_ints(cs);
165 writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb();
168 /* Reenable ISAC IRQ */
169 cs->writeisac(cs, ISAC_MASK, 0);
170 /* RESET Receiver and Transmitter */
171 cs->writeisac(cs, ISAC_CMDR, 0x41);
180 isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
183 if ((ic->command == ISDN_CMD_IOCTL) && (ic->arg == 9)) {
184 ret = isar_auxcmd(cs, ic);
186 reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET |
189 cs->writeisac(cs, ISAC_MASK, 0);
190 cs->writeisac(cs, ISAC_CMDR, 0x41);
194 return(isar_auxcmd(cs, ic));
198 static struct pci_bus *pnp_surf __devinitdata = NULL;
202 setup_isurf(struct IsdnCard *card)
205 struct IsdnCardState *cs = card->cs;
208 strcpy(tmp, ISurf_revision);
209 printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
211 if (cs->typ != ISDN_CTYPE_ISURF)
213 if (card->para[1] && card->para[2]) {
214 cs->hw.isurf.reset = card->para[1];
215 cs->hw.isurf.phymem = card->para[2];
216 cs->irq = card->para[0];
222 if (isapnp_present()) {
224 if ((pb = isapnp_find_card(
225 ISAPNP_VENDOR('S', 'I', 'E'),
226 ISAPNP_FUNCTION(0x0010), pnp_surf))) {
229 if (!(pd = isapnp_find_dev(pnp_surf,
230 ISAPNP_VENDOR('S', 'I', 'E'),
231 ISAPNP_FUNCTION(0x0010), pd))) {
232 printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
238 /* The ISA-PnP logic apparently
239 * expects upper limit address to be
240 * set. Since the isa-pnp module
241 * doesn't do this, so we have to make
244 isapnp_cfg_begin(pd->bus->number, pd->devfn);
245 isapnp_write_word(ISAPNP_CFG_MEM+3,
246 pd->resource[8].end >> 8);
248 cs->hw.isurf.reset = pd->resource[0].start;
249 cs->hw.isurf.phymem = pd->resource[8].start;
250 cs->irq = pd->irq_resource[0].start;
251 if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) {
252 printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n",
253 cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem);
258 printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
262 printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n");
266 printk(KERN_WARNING "HiSax: %s port/mem not set\n",
267 CardType[card->typ]);
271 if (check_region(cs->hw.isurf.reset, 1)) {
273 "HiSax: %s config port %x already in use\n",
278 request_region(cs->hw.isurf.reset, 1, "isurf isdn");
280 if (check_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE)) {
282 "HiSax: %s memory region %lx-%lx already in use\n",
285 cs->hw.isurf.phymem + ISURF_IOMEM_SIZE);
286 release_region(cs->hw.isurf.reset, 1);
289 request_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE,
293 (unsigned long) ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
294 cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
296 "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
301 cs->cardmsg = &ISurf_card_msg;
302 cs->irq_func = &isurf_interrupt;
303 cs->auxcmd = &isurf_auxcmd;
304 cs->readisac = &ReadISAC;
305 cs->writeisac = &WriteISAC;
306 cs->readisacfifo = &ReadISACfifo;
307 cs->writeisacfifo = &WriteISACfifo;
308 cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
309 cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
310 reset_isurf(cs, ISURF_RESET);
311 test_and_set_bit(HW_ISAR, &cs->HW_Flags);
312 ISACVersion(cs, "ISurf:");
313 cs->BC_Read_Reg = &ReadISAR;
314 cs->BC_Write_Reg = &WriteISAR;
315 cs->BC_Send_Data = &isar_fill_fifo;
316 ver = ISARVersion(cs, "ISurf:");
319 "ISurf: wrong ISAR version (ret = %d)\n", ver);
320 release_io_isurf(cs);