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