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