Linux 2.4.0-test7-pre6
[davej-history.git] / drivers / isdn / hisax / sedlbauer.c
blob192c496b0dcb28d71ac4bc88a8fe8f68521335e0
1 /* $Id: sedlbauer.c,v 1.23 2000/06/26 08:59:14 keil Exp $
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
10 * Copyright (C) 1997,1998 Marcus Niemann (for the modifications to
11 * the original file asuscom.c)
13 * Author Marcus Niemann (niemann@www-bib.fh-bielefeld.de)
15 * Thanks to Karsten Keil
16 * Sedlbauer AG for informations
17 * Edgar Toernig
19 * This file is (c) under GNU PUBLIC LICENSE
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
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
42 #define __NO_VERSION__
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>
52 extern const char *CardType[];
54 const char *Sedlbauer_revision = "$Revision: 1.23 $";
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"};
61 #ifndef PCI_VENDOR_ID_TIGERJET
62 #define PCI_VENDOR_ID_TIGERJET 0xe159
63 #endif
64 #ifndef PCI_DEVICE_ID_TIGERJET_100
65 #define PCI_DEVICE_ID_TIGERJET_100 0x0002
66 #endif
67 #define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51
68 #define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53
69 #define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54
70 #define PCI_SUB_ID_SEDLBAUER 0x01
72 #define SEDL_SPEED_CARD_WIN 1
73 #define SEDL_SPEED_STAR 2
74 #define SEDL_SPEED_FAX 3
75 #define SEDL_SPEED_WIN2_PC104 4
76 #define SEDL_SPEED_STAR2 5
77 #define SEDL_SPEED_PCI 6
78 #define SEDL_SPEEDFAX_PYRAMID 7
79 #define SEDL_SPEEDFAX_PCI 8
81 #define SEDL_CHIP_TEST 0
82 #define SEDL_CHIP_ISAC_HSCX 1
83 #define SEDL_CHIP_ISAC_ISAR 2
84 #define SEDL_CHIP_IPAC 3
86 #define SEDL_BUS_ISA 1
87 #define SEDL_BUS_PCI 2
88 #define SEDL_BUS_PCMCIA 3
90 #define byteout(addr,val) outb(val,addr)
91 #define bytein(addr) inb(addr)
93 #define SEDL_HSCX_ISA_RESET_ON 0
94 #define SEDL_HSCX_ISA_RESET_OFF 1
95 #define SEDL_HSCX_ISA_ISAC 2
96 #define SEDL_HSCX_ISA_HSCX 3
97 #define SEDL_HSCX_ISA_ADR 4
99 #define SEDL_HSCX_PCMCIA_RESET 0
100 #define SEDL_HSCX_PCMCIA_ISAC 1
101 #define SEDL_HSCX_PCMCIA_HSCX 2
102 #define SEDL_HSCX_PCMCIA_ADR 4
104 #define SEDL_ISAR_ISA_ISAC 4
105 #define SEDL_ISAR_ISA_ISAR 6
106 #define SEDL_ISAR_ISA_ADR 8
107 #define SEDL_ISAR_ISA_ISAR_RESET_ON 10
108 #define SEDL_ISAR_ISA_ISAR_RESET_OFF 12
110 #define SEDL_IPAC_ANY_ADR 0
111 #define SEDL_IPAC_ANY_IPAC 2
113 #define SEDL_IPAC_PCI_BASE 0
114 #define SEDL_IPAC_PCI_ADR 0xc0
115 #define SEDL_IPAC_PCI_IPAC 0xc8
116 #define SEDL_ISAR_PCI_ADR 0xc8
117 #define SEDL_ISAR_PCI_ISAC 0xd0
118 #define SEDL_ISAR_PCI_ISAR 0xe0
119 #define SEDL_ISAR_PCI_ISAR_RESET_ON 0x01
120 #define SEDL_ISAR_PCI_ISAR_RESET_OFF 0x18
121 #define SEDL_ISAR_PCI_LED1 0x08
122 #define SEDL_ISAR_PCI_LED2 0x10
124 #define SEDL_RESET 0x3 /* same as DOS driver */
126 static inline u_char
127 readreg(unsigned int ale, unsigned int adr, u_char off)
129 register u_char ret;
130 long flags;
132 save_flags(flags);
133 cli();
134 byteout(ale, off);
135 ret = bytein(adr);
136 restore_flags(flags);
137 return (ret);
140 static inline void
141 readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
143 /* fifo read without cli because it's allready done */
145 byteout(ale, off);
146 insb(adr, data, size);
150 static inline void
151 writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
153 long flags;
155 save_flags(flags);
156 cli();
157 byteout(ale, off);
158 byteout(adr, data);
159 restore_flags(flags);
162 static inline void
163 writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
165 /* fifo write without cli because it's allready done */
166 byteout(ale, off);
167 outsb(adr, data, size);
170 /* Interface functions */
172 static u_char
173 ReadISAC(struct IsdnCardState *cs, u_char offset)
175 return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset));
178 static void
179 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
181 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset, value);
184 static void
185 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
187 readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size);
190 static void
191 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
193 writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size);
196 static u_char
197 ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
199 return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80));
202 static void
203 WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
205 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80, value);
208 static void
209 ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
211 readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
214 static void
215 WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
217 writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
220 static u_char
221 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
223 return (readreg(cs->hw.sedl.adr,
224 cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0)));
227 static void
228 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
230 writereg(cs->hw.sedl.adr,
231 cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value);
234 /* ISAR access routines
235 * mode = 0 access with IRQ on
236 * mode = 1 access with IRQ off
237 * mode = 2 access with IRQ off and using last offset
240 static u_char
241 ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
243 if (mode == 0)
244 return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset));
245 else if (mode == 1)
246 byteout(cs->hw.sedl.adr, offset);
247 return(bytein(cs->hw.sedl.hscx));
250 static void
251 WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
253 if (mode == 0)
254 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value);
255 else {
256 if (mode == 1)
257 byteout(cs->hw.sedl.adr, offset);
258 byteout(cs->hw.sedl.hscx, value);
263 * fast interrupt HSCX stuff goes here
266 #define READHSCX(cs, nr, reg) readreg(cs->hw.sedl.adr, \
267 cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0))
268 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.sedl.adr, \
269 cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0), data)
271 #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.sedl.adr, \
272 cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt)
274 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.sedl.adr, \
275 cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt)
277 #include "hscx_irq.c"
279 static void
280 sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs)
282 struct IsdnCardState *cs = dev_id;
283 u_char val;
285 if (!cs) {
286 printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
287 return;
290 if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) {
291 /* The card tends to generate interrupts while being removed
292 causing us to just crash the kernel. bad. */
293 printk(KERN_WARNING "Sedlbauer: card not available!\n");
294 return;
297 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
298 Start_HSCX:
299 if (val)
300 hscx_int_main(cs, val);
301 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
302 Start_ISAC:
303 if (val)
304 isac_interrupt(cs, val);
305 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
306 if (val) {
307 if (cs->debug & L1_DEB_HSCX)
308 debugl1(cs, "HSCX IntStat after IntRoutine");
309 goto Start_HSCX;
311 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
312 if (val) {
313 if (cs->debug & L1_DEB_ISAC)
314 debugl1(cs, "ISAC IntStat after IntRoutine");
315 goto Start_ISAC;
317 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF);
318 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF);
319 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
320 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
321 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0);
322 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0);
325 static void
326 sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
328 struct IsdnCardState *cs = dev_id;
329 u_char ista, val, icnt = 5;
331 if (!cs) {
332 printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
333 return;
335 ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
336 Start_IPAC:
337 if (cs->debug & L1_DEB_IPAC)
338 debugl1(cs, "IPAC ISTA %02X", ista);
339 if (ista & 0x0f) {
340 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
341 if (ista & 0x01)
342 val |= 0x01;
343 if (ista & 0x04)
344 val |= 0x02;
345 if (ista & 0x08)
346 val |= 0x04;
347 if (val)
348 hscx_int_main(cs, val);
350 if (ista & 0x20) {
351 val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80);
352 if (val) {
353 isac_interrupt(cs, val);
356 if (ista & 0x10) {
357 val = 0x01;
358 isac_interrupt(cs, val);
360 ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
361 if ((ista & 0x3f) && icnt) {
362 icnt--;
363 goto Start_IPAC;
365 if (!icnt)
366 if (cs->debug & L1_DEB_ISAC)
367 debugl1(cs, "Sedlbauer IRQ LOOP");
368 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF);
369 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0);
372 static void
373 sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs)
375 struct IsdnCardState *cs = dev_id;
376 u_char val;
377 int cnt = 5;
379 if (!cs) {
380 printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
381 return;
384 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
385 Start_ISAR:
386 if (val & ISAR_IRQSTA)
387 isar_int_main(cs);
388 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
389 Start_ISAC:
390 if (val)
391 isac_interrupt(cs, val);
392 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
393 if ((val & ISAR_IRQSTA) && --cnt) {
394 if (cs->debug & L1_DEB_HSCX)
395 debugl1(cs, "ISAR IntStat after IntRoutine");
396 goto Start_ISAR;
398 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
399 if (val && --cnt) {
400 if (cs->debug & L1_DEB_ISAC)
401 debugl1(cs, "ISAC IntStat after IntRoutine");
402 goto Start_ISAC;
404 if (!cnt)
405 if (cs->debug & L1_DEB_ISAC)
406 debugl1(cs, "Sedlbauer IRQ LOOP");
408 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0);
409 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
410 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
411 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK);
414 void
415 release_io_sedlbauer(struct IsdnCardState *cs)
417 int bytecnt = 8;
419 if (cs->subtyp == SEDL_SPEED_FAX) {
420 bytecnt = 16;
421 } else if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
422 bytecnt = 256;
424 if (cs->hw.sedl.cfg_reg)
425 release_region(cs->hw.sedl.cfg_reg, bytecnt);
428 static void
429 reset_sedlbauer(struct IsdnCardState *cs)
431 long flags;
433 printk(KERN_INFO "Sedlbauer: resetting card\n");
435 if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) &&
436 (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) {
437 if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
438 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
439 save_flags(flags);
440 sti();
441 set_current_state(TASK_UNINTERRUPTIBLE);
442 schedule_timeout((10*HZ)/1000);
443 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
444 set_current_state(TASK_UNINTERRUPTIBLE);
445 schedule_timeout((10*HZ)/1000);
446 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0);
447 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
448 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0);
449 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
450 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
451 restore_flags(flags);
452 } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) &&
453 (cs->hw.sedl.bus == SEDL_BUS_PCI)) {
454 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
455 save_flags(flags);
456 sti();
457 current->state = TASK_UNINTERRUPTIBLE;
458 schedule_timeout((20*HZ)/1000);
459 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
460 current->state = TASK_UNINTERRUPTIBLE;
461 schedule_timeout((20*HZ)/1000);
462 restore_flags(flags);
463 } else {
464 byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */
465 save_flags(flags);
466 sti();
467 set_current_state(TASK_UNINTERRUPTIBLE);
468 schedule_timeout((10*HZ)/1000);
469 byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */
470 set_current_state(TASK_UNINTERRUPTIBLE);
471 schedule_timeout((10*HZ)/1000);
472 restore_flags(flags);
477 static int
478 Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
480 switch (mt) {
481 case CARD_RESET:
482 reset_sedlbauer(cs);
483 return(0);
484 case CARD_RELEASE:
485 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
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 reset_sedlbauer(cs);
491 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
492 ISAR_IRQBIT, 0);
493 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac,
494 ISAC_MASK, 0xFF);
496 release_io_sedlbauer(cs);
497 return(0);
498 case CARD_INIT:
499 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
500 clear_pending_isac_ints(cs);
501 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
502 ISAR_IRQBIT, 0);
503 initisac(cs);
504 initisar(cs);
505 /* Reenable all IRQ */
506 cs->writeisac(cs, ISAC_MASK, 0);
507 /* RESET Receiver and Transmitter */
508 cs->writeisac(cs, ISAC_CMDR, 0x41);
509 } else {
510 inithscxisac(cs, 3);
512 return(0);
513 case CARD_TEST:
514 return(0);
515 case MDL_INFO_CONN:
516 if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
517 return(0);
518 if ((long) arg)
519 cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2;
520 else
521 cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1;
522 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
523 break;
524 case MDL_INFO_REL:
525 if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
526 return(0);
527 if ((long) arg)
528 cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2;
529 else
530 cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1;
531 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
532 break;
534 return(0);
537 static struct pci_dev *dev_sedl __initdata = NULL;
539 __initfunc(int
540 setup_sedlbauer(struct IsdnCard *card))
542 int bytecnt, ver, val;
543 struct IsdnCardState *cs = card->cs;
544 char tmp[64];
545 u16 sub_vendor_id, sub_id;
546 long flags;
548 strcpy(tmp, Sedlbauer_revision);
549 printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
551 if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
552 cs->subtyp = SEDL_SPEED_CARD_WIN;
553 cs->hw.sedl.bus = SEDL_BUS_ISA;
554 cs->hw.sedl.chip = SEDL_CHIP_TEST;
555 } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
556 cs->subtyp = SEDL_SPEED_STAR;
557 cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
558 cs->hw.sedl.chip = SEDL_CHIP_TEST;
559 } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {
560 cs->subtyp = SEDL_SPEED_FAX;
561 cs->hw.sedl.bus = SEDL_BUS_ISA;
562 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
563 } else
564 return (0);
566 bytecnt = 8;
567 if (card->para[1]) {
568 cs->hw.sedl.cfg_reg = card->para[1];
569 cs->irq = card->para[0];
570 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
571 bytecnt = 16;
573 } else {
574 /* Probe for Sedlbauer speed pci */
575 #if CONFIG_PCI
576 if (!pci_present()) {
577 printk(KERN_ERR "Sedlbauer: no PCI bus present\n");
578 return(0);
580 if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
581 PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
582 if (pci_enable_device(dev_sedl))
583 return(0);
584 cs->irq = dev_sedl->irq;
585 if (!cs->irq) {
586 printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
587 return(0);
589 cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
590 } else {
591 printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
592 return(0);
594 cs->irq_flags |= SA_SHIRQ;
595 cs->hw.sedl.bus = SEDL_BUS_PCI;
596 sub_vendor_id = dev_sedl->subsystem_vendor;
597 sub_id = dev_sedl->subsystem_device;
598 printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
599 sub_vendor_id, sub_id);
600 printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
601 cs->hw.sedl.cfg_reg);
602 if (sub_id != PCI_SUB_ID_SEDLBAUER) {
603 printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
604 return(0);
606 if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
607 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
608 cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
609 } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
610 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
611 cs->subtyp = SEDL_SPEEDFAX_PCI;
612 } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
613 cs->hw.sedl.chip = SEDL_CHIP_IPAC;
614 cs->subtyp = SEDL_SPEED_PCI;
615 } else {
616 printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
617 sub_vendor_id);
618 return(0);
620 bytecnt = 256;
621 cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
622 cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
623 byteout(cs->hw.sedl.cfg_reg, 0xff);
624 byteout(cs->hw.sedl.cfg_reg, 0x00);
625 byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
626 byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
627 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
628 save_flags(flags);
629 sti();
630 current->state = TASK_UNINTERRUPTIBLE;
631 schedule_timeout((10*HZ)/1000);
632 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
633 restore_flags(flags);
634 #else
635 printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
636 return (0);
637 #endif /* CONFIG_PCI */
640 /* In case of the sedlbauer pcmcia card, this region is in use,
641 reserved for us by the card manager. So we do not check it
642 here, it would fail. */
643 if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
644 check_region((cs->hw.sedl.cfg_reg), bytecnt)) {
645 printk(KERN_WARNING
646 "HiSax: %s config port %x-%x already in use\n",
647 CardType[card->typ],
648 cs->hw.sedl.cfg_reg,
649 cs->hw.sedl.cfg_reg + bytecnt);
650 return (0);
651 } else {
652 request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn");
655 printk(KERN_INFO
656 "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
657 cs->hw.sedl.cfg_reg,
658 cs->hw.sedl.cfg_reg + bytecnt,
659 cs->irq);
661 cs->BC_Read_Reg = &ReadHSCX;
662 cs->BC_Write_Reg = &WriteHSCX;
663 cs->BC_Send_Data = &hscx_fill_fifo;
664 cs->cardmsg = &Sedl_card_msg;
667 * testing ISA and PCMCIA Cards for IPAC, default is ISAC
668 * do not test for PCI card, because ports are different
669 * and PCI card uses only IPAC (for the moment)
671 if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
672 val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR,
673 cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
674 if (val == 1) {
675 /* IPAC */
676 cs->subtyp = SEDL_SPEED_WIN2_PC104;
677 if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
678 cs->subtyp = SEDL_SPEED_STAR2;
680 cs->hw.sedl.chip = SEDL_CHIP_IPAC;
681 } else {
682 /* ISAC_HSCX oder ISAC_ISAR */
683 if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
684 cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
690 * hw.sedl.chip is now properly set
692 printk(KERN_INFO "Sedlbauer: %s detected\n",
693 Sedlbauer_Types[cs->subtyp]);
696 if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
697 if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
698 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
699 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
700 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
701 } else {
702 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
703 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
704 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
706 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
707 cs->readisac = &ReadISAC_IPAC;
708 cs->writeisac = &WriteISAC_IPAC;
709 cs->readisacfifo = &ReadISACfifo_IPAC;
710 cs->writeisacfifo = &WriteISACfifo_IPAC;
711 cs->irq_func = &sedlbauer_interrupt_ipac;
713 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ID);
714 printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
715 reset_sedlbauer(cs);
716 } else {
717 /* ISAC_HSCX oder ISAC_ISAR */
718 cs->readisac = &ReadISAC;
719 cs->writeisac = &WriteISAC;
720 cs->readisacfifo = &ReadISACfifo;
721 cs->writeisacfifo = &WriteISACfifo;
722 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
723 if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
724 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
725 SEDL_ISAR_PCI_ADR;
726 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
727 SEDL_ISAR_PCI_ISAC;
728 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
729 SEDL_ISAR_PCI_ISAR;
730 } else {
731 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
732 SEDL_ISAR_ISA_ADR;
733 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
734 SEDL_ISAR_ISA_ISAC;
735 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
736 SEDL_ISAR_ISA_ISAR;
737 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
738 SEDL_ISAR_ISA_ISAR_RESET_ON;
739 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
740 SEDL_ISAR_ISA_ISAR_RESET_OFF;
742 cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
743 cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
744 test_and_set_bit(HW_ISAR, &cs->HW_Flags);
745 cs->irq_func = &sedlbauer_interrupt_isar;
746 cs->auxcmd = &isar_auxcmd;
747 ISACVersion(cs, "Sedlbauer:");
748 cs->BC_Read_Reg = &ReadISAR;
749 cs->BC_Write_Reg = &WriteISAR;
750 cs->BC_Send_Data = &isar_fill_fifo;
751 ver = ISARVersion(cs, "Sedlbauer:");
752 if (ver < 0) {
753 printk(KERN_WARNING
754 "Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
755 release_io_sedlbauer(cs);
756 return (0);
758 } else {
759 if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
760 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
761 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
762 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
763 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
764 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
765 } else {
766 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
767 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
768 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
769 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
770 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
772 cs->irq_func = &sedlbauer_interrupt;
773 ISACVersion(cs, "Sedlbauer:");
775 if (HscxVersion(cs, "Sedlbauer:")) {
776 printk(KERN_WARNING
777 "Sedlbauer: wrong HSCX versions check IO address\n");
778 release_io_sedlbauer(cs);
779 return (0);
781 reset_sedlbauer(cs);
784 return (1);