File: /usr/src/linux/drivers/isdn/hisax/gazel.c

1     /* $Id: gazel.c,v 2.11.6.6 2001/06/08 08:48:46 kai Exp $
2      *
3      * gazel.c     low level stuff for Gazel isdn cards
4      *
5      * Author       BeWan Systems
6      *              based on source code from Karsten Keil
7      *
8      * This file is (c) under GNU General Public License
9      *
10      */
11     #include <linux/config.h>
12     #include <linux/init.h>
13     #define __NO_VERSION__
14     #include "hisax.h"
15     #include "isac.h"
16     #include "hscx.h"
17     #include "isdnl1.h"
18     #include "ipac.h"
19     #include <linux/pci.h>
20     
21     extern const char *CardType[];
22     const char *gazel_revision = "$Revision: 2.11.6.6 $";
23     
24     #define R647      1
25     #define R685      2
26     #define R753      3
27     #define R742      4
28     
29     #define PLX_CNTRL    0x50	/* registre de controle PLX */
30     #define RESET_GAZEL  0x4
31     #define RESET_9050   0x40000000
32     #define PLX_INCSR    0x4C	/* registre d'IT du 9050 */
33     #define INT_ISAC_EN  0x8	/* 1 = enable IT isac */
34     #define INT_ISAC     0x20	/* 1 = IT isac en cours */
35     #define INT_HSCX_EN  0x1	/* 1 = enable IT hscx */
36     #define INT_HSCX     0x4	/* 1 = IT hscx en cours */
37     #define INT_PCI_EN   0x40	/* 1 = enable IT PCI */
38     #define INT_IPAC_EN  0x3	/* enable IT ipac */
39     
40     
41     #define byteout(addr,val) outb(val,addr)
42     #define bytein(addr) inb(addr)
43     
44     static inline u_char
45     readreg(unsigned int adr, u_short off)
46     {
47     	return bytein(adr + off);
48     }
49     
50     static inline void
51     writereg(unsigned int adr, u_short off, u_char data)
52     {
53     	byteout(adr + off, data);
54     }
55     
56     
57     static inline void
58     read_fifo(unsigned int adr, u_char * data, int size)
59     {
60     	insb(adr, data, size);
61     }
62     
63     static void
64     write_fifo(unsigned int adr, u_char * data, int size)
65     {
66     	outsb(adr, data, size);
67     }
68     
69     static inline u_char
70     readreg_ipac(unsigned int adr, u_short off)
71     {
72     	register u_char ret;
73     	long flags;
74     
75     	save_flags(flags);
76     	cli();
77     	byteout(adr, off);
78     	ret = bytein(adr + 4);
79     	restore_flags(flags);
80     	return ret;
81     }
82     
83     static inline void
84     writereg_ipac(unsigned int adr, u_short off, u_char data)
85     {
86     	long flags;
87     
88     	save_flags(flags);
89     	cli();
90     	byteout(adr, off);
91     	byteout(adr + 4, data);
92     	restore_flags(flags);
93     }
94     
95     
96     static inline void
97     read_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size)
98     {
99     	byteout(adr, off);
100     	insb(adr + 4, data, size);
101     }
102     
103     static void
104     write_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size)
105     {
106     	byteout(adr, off);
107     	outsb(adr + 4, data, size);
108     }
109     
110     /* Interface functions */
111     
112     static u_char
113     ReadISAC(struct IsdnCardState *cs, u_char offset)
114     {
115     	u_short off2 = offset;
116     
117     	switch (cs->subtyp) {
118     		case R647:
119     			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
120     		case R685:
121     			return (readreg(cs->hw.gazel.isac, off2));
122     		case R753:
123     		case R742:
124     			return (readreg_ipac(cs->hw.gazel.ipac, 0x80 + off2));
125     	}
126     	return 0;
127     }
128     
129     static void
130     WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
131     {
132     	u_short off2 = offset;
133     
134     	switch (cs->subtyp) {
135     		case R647:
136     			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
137     		case R685:
138     			writereg(cs->hw.gazel.isac, off2, value);
139     			break;
140     		case R753:
141     		case R742:
142     			writereg_ipac(cs->hw.gazel.ipac, 0x80 + off2, value);
143     			break;
144     	}
145     }
146     
147     static void
148     ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
149     {
150     	switch (cs->subtyp) {
151     		case R647:
152     		case R685:
153     			read_fifo(cs->hw.gazel.isacfifo, data, size);
154     			break;
155     		case R753:
156     		case R742:
157     			read_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size);
158     			break;
159     	}
160     }
161     
162     static void
163     WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
164     {
165     	switch (cs->subtyp) {
166     		case R647:
167     		case R685:
168     			write_fifo(cs->hw.gazel.isacfifo, data, size);
169     			break;
170     		case R753:
171     		case R742:
172     			write_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size);
173     			break;
174     	}
175     }
176     
177     static void
178     ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
179     {
180     	switch (cs->subtyp) {
181     		case R647:
182     		case R685:
183     			read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
184     			break;
185     		case R753:
186     		case R742:
187     			read_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size);
188     			break;
189     	}
190     }
191     
192     static void
193     WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
194     {
195     	switch (cs->subtyp) {
196     		case R647:
197     		case R685:
198     			write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
199     			break;
200     		case R753:
201     		case R742:
202     			write_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size);
203     			break;
204     	}
205     }
206     
207     static u_char
208     ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
209     {
210     	u_short off2 = offset;
211     
212     	switch (cs->subtyp) {
213     		case R647:
214     			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
215     		case R685:
216     			return (readreg(cs->hw.gazel.hscx[hscx], off2));
217     		case R753:
218     		case R742:
219     			return (readreg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2));
220     	}
221     	return 0;
222     }
223     
224     static void
225     WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
226     {
227     	u_short off2 = offset;
228     
229     	switch (cs->subtyp) {
230     		case R647:
231     			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
232     		case R685:
233     			writereg(cs->hw.gazel.hscx[hscx], off2, value);
234     			break;
235     		case R753:
236     		case R742:
237     			writereg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2, value);
238     			break;
239     	}
240     }
241     
242     /*
243      * fast interrupt HSCX stuff goes here
244      */
245     
246     #define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
247     #define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
248     #define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt)
249     #define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
250     
251     #include "hscx_irq.c"
252     
253     static void
254     gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs)
255     {
256     #define MAXCOUNT 5
257     	struct IsdnCardState *cs = dev_id;
258     	u_char valisac, valhscx;
259     	int count = 0;
260     
261     	if (!cs) {
262     		printk(KERN_WARNING "Gazel: Spurious interrupt!\n");
263     		return;
264     	}
265     	do {
266     		valhscx = ReadHSCX(cs, 1, HSCX_ISTA);
267     		if (valhscx)
268     			hscx_int_main(cs, valhscx);
269     		valisac = ReadISAC(cs, ISAC_ISTA);
270     		if (valisac)
271     			isac_interrupt(cs, valisac);
272     		count++;
273     	} while ((valhscx || valisac) && (count < MAXCOUNT));
274     
275     	WriteHSCX(cs, 0, HSCX_MASK, 0xFF);
276     	WriteHSCX(cs, 1, HSCX_MASK, 0xFF);
277     	WriteISAC(cs, ISAC_MASK, 0xFF);
278     	WriteISAC(cs, ISAC_MASK, 0x0);
279     	WriteHSCX(cs, 0, HSCX_MASK, 0x0);
280     	WriteHSCX(cs, 1, HSCX_MASK, 0x0);
281     }
282     
283     
284     static void
285     gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
286     {
287     	struct IsdnCardState *cs = dev_id;
288     	u_char ista, val;
289     	int count = 0;
290     
291     	if (!cs) {
292     		printk(KERN_WARNING "Gazel: Spurious interrupt!\n");
293     		return;
294     	}
295     	ista = ReadISAC(cs, IPAC_ISTA - 0x80);
296     	do {
297     		if (ista & 0x0f) {
298     			val = ReadHSCX(cs, 1, HSCX_ISTA);
299     			if (ista & 0x01)
300     				val |= 0x01;
301     			if (ista & 0x04)
302     				val |= 0x02;
303     			if (ista & 0x08)
304     				val |= 0x04;
305     			if (val) {
306     				hscx_int_main(cs, val);
307     			}
308     		}
309     		if (ista & 0x20) {
310     			val = 0xfe & ReadISAC(cs, ISAC_ISTA);
311     			if (val) {
312     				isac_interrupt(cs, val);
313     			}
314     		}
315     		if (ista & 0x10) {
316     			val = 0x01;
317     			isac_interrupt(cs, val);
318     		}
319     		ista = ReadISAC(cs, IPAC_ISTA - 0x80);
320     		count++;
321     	}
322     	while ((ista & 0x3f) && (count < MAXCOUNT));
323     
324     	WriteISAC(cs, IPAC_MASK - 0x80, 0xFF);
325     	WriteISAC(cs, IPAC_MASK - 0x80, 0xC0);
326     }
327     void
328     release_io_gazel(struct IsdnCardState *cs)
329     {
330     	unsigned int i;
331     
332     	switch (cs->subtyp) {
333     		case R647:
334     			for (i = 0x0000; i < 0xC000; i += 0x1000)
335     				release_region(i + cs->hw.gazel.hscx[0], 16);
336     			release_region(0xC000 + cs->hw.gazel.hscx[0], 1);
337     			break;
338     
339     		case R685:
340     			release_region(cs->hw.gazel.hscx[0], 0x100);
341     			release_region(cs->hw.gazel.cfg_reg, 0x80);
342     			break;
343     
344     		case R753:
345     			release_region(cs->hw.gazel.ipac, 0x8);
346     			release_region(cs->hw.gazel.cfg_reg, 0x80);
347     			break;
348     
349     		case R742:
350     			release_region(cs->hw.gazel.ipac, 8);
351     			break;
352     	}
353     }
354     
355     static int
356     reset_gazel(struct IsdnCardState *cs)
357     {
358     	long flags;
359     	unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
360     
361     	switch (cs->subtyp) {
362     		case R647:
363     			save_flags(flags);
364     			cli();
365     			writereg(addr, 0, 0);
366     			HZDELAY(10);
367     			writereg(addr, 0, 1);
368     			HZDELAY(2);
369     			restore_flags(flags);
370     			break;
371     		case R685:
372     			plxcntrl = inl(addr + PLX_CNTRL);
373     			plxcntrl |= (RESET_9050 + RESET_GAZEL);
374     			outl(plxcntrl, addr + PLX_CNTRL);
375     			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
376     			HZDELAY(4);
377     			outl(plxcntrl, addr + PLX_CNTRL);
378     			HZDELAY(10);
379     			outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
380     			break;
381     		case R753:
382     			plxcntrl = inl(addr + PLX_CNTRL);
383     			plxcntrl |= (RESET_9050 + RESET_GAZEL);
384     			outl(plxcntrl, addr + PLX_CNTRL);
385     			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
386     			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
387     			HZDELAY(4);
388     			outl(plxcntrl, addr + PLX_CNTRL);
389     			HZDELAY(10);
390     			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
391     			WriteISAC(cs, IPAC_ACFG - 0x80, 0xff);
392     			WriteISAC(cs, IPAC_AOE - 0x80, 0x0);
393     			WriteISAC(cs, IPAC_MASK - 0x80, 0xff);
394     			WriteISAC(cs, IPAC_CONF - 0x80, 0x1);
395     			outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR);
396     			WriteISAC(cs, IPAC_MASK - 0x80, 0xc0);
397     			break;
398     		case R742:
399     			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
400     			HZDELAY(4);
401     			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
402     			WriteISAC(cs, IPAC_ACFG - 0x80, 0xff);
403     			WriteISAC(cs, IPAC_AOE - 0x80, 0x0);
404     			WriteISAC(cs, IPAC_MASK - 0x80, 0xff);
405     			WriteISAC(cs, IPAC_CONF - 0x80, 0x1);
406     			WriteISAC(cs, IPAC_MASK - 0x80, 0xc0);
407     			break;
408     	}
409     	return (0);
410     }
411     
412     static int
413     Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg)
414     {
415     	switch (mt) {
416     		case CARD_RESET:
417     			reset_gazel(cs);
418     			return (0);
419     		case CARD_RELEASE:
420     			release_io_gazel(cs);
421     			return (0);
422     		case CARD_INIT:
423     			inithscxisac(cs, 1);
424     			if ((cs->subtyp==R647)||(cs->subtyp==R685)) {
425     				int i;
426     				for (i=0;i<(2+MAX_WAITING_CALLS);i++) {
427     					cs->bcs[i].hw.hscx.tsaxr0 = 0x1f;
428     					cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
429     				}
430     			}
431     			return (0);
432     		case CARD_TEST:
433     			return (0);
434     	}
435     	return (0);
436     }
437     
438     static int
439     reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
440     {
441     	unsigned int i, base = 0, adr = 0, len = 0;
442     
443     	switch (cs->subtyp) {
444     		case R647:
445     			base = cs->hw.gazel.hscx[0];
446     			for (i = 0x0000; i < 0xC000; i += 0x1000) {
447     				if (check_region(adr = (i + base), len = 16))
448     					goto error;
449     			}
450     			if (check_region(adr = (0xC000 + base), len = 1))
451     				goto error;
452     
453     			for (i = 0x0000; i < 0xC000; i += 0x1000)
454     				request_region(i + base, 16, "gazel");
455     			request_region(0xC000 + base, 1, "gazel");
456     
457     			break;
458     
459     		case R685:
460     			if (check_region(adr = cs->hw.gazel.hscx[0], len = 0x100))
461     				goto error;
462     			if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80))
463     				goto error;
464     
465     			request_region(cs->hw.gazel.hscx[0], 0x100, "gazel");
466     			request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel");
467     			break;
468     
469     		case R753:
470     			if (check_region(adr = cs->hw.gazel.ipac, len = 0x8))
471     				goto error;
472     			if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80))
473     				goto error;
474     
475     			request_region(cs->hw.gazel.ipac, 0x8, "gazel");
476     			request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel");
477     			break;
478     
479     		case R742:
480     			if (check_region(adr = cs->hw.gazel.ipac, len = 0x8))
481     				goto error;
482     			request_region(cs->hw.gazel.ipac, 0x8, "gazel");
483     			break;
484     	}
485     
486     	return 0;
487     
488           error:
489     	printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n",
490     	       CardType[cs->typ], adr, adr + len);
491     	return 1;
492     }
493     
494     static int __init
495     setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
496     {
497     	printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n");
498     	// we got an irq parameter, assume it is an ISA card
499     	// R742 decodes address even in not started...
500     	// R647 returns FF if not present or not started
501     	// eventually needs improvment
502     	if (readreg_ipac(card->para[1], IPAC_ID) == 1)
503     		cs->subtyp = R742;
504     	else
505     		cs->subtyp = R647;
506     
507     	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
508     	cs->hw.gazel.ipac = card->para[1];
509     	cs->hw.gazel.isac = card->para[1] + 0x8000;
510     	cs->hw.gazel.hscx[0] = card->para[1];
511     	cs->hw.gazel.hscx[1] = card->para[1] + 0x4000;
512     	cs->irq = card->para[0];
513     	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
514     	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
515     	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
516     
517     	switch (cs->subtyp) {
518     		case R647:
519     			printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
520     			cs->dc.isac.adf2 = 0x87;
521     			printk(KERN_INFO
522     				"Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
523     				cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
524     			printk(KERN_INFO
525     				"Gazel: hscx A:0x%X  hscx B:0x%X\n",
526     				cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
527     
528     			break;
529     		case R742:
530     			printk(KERN_INFO "Gazel: Card ISA R742 found\n");
531     			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
532     			printk(KERN_INFO
533     			       "Gazel: config irq:%d ipac:0x%X\n",
534     			       cs->irq, cs->hw.gazel.ipac);
535     			break;
536     	}
537     
538     	return (0);
539     }
540     
541     static struct pci_dev *dev_tel __initdata = NULL;
542     
543     static int __init
544     setup_gazelpci(struct IsdnCardState *cs)
545     {
546     	u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
547     	u_char pci_irq = 0, found;
548     	u_int nbseek, seekcard;
549     
550     	printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
551     
552     	found = 0;
553     	if (!pci_present()) {
554     		printk(KERN_WARNING "Gazel: No PCI bus present\n");
555     		return 1;
556     	}
557     	seekcard = PCI_DEVICE_ID_PLX_R685;
558     	for (nbseek = 0; nbseek < 3; nbseek++) {
559     		if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) {
560     			if (pci_enable_device(dev_tel))
561     				return 1;
562     			pci_irq = dev_tel->irq;
563     			pci_ioaddr0 = pci_resource_start(dev_tel, 1);
564     			pci_ioaddr1 = pci_resource_start(dev_tel, 2);
565     			found = 1;
566     		}
567     		if (found)
568     			break;
569     		else {
570     			switch (seekcard) {
571     				case PCI_DEVICE_ID_PLX_R685:
572     					seekcard = PCI_DEVICE_ID_PLX_R753;
573     					break;
574     				case PCI_DEVICE_ID_PLX_R753:
575     					seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO;
576     					break;
577     			}
578     		}
579     	}
580     	if (!found) {
581     		printk(KERN_WARNING "Gazel: No PCI card found\n");
582     		return (1);
583     	}
584     	if (!pci_irq) {
585     		printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
586     		return 1;
587     	}
588     	cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
589     	cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
590     
591     	pci_ioaddr1 &= 0xfffe;
592     	cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe;
593     	cs->hw.gazel.ipac = pci_ioaddr1;
594     	cs->hw.gazel.isac = pci_ioaddr1 + 0x80;
595     	cs->hw.gazel.hscx[0] = pci_ioaddr1;
596     	cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40;
597     	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
598     	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
599     	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
600     	cs->irq = pci_irq;
601     	cs->irq_flags |= SA_SHIRQ;
602     
603     	switch (seekcard) {
604     		case PCI_DEVICE_ID_PLX_R685:
605     			printk(KERN_INFO "Gazel: Card PCI R685 found\n");
606     			cs->subtyp = R685;
607     			cs->dc.isac.adf2 = 0x87;
608     			printk(KERN_INFO
609     			    "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
610     			cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
611     			printk(KERN_INFO
612     			       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
613     			     cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
614     			break;
615     		case PCI_DEVICE_ID_PLX_R753:
616     		case PCI_DEVICE_ID_PLX_DJINN_ITOO:
617     			printk(KERN_INFO "Gazel: Card PCI R753 found\n");
618     			cs->subtyp = R753;
619     			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
620     			printk(KERN_INFO
621     			    "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
622     			cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
623     			break;
624     	}
625     
626     	return (0);
627     }
628     
629     int __init
630     setup_gazel(struct IsdnCard *card)
631     {
632     	struct IsdnCardState *cs = card->cs;
633     	char tmp[64];
634     	u_char val;
635     
636     	strcpy(tmp, gazel_revision);
637     	printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
638     
639     	if (cs->typ != ISDN_CTYPE_GAZEL)
640     		return (0);
641     
642     	if (card->para[0]) {
643     		if (setup_gazelisa(card, cs))
644     			return (0);
645     	} else {
646     
647     #if CONFIG_PCI
648     		if (setup_gazelpci(cs))
649     			return (0);
650     #else
651     		printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n");
652     		return (0);
653     #endif				/* CONFIG_PCI */
654     	}
655     
656     	if (reserve_regions(card, cs)) {
657     		return (0);
658     	}
659     	if (reset_gazel(cs)) {
660     		printk(KERN_WARNING "Gazel: wrong IRQ\n");
661     		release_io_gazel(cs);
662     		return (0);
663     	}
664     	cs->readisac = &ReadISAC;
665     	cs->writeisac = &WriteISAC;
666     	cs->readisacfifo = &ReadISACfifo;
667     	cs->writeisacfifo = &WriteISACfifo;
668     	cs->BC_Read_Reg = &ReadHSCX;
669     	cs->BC_Write_Reg = &WriteHSCX;
670     	cs->BC_Send_Data = &hscx_fill_fifo;
671     	cs->cardmsg = &Gazel_card_msg;
672     
673     	switch (cs->subtyp) {
674     		case R647:
675     		case R685:
676     			cs->irq_func = &gazel_interrupt;
677     			ISACVersion(cs, "Gazel:");
678     			if (HscxVersion(cs, "Gazel:")) {
679     				printk(KERN_WARNING
680     				       "Gazel: wrong HSCX versions check IO address\n");
681     				release_io_gazel(cs);
682     				return (0);
683     			}
684     			break;
685     		case R742:
686     		case R753:
687     			cs->irq_func = &gazel_interrupt_ipac;
688     			val = ReadISAC(cs, IPAC_ID - 0x80);
689     			printk(KERN_INFO "Gazel: IPAC version %x\n", val);
690     			break;
691     	}
692     
693     	return (1);
694     }
695