Fix typos.
[linux-2.6/linux-mips.git] / drivers / isdn / hisax / sedlbauer.c
blob1ffff0814392c0043b96e3c56412aefe881dc8fa
1 /* $Id: sedlbauer.c,v 1.25.6.6 2001/09/23 22:24:51 kai Exp $
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
10 * Author Marcus Niemann
11 * Copyright by Marcus Niemann <niemann@www-bib.fh-bielefeld.de>
13 * This software may be used and distributed according to the terms
14 * of the GNU General Public License, incorporated herein by reference.
16 * Thanks to Karsten Keil
17 * Sedlbauer AG for informations
18 * Edgar Toernig
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
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
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>
52 extern const char *CardType[];
53 static spinlock_t sedlbauer_lock = SPIN_LOCK_UNLOCKED;
55 const char *Sedlbauer_revision = "$Revision: 1.25.6.6 $";
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"};
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
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
76 #define SEDL_CHIP_ISAC_HSCX 1
77 #define SEDL_CHIP_ISAC_ISAR 2
78 #define SEDL_CHIP_IPAC 3
80 #define SEDL_BUS_ISA 1
81 #define SEDL_BUS_PCI 2
82 #define SEDL_BUS_PCMCIA 3
84 #define byteout(addr,val) outb(val,addr)
85 #define bytein(addr) inb(addr)
87 #define SEDL_HSCX_ISA_RESET_ON 0
88 #define SEDL_HSCX_ISA_RESET_OFF 1
89 #define SEDL_HSCX_ISA_ISAC 2
90 #define SEDL_HSCX_ISA_HSCX 3
91 #define SEDL_HSCX_ISA_ADR 4
93 #define SEDL_HSCX_PCMCIA_RESET 0
94 #define SEDL_HSCX_PCMCIA_ISAC 1
95 #define SEDL_HSCX_PCMCIA_HSCX 2
96 #define SEDL_HSCX_PCMCIA_ADR 4
98 #define SEDL_ISAR_ISA_ISAC 4
99 #define SEDL_ISAR_ISA_ISAR 6
100 #define SEDL_ISAR_ISA_ADR 8
101 #define SEDL_ISAR_ISA_ISAR_RESET_ON 10
102 #define SEDL_ISAR_ISA_ISAR_RESET_OFF 12
104 #define SEDL_IPAC_ANY_ADR 0
105 #define SEDL_IPAC_ANY_IPAC 2
107 #define SEDL_IPAC_PCI_BASE 0
108 #define SEDL_IPAC_PCI_ADR 0xc0
109 #define SEDL_IPAC_PCI_IPAC 0xc8
110 #define SEDL_ISAR_PCI_ADR 0xc8
111 #define SEDL_ISAR_PCI_ISAC 0xd0
112 #define SEDL_ISAR_PCI_ISAR 0xe0
113 #define SEDL_ISAR_PCI_ISAR_RESET_ON 0x01
114 #define SEDL_ISAR_PCI_ISAR_RESET_OFF 0x18
115 #define SEDL_ISAR_PCI_LED1 0x08
116 #define SEDL_ISAR_PCI_LED2 0x10
118 #define SEDL_RESET 0x3 /* same as DOS driver */
120 static inline u8
121 readreg(struct IsdnCardState *cs, unsigned int adr, u8 off)
123 u8 ret;
124 unsigned long flags;
126 spin_lock_irqsave(&sedlbauer_lock, flags);
127 byteout(cs->hw.sedl.adr, off);
128 ret = bytein(adr);
129 spin_unlock_irqrestore(&sedlbauer_lock, flags);
130 return ret;
133 static inline void
134 readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
136 unsigned long flags;
138 spin_lock_irqsave(&sedlbauer_lock, flags);
139 byteout(cs->hw.sedl.adr, off);
140 insb(adr, data, size);
141 spin_unlock_irqrestore(&sedlbauer_lock, flags);
145 static inline void
146 writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data)
148 byteout(cs->hw.sedl.adr, off);
149 byteout(adr, data);
152 static inline void
153 writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size)
155 byteout(cs->hw.sedl.adr, off);
156 outsb(adr, data, size);
159 static u8
160 isac_read(struct IsdnCardState *cs, u8 offset)
162 return readreg(cs, cs->hw.sedl.isac, offset);
165 static void
166 isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
168 writereg(cs, cs->hw.sedl.isac, offset, value);
171 static void
172 isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
174 readfifo(cs, cs->hw.sedl.isac, 0, data, size);
177 static void
178 isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
180 writefifo(cs, cs->hw.sedl.isac, 0, data, size);
183 static struct dc_hw_ops isac_ops = {
184 .read_reg = isac_read,
185 .write_reg = isac_write,
186 .read_fifo = isac_read_fifo,
187 .write_fifo = isac_write_fifo,
190 static u8
191 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
193 return readreg(cs, cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0));
196 static void
197 hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
199 writereg(cs, cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value);
202 static void
203 hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
205 readfifo(cs, cs->hw.sedl.hscx, hscx ? 0x40 : 0, data, size);
208 static void
209 hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
211 writefifo(cs, cs->hw.sedl.hscx, hscx ? 0x40 : 0, data, size);
214 static struct bc_hw_ops hscx_ops = {
215 .read_reg = hscx_read,
216 .write_reg = hscx_write,
217 .read_fifo = hscx_read_fifo,
218 .write_fifo = hscx_write_fifo,
221 static inline u8
222 ipac_read(struct IsdnCardState *cs, u8 offset)
224 return readreg(cs, cs->hw.sedl.isac, offset);
227 static inline void
228 ipac_write(struct IsdnCardState *cs, u8 offset, u8 value)
230 writereg(cs, cs->hw.sedl.isac, offset, value);
233 static inline void
234 ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
236 readfifo(cs, cs->hw.sedl.isac, offset, data, size);
239 static inline void
240 ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size)
242 writefifo(cs, cs->hw.sedl.isac, offset, data, size);
245 /* This will generate ipac_dc_ops and ipac_bc_ops using the functions
246 * above */
248 BUILD_IPAC_OPS(ipac);
251 /* ISAR access routines
252 * mode = 0 access with IRQ on
253 * mode = 1 access with IRQ off
254 * mode = 2 access with IRQ off and using last offset
257 static u8
258 isar_read(struct IsdnCardState *cs, int mode, u8 offset)
260 if (mode == 0)
261 return readreg(cs, cs->hw.sedl.hscx, offset);
263 if (mode == 1)
264 byteout(cs->hw.sedl.adr, offset);
266 return bytein(cs->hw.sedl.hscx);
269 static void
270 isar_write(struct IsdnCardState *cs, int mode, u8 offset, u8 value)
272 if (mode == 0)
273 return writereg(cs, cs->hw.sedl.hscx, offset, value);
275 if (mode == 1)
276 byteout(cs->hw.sedl.adr, offset);
278 byteout(cs->hw.sedl.hscx, value);
281 static struct bc_hw_ops isar_ops = {
282 .read_reg = isar_read,
283 .write_reg = isar_write,
286 static irqreturn_t
287 sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs)
289 struct IsdnCardState *cs = dev_id;
291 if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) {
292 /* The card tends to generate interrupts while being removed
293 causing us to just crash the kernel. bad. */
294 printk(KERN_WARNING "Sedlbauer: card not available!\n");
295 return IRQ_NONE;
297 return hscxisac_irq(intno, dev_id, regs);
300 static irqreturn_t
301 sedlbauer_isar_interrupt(int intno, void *dev_id, struct pt_regs *regs)
303 struct IsdnCardState *cs = dev_id;
304 u8 val;
305 int cnt = 5;
307 spin_lock(&cs->lock);
308 val = isar_read(cs, 0, ISAR_IRQBIT);
309 Start_ISAR:
310 if (val & ISAR_IRQSTA)
311 isar_int_main(cs);
312 val = isac_read(cs, ISAC_ISTA);
313 Start_ISAC:
314 if (val)
315 isac_interrupt(cs, val);
316 val = isar_read(cs, 0, ISAR_IRQBIT);
317 if ((val & ISAR_IRQSTA) && --cnt) {
318 if (cs->debug & L1_DEB_HSCX)
319 debugl1(cs, "ISAR IntStat after IntRoutine");
320 goto Start_ISAR;
322 val = isac_read(cs, ISAC_ISTA);
323 if (val && --cnt) {
324 if (cs->debug & L1_DEB_ISAC)
325 debugl1(cs, "ISAC IntStat after IntRoutine");
326 goto Start_ISAC;
328 if (!cnt)
329 if (cs->debug & L1_DEB_ISAC)
330 debugl1(cs, "Sedlbauer IRQ LOOP");
332 isar_write(cs, 0, ISAR_IRQBIT, 0);
333 isac_write(cs, ISAC_MASK, 0xFF);
334 isac_write(cs, ISAC_MASK, 0x0);
335 isar_write(cs, 0, ISAR_IRQBIT, ISAR_IRQMSK);
336 spin_unlock(&cs->lock);
337 return IRQ_HANDLED;
340 static int
341 sedlbauer_ipac_reset(struct IsdnCardState *cs)
343 writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
344 set_current_state(TASK_UNINTERRUPTIBLE);
345 schedule_timeout((10*HZ)/1000);
346 writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
347 set_current_state(TASK_UNINTERRUPTIBLE);
348 schedule_timeout((10*HZ)/1000);
349 writereg(cs, cs->hw.sedl.isac, IPAC_CONF, 0x0);
350 writereg(cs, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
351 writereg(cs, cs->hw.sedl.isac, IPAC_AOE, 0x0);
352 writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
353 writereg(cs, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
354 return 0;
357 static int
358 sedlbauer_isar_pci_reset(struct IsdnCardState *cs)
360 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
361 current->state = TASK_UNINTERRUPTIBLE;
362 schedule_timeout((20*HZ)/1000);
363 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
364 current->state = TASK_UNINTERRUPTIBLE;
365 schedule_timeout((20*HZ)/1000);
366 return 0;
369 static int
370 sedlbauer_reset(struct IsdnCardState *cs)
372 printk(KERN_INFO "Sedlbauer: resetting card\n");
373 if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA &&
374 cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX)
375 return 0;
377 if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
378 return sedlbauer_ipac_reset(cs);
379 } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) &&
380 (cs->hw.sedl.bus == SEDL_BUS_PCI)) {
381 return sedlbauer_isar_pci_reset(cs);
382 } else {
383 byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */
384 set_current_state(TASK_UNINTERRUPTIBLE);
385 schedule_timeout((10*HZ)/1000);
386 byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */
387 set_current_state(TASK_UNINTERRUPTIBLE);
388 schedule_timeout((10*HZ)/1000);
390 return 0;
393 static void
394 sedlbauer_isar_release(struct IsdnCardState *cs)
396 isar_write(cs, 0, ISAR_IRQBIT, 0);
397 isac_write(cs, ISAC_MASK, 0xFF);
398 sedlbauer_reset(cs);
399 isar_write(cs, 0, ISAR_IRQBIT, 0);
400 isac_write(cs, ISAC_MASK, 0xFF);
401 hisax_release_resources(cs);
404 static void
405 sedlbauer_led_handler(struct IsdnCardState *cs)
407 if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
408 return;
410 if (cs->status & 0x2000)
411 cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2;
412 else
413 cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2;
415 if (cs->status & 0x1000)
416 cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1;
417 else
418 cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1;
420 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
423 static void
424 sedlbauer_isar_init(struct IsdnCardState *cs)
426 isar_write(cs, 0, ISAR_IRQBIT, 0);
427 initisac(cs);
428 initisar(cs);
431 static struct card_ops sedlbauer_ops = {
432 .init = inithscxisac,
433 .reset = sedlbauer_reset,
434 .release = hisax_release_resources,
435 .led_handler = sedlbauer_led_handler,
436 .irq_func = sedlbauer_interrupt,
439 static struct card_ops sedlbauer_ipac_ops = {
440 .init = ipac_init,
441 .reset = sedlbauer_reset,
442 .release = hisax_release_resources,
443 .led_handler = sedlbauer_led_handler,
444 .irq_func = ipac_irq,
447 static struct card_ops sedlbauer_isar_ops = {
448 .init = sedlbauer_isar_init,
449 .reset = sedlbauer_reset,
450 .release = sedlbauer_isar_release,
451 .led_handler = sedlbauer_led_handler,
452 .irq_func = sedlbauer_isar_interrupt,
455 static int __init
456 sedl_ipac_probe(struct IsdnCardState *cs)
458 u8 val;
460 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
461 val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
462 printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
463 return (val == 1 || val == 2);
466 static int __init
467 sedl_ipac_init(struct IsdnCardState *cs)
469 cs->card_ops = &sedlbauer_ipac_ops;
470 if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
471 return -ENODEV;
472 sedlbauer_reset(cs);
473 return 0;
476 static int __init
477 sedl_isac_isar_init(struct IsdnCardState *cs)
479 cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
480 cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
481 __set_bit(HW_ISAR, &cs->HW_Flags);
482 cs->card_ops = &sedlbauer_isar_ops;
483 cs->auxcmd = &isar_auxcmd;
484 isac_setup(cs, &isac_ops);
485 return isar_setup(cs, &isar_ops);
488 static int __init
489 sedl_isac_hscx_init(struct IsdnCardState *cs)
491 cs->card_ops = &sedlbauer_ops;
492 if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
493 return -ENODEV;
494 sedlbauer_reset(cs);
495 return 0;
498 static int __init
499 sedl_card_win_probe(struct IsdnCardState *cs, struct IsdnCard *card)
501 cs->irq = card->para[0];
502 cs->hw.sedl.cfg_reg = card->para[1];
503 cs->hw.sedl.bus = SEDL_BUS_ISA;
504 if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 8, "sedlbauer isdn"))
505 goto err;
507 if (sedl_ipac_probe(cs)) {
508 cs->subtyp = SEDL_SPEED_WIN2_PC104;
509 cs->hw.sedl.chip = SEDL_CHIP_IPAC;
510 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
511 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
512 if (sedl_ipac_init(cs))
513 goto err;
514 } else {
515 cs->subtyp = SEDL_SPEED_CARD_WIN;
516 cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
517 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
518 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
519 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
520 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
521 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
522 if (sedl_isac_hscx_init(cs))
523 goto err;
525 printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
526 Sedlbauer_Types[cs->subtyp],
527 cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
529 return 0;
530 err:
531 hisax_release_resources(cs);
532 return -EBUSY;
535 static int __init
536 sedl_star_probe(struct IsdnCardState *cs, struct IsdnCard *card)
538 cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
539 if (sedl_ipac_probe(cs)) {
540 cs->subtyp = SEDL_SPEED_STAR2;
541 cs->hw.sedl.chip = SEDL_CHIP_IPAC;
542 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
543 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
544 if (sedl_ipac_init(cs))
545 goto err;
546 } else {
547 cs->subtyp = SEDL_SPEED_STAR;
548 cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
549 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
550 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
551 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
552 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
553 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
554 if (sedl_isac_hscx_init(cs))
555 goto err;
557 printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
558 Sedlbauer_Types[cs->subtyp],
559 cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
561 return 0;
562 err:
563 hisax_release_resources(cs);
564 return -EBUSY;
567 static int __init
568 sedl_fax_probe(struct IsdnCardState *cs, struct IsdnCard *card)
570 cs->subtyp = SEDL_SPEED_FAX;
571 cs->hw.sedl.bus = SEDL_BUS_ISA;
572 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
573 if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 16, "sedlbauer isdn"))
574 goto err;
576 printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
577 Sedlbauer_Types[cs->subtyp],
578 cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 16, cs->irq);
580 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR;
581 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC;
582 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR;
583 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON;
584 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF;
585 if (sedl_isac_isar_init(cs))
586 goto err;
588 return 0;
589 err:
590 hisax_release_resources(cs);
591 return -EBUSY;
594 static int __init
595 sedl_pci_init(struct IsdnCardState *cs, struct pci_dev *pdev)
597 cs->irq = pdev->irq;
598 cs->irq_flags |= SA_SHIRQ;
599 cs->hw.sedl.cfg_reg = pci_resource_start(pdev, 0);
600 cs->hw.sedl.bus = SEDL_BUS_PCI;
602 if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 256, "sedlbauer isdn"))
603 return -EBUSY;
605 printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
606 Sedlbauer_Types[cs->subtyp],
607 cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 256, cs->irq);
609 cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
610 cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
611 byteout(cs->hw.sedl.cfg_reg, 0xff);
612 byteout(cs->hw.sedl.cfg_reg, 0x00);
613 byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
614 byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
615 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
616 current->state = TASK_UNINTERRUPTIBLE;
617 schedule_timeout((10*HZ)/1000);
618 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
619 return 0;
622 static int __init
623 sedl_fax_pyramid_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
625 if (pci_enable_device(pdev))
626 goto err;
628 cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
629 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
630 if (sedl_pci_init(cs, pdev))
631 goto err;
633 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
634 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
635 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
636 if (sedl_isac_isar_init(cs))
637 goto err;
639 return 0;
640 err:
641 hisax_release_resources(cs);
642 return -EBUSY;
645 static int __init
646 sedl_fax_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
648 if (pci_enable_device(pdev))
649 goto err;
651 cs->subtyp = SEDL_SPEEDFAX_PCI;
652 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
654 if (sedl_pci_init(cs, pdev))
655 goto err;
657 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
658 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
659 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
660 if (sedl_isac_isar_init(cs))
661 goto err;
663 return 0;
664 err:
665 hisax_release_resources(cs);
666 return -EBUSY;
669 static int __init
670 sedl_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
672 if (pci_enable_device(pdev))
673 goto err;
675 cs->subtyp = SEDL_SPEED_PCI;
676 cs->hw.sedl.chip = SEDL_CHIP_IPAC;
677 if (sedl_pci_init(cs, pdev))
678 goto err;
680 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
681 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
682 if (sedl_ipac_init(cs))
683 goto err;
684 return 0;
685 err:
686 hisax_release_resources(cs);
687 return -EBUSY;
690 static struct pci_dev *dev_sedl __devinitdata = NULL;
692 #ifdef __ISAPNP__
693 static struct isapnp_device_id sedl_ids[] __initdata = {
694 { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
695 ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
696 (unsigned long) "Speed win" },
697 { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
698 ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
699 (unsigned long) "Speed Fax+" },
700 { 0, }
703 static struct isapnp_device_id *pdev = &sedl_ids[0];
704 static struct pnp_card *pnp_c __devinitdata = NULL;
705 #endif
707 int __devinit
708 setup_sedlbauer(struct IsdnCard *card)
710 struct IsdnCardState *cs = card->cs;
711 char tmp[64];
712 u16 sub_vendor_id, sub_id;
714 strcpy(tmp, Sedlbauer_revision);
715 printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n",
716 HiSax_getrev(tmp));
718 if (card->para[1]) {
719 if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
720 if (sedl_card_win_probe(card->cs, card) < 0)
721 return 0;
722 return 1;
723 } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
724 if (sedl_star_probe(card->cs, card) < 0)
725 return 0;
726 return 1;
727 } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {
728 if (sedl_fax_probe(card->cs, card) < 0)
729 return 0;
730 return 1;
733 #ifdef __ISAPNP__
734 if (isapnp_present()) {
735 struct pnp_card *pb;
736 struct pnp_dev *pd;
738 while(pdev->card_vendor) {
739 if ((pb = pnp_find_card(pdev->card_vendor,
740 pdev->card_device,
741 pnp_c))) {
742 pnp_c = pb;
743 pd = NULL;
744 if ((pd = pnp_find_dev(pnp_c,
745 pdev->vendor,
746 pdev->function,
747 pd))) {
748 printk(KERN_INFO "HiSax: %s detected\n",
749 (char *)pdev->driver_data);
750 if (pnp_device_attach(pd) < 0) {
751 printk(KERN_ERR "Sedlbauer PnP: attach failed\n");
752 return 0;
754 if (pnp_activate_dev(pd) < 0) {
755 printk(KERN_ERR "Sedlbauer PnP: activate failed\n");
756 pnp_device_detach(pd);
757 return 0;
759 if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
760 printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
761 pnp_irq(pd, 0), pnp_port_start(pd, 0));
762 pnp_device_detach(pd);
763 goto err;
765 card->para[1] = pnp_port_start(pd, 0);
766 card->para[0] = pnp_irq(pd, 0);
767 cs->hw.sedl.cfg_reg = card->para[1];
768 cs->irq = card->para[0];
769 if (pdev->function == ISAPNP_FUNCTION(0x2)) {
770 if (sedl_fax_probe(card->cs, card))
771 return 0;
772 return 1;
773 } else {
774 if (sedl_card_win_probe(card->cs, card))
775 return 0;
776 return 1;
778 } else {
779 printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
780 goto err;
783 pdev++;
784 pnp_c=NULL;
786 if (!pdev->card_vendor) {
787 printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
790 #endif
791 /* Probe for Sedlbauer speed pci */
792 #ifdef CONFIG_PCI
793 dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
794 PCI_DEVICE_ID_TIGERJET_100, dev_sedl);
795 if (dev_sedl) {
796 sub_vendor_id = dev_sedl->subsystem_vendor;
797 sub_id = dev_sedl->subsystem_device;
798 printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
799 sub_vendor_id, sub_id);
800 if (sub_id != PCI_SUB_ID_SEDLBAUER) {
801 printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
802 return 0;
804 if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
805 if (sedl_fax_pyramid_probe(cs, dev_sedl))
806 return 0;
807 return 1;
808 } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
809 if (sedl_fax_pci_probe(cs, dev_sedl))
810 return 0;
811 return 1;
812 } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
813 if (sedl_pci_probe(cs, dev_sedl))
814 return 0;
815 return 1;
817 printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
818 sub_vendor_id);
819 return 0;
821 #endif /* CONFIG_PCI */
822 return 0;