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