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