1/* $Id: sedlbauer.c,v 1.1.1.1 2007/08/03 18:52:36 Exp $
2 *
3 * low level stuff for Sedlbauer cards
4 * includes support for the Sedlbauer speed star (speed star II),
5 * support for the Sedlbauer speed fax+,
6 * support for the Sedlbauer ISDN-Controller PC/104 and
7 * support for the Sedlbauer speed pci
8 * derived from the original file asuscom.c from Karsten Keil
9 *
10 * Author       Marcus Niemann
11 * Copyright    by Marcus Niemann    <niemann@www-bib.fh-bielefeld.de>
12 *
13 * This software may be used and distributed according to the terms
14 * of the GNU General Public License, incorporated herein by reference.
15 *
16 * Thanks to  Karsten Keil
17 *            Sedlbauer AG for informations
18 *            Edgar Toernig
19 *
20 */
21
22/* Supported cards:
23 * Card:	Chip:		Configuration:	Comment:
24 * ---------------------------------------------------------------------
25 * Speed Card	ISAC_HSCX	DIP-SWITCH
26 * Speed Win	ISAC_HSCX	ISAPNP
27 * Speed Fax+	ISAC_ISAR	ISAPNP		Full analog support
28 * Speed Star	ISAC_HSCX	CARDMGR
29 * Speed Win2	IPAC		ISAPNP
30 * ISDN PC/104	IPAC		DIP-SWITCH
31 * Speed Star2	IPAC		CARDMGR
32 * Speed PCI	IPAC		PCI PNP
33 * Speed Fax+ 	ISAC_ISAR	PCI PNP		Full analog support
34 *
35 * Important:
36 * For the sedlbauer speed fax+ to work properly you have to download
37 * the firmware onto the card.
38 * For example: hisaxctrl <DriverID> 9 ISAR.BIN
39*/
40
41#include <linux/init.h>
42#include "hisax.h"
43#include "isac.h"
44#include "ipac.h"
45#include "hscx.h"
46#include "isar.h"
47#include "isdnl1.h"
48#include <linux/pci.h>
49#include <linux/isapnp.h>
50
51extern const char *CardType[];
52
53static const char *Sedlbauer_revision = "$Revision: 1.1.1.1 $";
54
55static const char *Sedlbauer_Types[] =
56	{"None", "speed card/win", "speed star", "speed fax+",
57	"speed win II / ISDN PC/104", "speed star II", "speed pci",
58	"speed fax+ pyramid", "speed fax+ pci", "HST Saphir III"};
59
60#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID	0x51
61#define PCI_SUBVENDOR_HST_SAPHIR3	0x52
62#define PCI_SUBVENDOR_SEDLBAUER_PCI	0x53
63#define PCI_SUBVENDOR_SPEEDFAX_PCI	0x54
64#define PCI_SUB_ID_SEDLBAUER		0x01
65
66#define SEDL_SPEED_CARD_WIN	1
67#define SEDL_SPEED_STAR 	2
68#define SEDL_SPEED_FAX		3
69#define SEDL_SPEED_WIN2_PC104 	4
70#define SEDL_SPEED_STAR2 	5
71#define SEDL_SPEED_PCI   	6
72#define SEDL_SPEEDFAX_PYRAMID	7
73#define SEDL_SPEEDFAX_PCI	8
74#define HST_SAPHIR3		9
75
76#define SEDL_CHIP_TEST		0
77#define SEDL_CHIP_ISAC_HSCX	1
78#define SEDL_CHIP_ISAC_ISAR	2
79#define SEDL_CHIP_IPAC		3
80
81#define SEDL_BUS_ISA		1
82#define SEDL_BUS_PCI		2
83#define	SEDL_BUS_PCMCIA		3
84
85#define byteout(addr,val) outb(val,addr)
86#define bytein(addr) inb(addr)
87
88#define SEDL_HSCX_ISA_RESET_ON	0
89#define SEDL_HSCX_ISA_RESET_OFF	1
90#define SEDL_HSCX_ISA_ISAC	2
91#define SEDL_HSCX_ISA_HSCX	3
92#define SEDL_HSCX_ISA_ADR	4
93
94#define SEDL_HSCX_PCMCIA_RESET	0
95#define SEDL_HSCX_PCMCIA_ISAC	1
96#define SEDL_HSCX_PCMCIA_HSCX	2
97#define SEDL_HSCX_PCMCIA_ADR	4
98
99#define SEDL_ISAR_ISA_ISAC		4
100#define SEDL_ISAR_ISA_ISAR		6
101#define SEDL_ISAR_ISA_ADR		8
102#define SEDL_ISAR_ISA_ISAR_RESET_ON	10
103#define SEDL_ISAR_ISA_ISAR_RESET_OFF	12
104
105#define SEDL_IPAC_ANY_ADR		0
106#define SEDL_IPAC_ANY_IPAC		2
107
108#define SEDL_IPAC_PCI_BASE		0
109#define SEDL_IPAC_PCI_ADR		0xc0
110#define SEDL_IPAC_PCI_IPAC		0xc8
111#define SEDL_ISAR_PCI_ADR		0xc8
112#define SEDL_ISAR_PCI_ISAC		0xd0
113#define SEDL_ISAR_PCI_ISAR		0xe0
114#define SEDL_ISAR_PCI_ISAR_RESET_ON	0x01
115#define SEDL_ISAR_PCI_ISAR_RESET_OFF	0x18
116#define SEDL_ISAR_PCI_LED1		0x08
117#define SEDL_ISAR_PCI_LED2		0x10
118
119#define SEDL_RESET      0x3	/* same as DOS driver */
120
121static inline u_char
122readreg(unsigned int ale, unsigned int adr, u_char off)
123{
124	register u_char ret;
125
126	byteout(ale, off);
127	ret = bytein(adr);
128	return (ret);
129}
130
131static inline void
132readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
133{
134	byteout(ale, off);
135	insb(adr, data, size);
136}
137
138
139static inline void
140writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
141{
142	byteout(ale, off);
143	byteout(adr, data);
144}
145
146static inline void
147writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
148{
149	byteout(ale, off);
150	outsb(adr, data, size);
151}
152
153/* Interface functions */
154
155static u_char
156ReadISAC(struct IsdnCardState *cs, u_char offset)
157{
158	return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset));
159}
160
161static void
162WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
163{
164	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset, value);
165}
166
167static void
168ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
169{
170	readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size);
171}
172
173static void
174WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
175{
176	writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size);
177}
178
179static u_char
180ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
181{
182	return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80));
183}
184
185static void
186WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
187{
188	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80, value);
189}
190
191static void
192ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
193{
194	readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
195}
196
197static void
198WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
199{
200	writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
201}
202
203static u_char
204ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
205{
206	return (readreg(cs->hw.sedl.adr,
207			cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0)));
208}
209
210static void
211WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
212{
213	writereg(cs->hw.sedl.adr,
214		 cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value);
215}
216
217/* ISAR access routines
218 * mode = 0 access with IRQ on
219 * mode = 1 access with IRQ off
220 * mode = 2 access with IRQ off and using last offset
221 */
222
223static u_char
224ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
225{
226	if (mode == 0)
227		return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset));
228	else if (mode == 1)
229		byteout(cs->hw.sedl.adr, offset);
230	return(bytein(cs->hw.sedl.hscx));
231}
232
233static void
234WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
235{
236	if (mode == 0)
237		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value);
238	else {
239		if (mode == 1)
240			byteout(cs->hw.sedl.adr, offset);
241		byteout(cs->hw.sedl.hscx, value);
242	}
243}
244
245/*
246 * fast interrupt HSCX stuff goes here
247 */
248
249#define READHSCX(cs, nr, reg) readreg(cs->hw.sedl.adr, \
250		cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0))
251#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.sedl.adr, \
252		cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0), data)
253
254#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.sedl.adr, \
255		cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt)
256
257#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.sedl.adr, \
258		cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt)
259
260#include "hscx_irq.c"
261
262static irqreturn_t
263sedlbauer_interrupt(int intno, void *dev_id)
264{
265	struct IsdnCardState *cs = dev_id;
266	u_char val;
267	u_long flags;
268
269	spin_lock_irqsave(&cs->lock, flags);
270	if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) {
271		/* The card tends to generate interrupts while being removed
272		   causing us to just crash the kernel. bad. */
273		spin_unlock_irqrestore(&cs->lock, flags);
274		printk(KERN_WARNING "Sedlbauer: card not available!\n");
275		return IRQ_NONE;
276	}
277
278	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
279      Start_HSCX:
280	if (val)
281		hscx_int_main(cs, val);
282	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
283      Start_ISAC:
284	if (val)
285		isac_interrupt(cs, val);
286	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
287	if (val) {
288		if (cs->debug & L1_DEB_HSCX)
289			debugl1(cs, "HSCX IntStat after IntRoutine");
290		goto Start_HSCX;
291	}
292	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
293	if (val) {
294		if (cs->debug & L1_DEB_ISAC)
295			debugl1(cs, "ISAC IntStat after IntRoutine");
296		goto Start_ISAC;
297	}
298	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF);
299	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF);
300	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
301	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
302	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0);
303	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0);
304	spin_unlock_irqrestore(&cs->lock, flags);
305	return IRQ_HANDLED;
306}
307
308static irqreturn_t
309sedlbauer_interrupt_ipac(int intno, void *dev_id)
310{
311	struct IsdnCardState *cs = dev_id;
312	u_char ista, val, icnt = 5;
313	u_long flags;
314
315	spin_lock_irqsave(&cs->lock, flags);
316	ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
317Start_IPAC:
318	if (cs->debug & L1_DEB_IPAC)
319		debugl1(cs, "IPAC ISTA %02X", ista);
320	if (ista & 0x0f) {
321		val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
322		if (ista & 0x01)
323			val |= 0x01;
324		if (ista & 0x04)
325			val |= 0x02;
326		if (ista & 0x08)
327			val |= 0x04;
328		if (val)
329			hscx_int_main(cs, val);
330	}
331	if (ista & 0x20) {
332		val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80);
333		if (val) {
334			isac_interrupt(cs, val);
335		}
336	}
337	if (ista & 0x10) {
338		val = 0x01;
339		isac_interrupt(cs, val);
340	}
341	ista  = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
342	if ((ista & 0x3f) && icnt) {
343		icnt--;
344		goto Start_IPAC;
345	}
346	if (!icnt)
347		if (cs->debug & L1_DEB_ISAC)
348			debugl1(cs, "Sedlbauer IRQ LOOP");
349	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF);
350	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0);
351	spin_unlock_irqrestore(&cs->lock, flags);
352	return IRQ_HANDLED;
353}
354
355static irqreturn_t
356sedlbauer_interrupt_isar(int intno, void *dev_id)
357{
358	struct IsdnCardState *cs = dev_id;
359	u_char val;
360	int cnt = 5;
361	u_long flags;
362
363	spin_lock_irqsave(&cs->lock, flags);
364	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
365      Start_ISAR:
366	if (val & ISAR_IRQSTA)
367		isar_int_main(cs);
368	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
369      Start_ISAC:
370	if (val)
371		isac_interrupt(cs, val);
372	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
373	if ((val & ISAR_IRQSTA) && --cnt) {
374		if (cs->debug & L1_DEB_HSCX)
375			debugl1(cs, "ISAR IntStat after IntRoutine");
376		goto Start_ISAR;
377	}
378	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
379	if (val && --cnt) {
380		if (cs->debug & L1_DEB_ISAC)
381			debugl1(cs, "ISAC IntStat after IntRoutine");
382		goto Start_ISAC;
383	}
384	if (!cnt)
385		if (cs->debug & L1_DEB_ISAC)
386			debugl1(cs, "Sedlbauer IRQ LOOP");
387
388	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0);
389	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
390	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
391	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK);
392	spin_unlock_irqrestore(&cs->lock, flags);
393	return IRQ_HANDLED;
394}
395
396static void
397release_io_sedlbauer(struct IsdnCardState *cs)
398{
399	int bytecnt = 8;
400
401	if (cs->subtyp == SEDL_SPEED_FAX) {
402		bytecnt = 16;
403	} else if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
404		bytecnt = 256;
405	}
406	if (cs->hw.sedl.cfg_reg)
407		release_region(cs->hw.sedl.cfg_reg, bytecnt);
408}
409
410static void
411reset_sedlbauer(struct IsdnCardState *cs)
412{
413	printk(KERN_INFO "Sedlbauer: resetting card\n");
414
415	if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) &&
416	   (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) {
417		if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
418			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
419			mdelay(2);
420			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
421			mdelay(10);
422			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0);
423			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
424			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0);
425			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
426			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
427		} else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) &&
428			(cs->hw.sedl.bus == SEDL_BUS_PCI)) {
429			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
430			mdelay(2);
431			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
432			mdelay(10);
433		} else {
434			byteout(cs->hw.sedl.reset_on, SEDL_RESET);	/* Reset On */
435			mdelay(2);
436			byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
437			mdelay(10);
438		}
439	}
440}
441
442static int
443Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
444{
445	u_long flags;
446
447	switch (mt) {
448		case CARD_RESET:
449			spin_lock_irqsave(&cs->lock, flags);
450			reset_sedlbauer(cs);
451			spin_unlock_irqrestore(&cs->lock, flags);
452			return(0);
453		case CARD_RELEASE:
454			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
455				spin_lock_irqsave(&cs->lock, flags);
456				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
457					ISAR_IRQBIT, 0);
458				writereg(cs->hw.sedl.adr, cs->hw.sedl.isac,
459					ISAC_MASK, 0xFF);
460				reset_sedlbauer(cs);
461				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
462					ISAR_IRQBIT, 0);
463				writereg(cs->hw.sedl.adr, cs->hw.sedl.isac,
464					ISAC_MASK, 0xFF);
465				spin_unlock_irqrestore(&cs->lock, flags);
466			}
467			release_io_sedlbauer(cs);
468			return(0);
469		case CARD_INIT:
470			spin_lock_irqsave(&cs->lock, flags);
471			reset_sedlbauer(cs);
472			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
473				clear_pending_isac_ints(cs);
474				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
475					ISAR_IRQBIT, 0);
476				initisac(cs);
477				initisar(cs);
478				/* Reenable all IRQ */
479				cs->writeisac(cs, ISAC_MASK, 0);
480				/* RESET Receiver and Transmitter */
481				cs->writeisac(cs, ISAC_CMDR, 0x41);
482			} else {
483				inithscxisac(cs, 3);
484			}
485			spin_unlock_irqrestore(&cs->lock, flags);
486			return(0);
487		case CARD_TEST:
488			return(0);
489		case MDL_INFO_CONN:
490			if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
491				return(0);
492			spin_lock_irqsave(&cs->lock, flags);
493			if ((long) arg)
494				cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2;
495			else
496				cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1;
497			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
498			spin_unlock_irqrestore(&cs->lock, flags);
499			break;
500		case MDL_INFO_REL:
501			if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
502				return(0);
503			spin_lock_irqsave(&cs->lock, flags);
504			if ((long) arg)
505				cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2;
506			else
507				cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1;
508			byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
509			spin_unlock_irqrestore(&cs->lock, flags);
510			break;
511	}
512	return(0);
513}
514
515static struct pci_dev *dev_sedl __devinitdata = NULL;
516
517#ifdef __ISAPNP__
518static struct isapnp_device_id sedl_ids[] __devinitdata = {
519	{ ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
520	  ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
521	  (unsigned long) "Speed win" },
522	{ ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
523	  ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
524	  (unsigned long) "Speed Fax+" },
525	{ 0, }
526};
527
528static struct isapnp_device_id *ipid __devinitdata = &sedl_ids[0];
529static struct pnp_card *pnp_c __devinitdata = NULL;
530#endif
531
532int __devinit
533setup_sedlbauer(struct IsdnCard *card)
534{
535	int bytecnt, ver, val;
536	struct IsdnCardState *cs = card->cs;
537	char tmp[64];
538	u16 sub_vendor_id, sub_id;
539
540	strcpy(tmp, Sedlbauer_revision);
541	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
542
543 	if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
544 		cs->subtyp = SEDL_SPEED_CARD_WIN;
545		cs->hw.sedl.bus = SEDL_BUS_ISA;
546		cs->hw.sedl.chip = SEDL_CHIP_TEST;
547 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
548 		cs->subtyp = SEDL_SPEED_STAR;
549		cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
550		cs->hw.sedl.chip = SEDL_CHIP_TEST;
551 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {
552 		cs->subtyp = SEDL_SPEED_FAX;
553		cs->hw.sedl.bus = SEDL_BUS_ISA;
554		cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
555 	} else
556		return (0);
557
558	bytecnt = 8;
559	if (card->para[1]) {
560		cs->hw.sedl.cfg_reg = card->para[1];
561		cs->irq = card->para[0];
562		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
563			bytecnt = 16;
564		}
565	} else {
566#ifdef __ISAPNP__
567		if (isapnp_present()) {
568			struct pnp_dev *pnp_d;
569			while(ipid->card_vendor) {
570				if ((pnp_c = pnp_find_card(ipid->card_vendor,
571					ipid->card_device, pnp_c))) {
572					pnp_d = NULL;
573					if ((pnp_d = pnp_find_dev(pnp_c,
574						ipid->vendor, ipid->function, pnp_d))) {
575						int err;
576
577						printk(KERN_INFO "HiSax: %s detected\n",
578							(char *)ipid->driver_data);
579						pnp_disable_dev(pnp_d);
580						err = pnp_activate_dev(pnp_d);
581						if (err<0) {
582							printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
583								__FUNCTION__, err);
584							return(0);
585						}
586						card->para[1] = pnp_port_start(pnp_d, 0);
587						card->para[0] = pnp_irq(pnp_d, 0);
588
589						if (!card->para[0] || !card->para[1]) {
590							printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
591								card->para[0], card->para[1]);
592							pnp_disable_dev(pnp_d);
593							return(0);
594						}
595						cs->hw.sedl.cfg_reg = card->para[1];
596						cs->irq = card->para[0];
597						if (ipid->function == ISAPNP_FUNCTION(0x2)) {
598							cs->subtyp = SEDL_SPEED_FAX;
599							cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
600							bytecnt = 16;
601						} else {
602							cs->subtyp = SEDL_SPEED_CARD_WIN;
603							cs->hw.sedl.chip = SEDL_CHIP_TEST;
604						}
605						goto ready;
606					} else {
607						printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
608						return(0);
609					}
610				}
611				ipid++;
612				pnp_c = NULL;
613			}
614			if (!ipid->card_vendor) {
615				printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
616			}
617		}
618#endif
619/* Probe for Sedlbauer speed pci */
620#ifdef CONFIG_PCI
621		if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
622				PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
623			if (pci_enable_device(dev_sedl))
624				return(0);
625			cs->irq = dev_sedl->irq;
626			if (!cs->irq) {
627				printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
628				return(0);
629			}
630			cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
631		} else {
632			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
633			return(0);
634		}
635		cs->irq_flags |= IRQF_SHARED;
636		cs->hw.sedl.bus = SEDL_BUS_PCI;
637		sub_vendor_id = dev_sedl->subsystem_vendor;
638		sub_id = dev_sedl->subsystem_device;
639		printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
640			sub_vendor_id, sub_id);
641		printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
642			cs->hw.sedl.cfg_reg);
643		if (sub_id != PCI_SUB_ID_SEDLBAUER) {
644			printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
645			return(0);
646		}
647		if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
648			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
649			cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
650		} else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
651			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
652			cs->subtyp = SEDL_SPEEDFAX_PCI;
653		} else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) {
654			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
655			cs->subtyp = HST_SAPHIR3;
656		} else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
657			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
658			cs->subtyp = SEDL_SPEED_PCI;
659		} else {
660			printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
661				sub_vendor_id);
662			return(0);
663		}
664		bytecnt = 256;
665		cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
666		cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
667		byteout(cs->hw.sedl.cfg_reg, 0xff);
668		byteout(cs->hw.sedl.cfg_reg, 0x00);
669		byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
670		byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
671		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
672		mdelay(2);
673		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
674		mdelay(10);
675#else
676		printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
677		return (0);
678#endif /* CONFIG_PCI */
679	}
680
681#ifdef __ISAPNP__
682ready:
683#endif
684
685	/* In case of the sedlbauer pcmcia card, this region is in use,
686	 * reserved for us by the card manager. So we do not check it
687	 * here, it would fail.
688	 */
689	if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
690		!request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn")) {
691		printk(KERN_WARNING
692			"HiSax: %s config port %x-%x already in use\n",
693			CardType[card->typ],
694			cs->hw.sedl.cfg_reg,
695			cs->hw.sedl.cfg_reg + bytecnt);
696			return (0);
697	}
698
699	printk(KERN_INFO
700	       "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
701	       cs->hw.sedl.cfg_reg,
702	       cs->hw.sedl.cfg_reg + bytecnt,
703	       cs->irq);
704
705	cs->BC_Read_Reg = &ReadHSCX;
706	cs->BC_Write_Reg = &WriteHSCX;
707	cs->BC_Send_Data = &hscx_fill_fifo;
708	cs->cardmsg = &Sedl_card_msg;
709
710/*
711 * testing ISA and PCMCIA Cards for IPAC, default is ISAC
712 * do not test for PCI card, because ports are different
713 * and PCI card uses only IPAC (for the moment)
714 */
715	if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
716		val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR,
717			cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
718		printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
719	        if ((val == 1) || (val == 2)) {
720			/* IPAC */
721			cs->subtyp = SEDL_SPEED_WIN2_PC104;
722			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
723				cs->subtyp = SEDL_SPEED_STAR2;
724			}
725			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
726		} else {
727			/* ISAC_HSCX oder ISAC_ISAR */
728			if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
729				cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
730			}
731		}
732	}
733
734/*
735 * hw.sedl.chip is now properly set
736 */
737	printk(KERN_INFO "Sedlbauer: %s detected\n",
738		Sedlbauer_Types[cs->subtyp]);
739
740	setup_isac(cs);
741	if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
742		if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
743	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
744			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
745			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
746		} else {
747	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
748			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
749			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
750		}
751		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
752		cs->readisac = &ReadISAC_IPAC;
753		cs->writeisac = &WriteISAC_IPAC;
754		cs->readisacfifo = &ReadISACfifo_IPAC;
755		cs->writeisacfifo = &WriteISACfifo_IPAC;
756		cs->irq_func = &sedlbauer_interrupt_ipac;
757		val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ID);
758		printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
759	} else {
760		/* ISAC_HSCX oder ISAC_ISAR */
761		cs->readisac = &ReadISAC;
762		cs->writeisac = &WriteISAC;
763		cs->readisacfifo = &ReadISACfifo;
764		cs->writeisacfifo = &WriteISACfifo;
765		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
766			if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
767				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
768							SEDL_ISAR_PCI_ADR;
769				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
770							SEDL_ISAR_PCI_ISAC;
771				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
772							SEDL_ISAR_PCI_ISAR;
773			} else {
774				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
775							SEDL_ISAR_ISA_ADR;
776				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
777							SEDL_ISAR_ISA_ISAC;
778				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
779							SEDL_ISAR_ISA_ISAR;
780				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
781							SEDL_ISAR_ISA_ISAR_RESET_ON;
782				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
783							SEDL_ISAR_ISA_ISAR_RESET_OFF;
784			}
785			cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
786			cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
787			test_and_set_bit(HW_ISAR, &cs->HW_Flags);
788			cs->irq_func = &sedlbauer_interrupt_isar;
789			cs->auxcmd = &isar_auxcmd;
790			ISACVersion(cs, "Sedlbauer:");
791			cs->BC_Read_Reg = &ReadISAR;
792			cs->BC_Write_Reg = &WriteISAR;
793			cs->BC_Send_Data = &isar_fill_fifo;
794			bytecnt = 3;
795			while (bytecnt) {
796				ver = ISARVersion(cs, "Sedlbauer:");
797				if (ver < 0)
798					printk(KERN_WARNING
799						"Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
800				else
801					break;
802				reset_sedlbauer(cs);
803				bytecnt--;
804			}
805			if (!bytecnt) {
806				release_io_sedlbauer(cs);
807				return (0);
808			}
809		} else {
810			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
811				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
812				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
813				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
814				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
815				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
816				cs->irq_flags |= IRQF_SHARED;
817			} else {
818				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
819				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
820				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
821				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
822				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
823			}
824			cs->irq_func = &sedlbauer_interrupt;
825			ISACVersion(cs, "Sedlbauer:");
826
827			if (HscxVersion(cs, "Sedlbauer:")) {
828				printk(KERN_WARNING
829					"Sedlbauer: wrong HSCX versions check IO address\n");
830				release_io_sedlbauer(cs);
831				return (0);
832			}
833		}
834	}
835	return (1);
836}
837