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[] = {
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 = &sedl_ids[0];
531 static struct pnp_card *pnp_c = NULL;
532 
setup_sedlbauer_isapnp(struct IsdnCard * card,int * bytecnt)533 static int setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
534 {
535 	struct IsdnCardState *cs = card->cs;
536 	struct pnp_dev *pnp_d;
537 
538 	if (!isapnp_present())
539 		return -1;
540 
541 	while (ipid->card_vendor) {
542 		if ((pnp_c = pnp_find_card(ipid->card_vendor,
543 					   ipid->card_device, pnp_c))) {
544 			pnp_d = NULL;
545 			if ((pnp_d = pnp_find_dev(pnp_c,
546 						  ipid->vendor, ipid->function, pnp_d))) {
547 				int err;
548 
549 				printk(KERN_INFO "HiSax: %s detected\n",
550 				       (char *)ipid->driver_data);
551 				pnp_disable_dev(pnp_d);
552 				err = pnp_activate_dev(pnp_d);
553 				if (err < 0) {
554 					printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
555 					       __func__, err);
556 					return (0);
557 				}
558 				card->para[1] = pnp_port_start(pnp_d, 0);
559 				card->para[0] = pnp_irq(pnp_d, 0);
560 
561 				if (card->para[0] == -1 || !card->para[1]) {
562 					printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
563 					       card->para[0], card->para[1]);
564 					pnp_disable_dev(pnp_d);
565 					return (0);
566 				}
567 				cs->hw.sedl.cfg_reg = card->para[1];
568 				cs->irq = card->para[0];
569 				if (ipid->function == ISAPNP_FUNCTION(0x2)) {
570 					cs->subtyp = SEDL_SPEED_FAX;
571 					cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
572 					*bytecnt = 16;
573 				} else {
574 					cs->subtyp = SEDL_SPEED_CARD_WIN;
575 					cs->hw.sedl.chip = SEDL_CHIP_TEST;
576 				}
577 
578 				return (1);
579 			} else {
580 				printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
581 				return (0);
582 			}
583 		}
584 		ipid++;
585 		pnp_c = NULL;
586 	}
587 
588 	printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
589 	return -1;
590 }
591 #else
592 
setup_sedlbauer_isapnp(struct IsdnCard * card,int * bytecnt)593 static int setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
594 {
595 	return -1;
596 }
597 #endif /* __ISAPNP__ */
598 
599 #ifdef CONFIG_PCI
600 static struct pci_dev *dev_sedl = NULL;
601 
setup_sedlbauer_pci(struct IsdnCard * card)602 static int setup_sedlbauer_pci(struct IsdnCard *card)
603 {
604 	struct IsdnCardState *cs = card->cs;
605 	u16 sub_vendor_id, sub_id;
606 
607 	if ((dev_sedl = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET,
608 					      PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
609 		if (pci_enable_device(dev_sedl))
610 			return (0);
611 		cs->irq = dev_sedl->irq;
612 		if (!cs->irq) {
613 			printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
614 			return (0);
615 		}
616 		cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
617 	} else {
618 		printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
619 		return (0);
620 	}
621 	cs->irq_flags |= IRQF_SHARED;
622 	cs->hw.sedl.bus = SEDL_BUS_PCI;
623 	sub_vendor_id = dev_sedl->subsystem_vendor;
624 	sub_id = dev_sedl->subsystem_device;
625 	printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
626 	       sub_vendor_id, sub_id);
627 	printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
628 	       cs->hw.sedl.cfg_reg);
629 	if (sub_id != PCI_SUB_ID_SEDLBAUER) {
630 		printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
631 		return (0);
632 	}
633 	if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
634 		cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
635 		cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
636 	} else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
637 		cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
638 		cs->subtyp = SEDL_SPEEDFAX_PCI;
639 	} else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) {
640 		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
641 		cs->subtyp = HST_SAPHIR3;
642 	} else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
643 		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
644 		cs->subtyp = SEDL_SPEED_PCI;
645 	} else {
646 		printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
647 		       sub_vendor_id);
648 		return (0);
649 	}
650 
651 	cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
652 	cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
653 	byteout(cs->hw.sedl.cfg_reg, 0xff);
654 	byteout(cs->hw.sedl.cfg_reg, 0x00);
655 	byteout(cs->hw.sedl.cfg_reg + 2, 0xdd);
656 	byteout(cs->hw.sedl.cfg_reg + 5, 0); /* disable all IRQ */
657 	byteout(cs->hw.sedl.cfg_reg + 3, cs->hw.sedl.reset_on);
658 	mdelay(2);
659 	byteout(cs->hw.sedl.cfg_reg + 3, cs->hw.sedl.reset_off);
660 	mdelay(10);
661 
662 	return (1);
663 }
664 
665 #else
666 
setup_sedlbauer_pci(struct IsdnCard * card)667 static int setup_sedlbauer_pci(struct IsdnCard *card)
668 {
669 	return (1);
670 }
671 
672 #endif /* CONFIG_PCI */
673 
setup_sedlbauer(struct IsdnCard * card)674 int setup_sedlbauer(struct IsdnCard *card)
675 {
676 	int bytecnt = 8, ver, val, rc;
677 	struct IsdnCardState *cs = card->cs;
678 	char tmp[64];
679 
680 	strcpy(tmp, Sedlbauer_revision);
681 	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
682 
683 	if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
684 		cs->subtyp = SEDL_SPEED_CARD_WIN;
685 		cs->hw.sedl.bus = SEDL_BUS_ISA;
686 		cs->hw.sedl.chip = SEDL_CHIP_TEST;
687 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
688 		cs->subtyp = SEDL_SPEED_STAR;
689 		cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
690 		cs->hw.sedl.chip = SEDL_CHIP_TEST;
691 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {
692 		cs->subtyp = SEDL_SPEED_FAX;
693 		cs->hw.sedl.bus = SEDL_BUS_ISA;
694 		cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
695 	} else
696 		return (0);
697 
698 	bytecnt = 8;
699 	if (card->para[1]) {
700 		cs->hw.sedl.cfg_reg = card->para[1];
701 		cs->irq = card->para[0];
702 		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
703 			bytecnt = 16;
704 		}
705 	} else {
706 		rc = setup_sedlbauer_isapnp(card, &bytecnt);
707 		if (!rc)
708 			return (0);
709 		if (rc > 0)
710 			goto ready;
711 
712 		/* Probe for Sedlbauer speed pci */
713 		rc = setup_sedlbauer_pci(card);
714 		if (!rc)
715 			return (0);
716 
717 		bytecnt = 256;
718 	}
719 
720 ready:
721 
722 	/* In case of the sedlbauer pcmcia card, this region is in use,
723 	 * reserved for us by the card manager. So we do not check it
724 	 * here, it would fail.
725 	 */
726 	if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
727 	    !request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn")) {
728 		printk(KERN_WARNING
729 		       "HiSax: %s config port %x-%x already in use\n",
730 		       CardType[card->typ],
731 		       cs->hw.sedl.cfg_reg,
732 		       cs->hw.sedl.cfg_reg + bytecnt);
733 		return (0);
734 	}
735 
736 	printk(KERN_INFO
737 	       "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
738 	       cs->hw.sedl.cfg_reg,
739 	       cs->hw.sedl.cfg_reg + bytecnt,
740 	       cs->irq);
741 
742 	cs->BC_Read_Reg = &ReadHSCX;
743 	cs->BC_Write_Reg = &WriteHSCX;
744 	cs->BC_Send_Data = &hscx_fill_fifo;
745 	cs->cardmsg = &Sedl_card_msg;
746 
747 /*
748  * testing ISA and PCMCIA Cards for IPAC, default is ISAC
749  * do not test for PCI card, because ports are different
750  * and PCI card uses only IPAC (for the moment)
751  */
752 	if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
753 		val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR,
754 			      cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
755 		printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
756 		if ((val == 1) || (val == 2)) {
757 			/* IPAC */
758 			cs->subtyp = SEDL_SPEED_WIN2_PC104;
759 			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
760 				cs->subtyp = SEDL_SPEED_STAR2;
761 			}
762 			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
763 		} else {
764 			/* ISAC_HSCX oder ISAC_ISAR */
765 			if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
766 				cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
767 			}
768 		}
769 	}
770 
771 /*
772  * hw.sedl.chip is now properly set
773  */
774 	printk(KERN_INFO "Sedlbauer: %s detected\n",
775 	       Sedlbauer_Types[cs->subtyp]);
776 
777 	setup_isac(cs);
778 	if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
779 		if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
780 			cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
781 			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
782 			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
783 		} else {
784 			cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
785 			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
786 			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
787 		}
788 		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
789 		cs->readisac = &ReadISAC_IPAC;
790 		cs->writeisac = &WriteISAC_IPAC;
791 		cs->readisacfifo = &ReadISACfifo_IPAC;
792 		cs->writeisacfifo = &WriteISACfifo_IPAC;
793 		cs->irq_func = &sedlbauer_interrupt_ipac;
794 		val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ID);
795 		printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
796 	} else {
797 		/* ISAC_HSCX oder ISAC_ISAR */
798 		cs->readisac = &ReadISAC;
799 		cs->writeisac = &WriteISAC;
800 		cs->readisacfifo = &ReadISACfifo;
801 		cs->writeisacfifo = &WriteISACfifo;
802 		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
803 			if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
804 				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
805 					SEDL_ISAR_PCI_ADR;
806 				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
807 					SEDL_ISAR_PCI_ISAC;
808 				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
809 					SEDL_ISAR_PCI_ISAR;
810 			} else {
811 				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
812 					SEDL_ISAR_ISA_ADR;
813 				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
814 					SEDL_ISAR_ISA_ISAC;
815 				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
816 					SEDL_ISAR_ISA_ISAR;
817 				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
818 					SEDL_ISAR_ISA_ISAR_RESET_ON;
819 				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
820 					SEDL_ISAR_ISA_ISAR_RESET_OFF;
821 			}
822 			cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
823 			cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
824 			test_and_set_bit(HW_ISAR, &cs->HW_Flags);
825 			cs->irq_func = &sedlbauer_interrupt_isar;
826 			cs->auxcmd = &isar_auxcmd;
827 			ISACVersion(cs, "Sedlbauer:");
828 			cs->BC_Read_Reg = &ReadISAR;
829 			cs->BC_Write_Reg = &WriteISAR;
830 			cs->BC_Send_Data = &isar_fill_fifo;
831 			bytecnt = 3;
832 			while (bytecnt) {
833 				ver = ISARVersion(cs, "Sedlbauer:");
834 				if (ver < 0)
835 					printk(KERN_WARNING
836 					       "Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
837 				else
838 					break;
839 				reset_sedlbauer(cs);
840 				bytecnt--;
841 			}
842 			if (!bytecnt) {
843 				release_io_sedlbauer(cs);
844 				return (0);
845 			}
846 		} else {
847 			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
848 				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
849 				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
850 				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
851 				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
852 				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
853 				cs->irq_flags |= IRQF_SHARED;
854 			} else {
855 				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
856 				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
857 				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
858 				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
859 				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
860 			}
861 			cs->irq_func = &sedlbauer_interrupt;
862 			ISACVersion(cs, "Sedlbauer:");
863 
864 			if (HscxVersion(cs, "Sedlbauer:")) {
865 				printk(KERN_WARNING
866 				       "Sedlbauer: wrong HSCX versions check IO address\n");
867 				release_io_sedlbauer(cs);
868 				return (0);
869 			}
870 		}
871 	}
872 	return (1);
873 }
874