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