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