linux/drivers/isdn/hisax/hisax_fcpcipnp.c
<<
>>
Prefs
   1/*
   2 * Driver for AVM Fritz!PCI, Fritz!PCI v2, Fritz!PnP ISDN cards
   3 *
   4 * Author       Kai Germaschewski
   5 * Copyright    2001 by Kai Germaschewski  <kai.germaschewski@gmx.de>
   6 *              2001 by Karsten Keil       <keil@isdn4linux.de>
   7 *
   8 * based upon Karsten Keil's original avm_pci.c driver
   9 *
  10 * This software may be used and distributed according to the terms
  11 * of the GNU General Public License, incorporated herein by reference.
  12 *
  13 * Thanks to Wizard Computersysteme GmbH, Bremervoerde and
  14 *           SoHaNet Technology GmbH, Berlin
  15 * for supporting the development of this driver
  16 */
  17
  18
  19/* TODO:
  20 *
  21 * o POWER PC
  22 * o clean up debugging
  23 * o tx_skb at PH_DEACTIVATE time
  24 */
  25
  26#include <linux/module.h>
  27#include <linux/init.h>
  28#include <linux/interrupt.h>
  29#include <linux/pci.h>
  30#include <linux/isapnp.h>
  31#include <linux/kmod.h>
  32#include <linux/slab.h>
  33#include <linux/skbuff.h>
  34#include <linux/netdevice.h>
  35#include <linux/delay.h>
  36
  37#include <asm/io.h>
  38
  39#include "hisax_fcpcipnp.h"
  40
  41// debugging cruft
  42#define __debug_variable debug
  43#include "hisax_debug.h"
  44
  45#ifdef CONFIG_HISAX_DEBUG
  46static int debug = 0;
  47/* static int hdlcfifosize = 32; */
  48module_param(debug, int, 0);
  49/* module_param(hdlcfifosize, int, 0); */
  50#endif
  51
  52MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
  53MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
  54
  55static const struct pci_device_id fcpci_ids[] = {
  56        { .vendor      = PCI_VENDOR_ID_AVM,
  57          .device      = PCI_DEVICE_ID_AVM_A1,
  58          .subvendor   = PCI_ANY_ID,
  59          .subdevice   = PCI_ANY_ID,
  60          .driver_data = (unsigned long) "Fritz!Card PCI",
  61        },
  62        { .vendor      = PCI_VENDOR_ID_AVM,
  63          .device      = PCI_DEVICE_ID_AVM_A1_V2,
  64          .subvendor   = PCI_ANY_ID,
  65          .subdevice   = PCI_ANY_ID,
  66          .driver_data = (unsigned long) "Fritz!Card PCI v2" },
  67        {}
  68};
  69
  70MODULE_DEVICE_TABLE(pci, fcpci_ids);
  71
  72#ifdef CONFIG_PNP
  73static struct pnp_device_id fcpnp_ids[] = {
  74        {
  75                .id             = "AVM0900",
  76                .driver_data    = (unsigned long) "Fritz!Card PnP",
  77        },
  78        { .id = "" }
  79};
  80
  81MODULE_DEVICE_TABLE(pnp, fcpnp_ids);
  82#endif
  83
  84static int protocol = 2;       /* EURO-ISDN Default */
  85module_param(protocol, int, 0);
  86MODULE_LICENSE("GPL");
  87
  88// ----------------------------------------------------------------------
  89
  90#define  AVM_INDEX              0x04
  91#define  AVM_DATA               0x10
  92
  93#define  AVM_IDX_HDLC_1         0x00
  94#define  AVM_IDX_HDLC_2         0x01
  95#define  AVM_IDX_ISAC_FIFO      0x02
  96#define  AVM_IDX_ISAC_REG_LOW   0x04
  97#define  AVM_IDX_ISAC_REG_HIGH  0x06
  98
  99#define  AVM_STATUS0            0x02
 100
 101#define  AVM_STATUS0_IRQ_ISAC   0x01
 102#define  AVM_STATUS0_IRQ_HDLC   0x02
 103#define  AVM_STATUS0_IRQ_TIMER  0x04
 104#define  AVM_STATUS0_IRQ_MASK   0x07
 105
 106#define  AVM_STATUS0_RESET      0x01
 107#define  AVM_STATUS0_DIS_TIMER  0x02
 108#define  AVM_STATUS0_RES_TIMER  0x04
 109#define  AVM_STATUS0_ENA_IRQ    0x08
 110#define  AVM_STATUS0_TESTBIT    0x10
 111
 112#define  AVM_STATUS1            0x03
 113#define  AVM_STATUS1_ENA_IOM    0x80
 114
 115#define  HDLC_FIFO              0x0
 116#define  HDLC_STATUS            0x4
 117#define  HDLC_CTRL              0x4
 118
 119#define  HDLC_MODE_ITF_FLG      0x01
 120#define  HDLC_MODE_TRANS        0x02
 121#define  HDLC_MODE_CCR_7        0x04
 122#define  HDLC_MODE_CCR_16       0x08
 123#define  HDLC_MODE_TESTLOOP     0x80
 124
 125#define  HDLC_INT_XPR           0x80
 126#define  HDLC_INT_XDU           0x40
 127#define  HDLC_INT_RPR           0x20
 128#define  HDLC_INT_MASK          0xE0
 129
 130#define  HDLC_STAT_RME          0x01
 131#define  HDLC_STAT_RDO          0x10
 132#define  HDLC_STAT_CRCVFRRAB    0x0E
 133#define  HDLC_STAT_CRCVFR       0x06
 134#define  HDLC_STAT_RML_MASK     0xff00
 135
 136#define  HDLC_CMD_XRS           0x80
 137#define  HDLC_CMD_XME           0x01
 138#define  HDLC_CMD_RRS           0x20
 139#define  HDLC_CMD_XML_MASK      0xff00
 140
 141#define  AVM_HDLC_FIFO_1        0x10
 142#define  AVM_HDLC_FIFO_2        0x18
 143
 144#define  AVM_HDLC_STATUS_1      0x14
 145#define  AVM_HDLC_STATUS_2      0x1c
 146
 147#define  AVM_ISACSX_INDEX       0x04
 148#define  AVM_ISACSX_DATA        0x08
 149
 150// ----------------------------------------------------------------------
 151// Fritz!PCI
 152
 153static unsigned char fcpci_read_isac(struct isac *isac, unsigned char offset)
 154{
 155        struct fritz_adapter *adapter = isac->priv;
 156        unsigned char idx = (offset > 0x2f) ?
 157                AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
 158        unsigned char val;
 159        unsigned long flags;
 160
 161        spin_lock_irqsave(&adapter->hw_lock, flags);
 162        outb(idx, adapter->io + AVM_INDEX);
 163        val = inb(adapter->io + AVM_DATA + (offset & 0xf));
 164        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 165        DBG(0x1000, " port %#x, value %#x",
 166            offset, val);
 167        return val;
 168}
 169
 170static void fcpci_write_isac(struct isac *isac, unsigned char offset,
 171                             unsigned char value)
 172{
 173        struct fritz_adapter *adapter = isac->priv;
 174        unsigned char idx = (offset > 0x2f) ?
 175                AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
 176        unsigned long flags;
 177
 178        DBG(0x1000, " port %#x, value %#x",
 179            offset, value);
 180        spin_lock_irqsave(&adapter->hw_lock, flags);
 181        outb(idx, adapter->io + AVM_INDEX);
 182        outb(value, adapter->io + AVM_DATA + (offset & 0xf));
 183        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 184}
 185
 186static void fcpci_read_isac_fifo(struct isac *isac, unsigned char *data,
 187                                 int size)
 188{
 189        struct fritz_adapter *adapter = isac->priv;
 190        unsigned long flags;
 191
 192        spin_lock_irqsave(&adapter->hw_lock, flags);
 193        outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);
 194        insb(adapter->io + AVM_DATA, data, size);
 195        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 196}
 197
 198static void fcpci_write_isac_fifo(struct isac *isac, unsigned char *data,
 199                                  int size)
 200{
 201        struct fritz_adapter *adapter = isac->priv;
 202        unsigned long flags;
 203
 204        spin_lock_irqsave(&adapter->hw_lock, flags);
 205        outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);
 206        outsb(adapter->io + AVM_DATA, data, size);
 207        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 208}
 209
 210static u32 fcpci_read_hdlc_status(struct fritz_adapter *adapter, int nr)
 211{
 212        u32 val;
 213        int idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
 214        unsigned long flags;
 215
 216        spin_lock_irqsave(&adapter->hw_lock, flags);
 217        outl(idx, adapter->io + AVM_INDEX);
 218        val = inl(adapter->io + AVM_DATA + HDLC_STATUS);
 219        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 220        return val;
 221}
 222
 223static void __fcpci_write_ctrl(struct fritz_bcs *bcs, int which)
 224{
 225        struct fritz_adapter *adapter = bcs->adapter;
 226        int idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
 227
 228        DBG(0x40, "hdlc %c wr%x ctrl %x",
 229            'A' + bcs->channel, which, bcs->ctrl.ctrl);
 230
 231        outl(idx, adapter->io + AVM_INDEX);
 232        outl(bcs->ctrl.ctrl, adapter->io + AVM_DATA + HDLC_CTRL);
 233}
 234
 235static void fcpci_write_ctrl(struct fritz_bcs *bcs, int which)
 236{
 237        struct fritz_adapter *adapter = bcs->adapter;
 238        unsigned long flags;
 239
 240        spin_lock_irqsave(&adapter->hw_lock, flags);
 241        __fcpci_write_ctrl(bcs, which);
 242        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 243}
 244
 245// ----------------------------------------------------------------------
 246// Fritz!PCI v2
 247
 248static unsigned char fcpci2_read_isac(struct isac *isac, unsigned char offset)
 249{
 250        struct fritz_adapter *adapter = isac->priv;
 251        unsigned char val;
 252        unsigned long flags;
 253
 254        spin_lock_irqsave(&adapter->hw_lock, flags);
 255        outl(offset, adapter->io + AVM_ISACSX_INDEX);
 256        val = inl(adapter->io + AVM_ISACSX_DATA);
 257        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 258        DBG(0x1000, " port %#x, value %#x",
 259            offset, val);
 260
 261        return val;
 262}
 263
 264static void fcpci2_write_isac(struct isac *isac, unsigned char offset,
 265                              unsigned char value)
 266{
 267        struct fritz_adapter *adapter = isac->priv;
 268        unsigned long flags;
 269
 270        DBG(0x1000, " port %#x, value %#x",
 271            offset, value);
 272        spin_lock_irqsave(&adapter->hw_lock, flags);
 273        outl(offset, adapter->io + AVM_ISACSX_INDEX);
 274        outl(value, adapter->io + AVM_ISACSX_DATA);
 275        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 276}
 277
 278static void fcpci2_read_isac_fifo(struct isac *isac, unsigned char *data,
 279                                  int size)
 280{
 281        struct fritz_adapter *adapter = isac->priv;
 282        int i;
 283        unsigned long flags;
 284
 285        spin_lock_irqsave(&adapter->hw_lock, flags);
 286        outl(0, adapter->io + AVM_ISACSX_INDEX);
 287        for (i = 0; i < size; i++)
 288                data[i] = inl(adapter->io + AVM_ISACSX_DATA);
 289        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 290}
 291
 292static void fcpci2_write_isac_fifo(struct isac *isac, unsigned char *data,
 293                                   int size)
 294{
 295        struct fritz_adapter *adapter = isac->priv;
 296        int i;
 297        unsigned long flags;
 298
 299        spin_lock_irqsave(&adapter->hw_lock, flags);
 300        outl(0, adapter->io + AVM_ISACSX_INDEX);
 301        for (i = 0; i < size; i++)
 302                outl(data[i], adapter->io + AVM_ISACSX_DATA);
 303        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 304}
 305
 306static u32 fcpci2_read_hdlc_status(struct fritz_adapter *adapter, int nr)
 307{
 308        int offset = nr ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;
 309
 310        return inl(adapter->io + offset);
 311}
 312
 313static void fcpci2_write_ctrl(struct fritz_bcs *bcs, int which)
 314{
 315        struct fritz_adapter *adapter = bcs->adapter;
 316        int offset = bcs->channel ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;
 317
 318        DBG(0x40, "hdlc %c wr%x ctrl %x",
 319            'A' + bcs->channel, which, bcs->ctrl.ctrl);
 320
 321        outl(bcs->ctrl.ctrl, adapter->io + offset);
 322}
 323
 324// ----------------------------------------------------------------------
 325// Fritz!PnP (ISAC access as for Fritz!PCI)
 326
 327static u32 fcpnp_read_hdlc_status(struct fritz_adapter *adapter, int nr)
 328{
 329        unsigned char idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
 330        u32 val;
 331        unsigned long flags;
 332
 333        spin_lock_irqsave(&adapter->hw_lock, flags);
 334        outb(idx, adapter->io + AVM_INDEX);
 335        val = inb(adapter->io + AVM_DATA + HDLC_STATUS);
 336        if (val & HDLC_INT_RPR)
 337                val |= inb(adapter->io + AVM_DATA + HDLC_STATUS + 1) << 8;
 338        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 339        return val;
 340}
 341
 342static void __fcpnp_write_ctrl(struct fritz_bcs *bcs, int which)
 343{
 344        struct fritz_adapter *adapter = bcs->adapter;
 345        unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
 346
 347        DBG(0x40, "hdlc %c wr%x ctrl %x",
 348            'A' + bcs->channel, which, bcs->ctrl.ctrl);
 349
 350        outb(idx, adapter->io + AVM_INDEX);
 351        if (which & 4)
 352                outb(bcs->ctrl.sr.mode,
 353                     adapter->io + AVM_DATA + HDLC_STATUS + 2);
 354        if (which & 2)
 355                outb(bcs->ctrl.sr.xml,
 356                     adapter->io + AVM_DATA + HDLC_STATUS + 1);
 357        if (which & 1)
 358                outb(bcs->ctrl.sr.cmd,
 359                     adapter->io + AVM_DATA + HDLC_STATUS + 0);
 360}
 361
 362static void fcpnp_write_ctrl(struct fritz_bcs *bcs, int which)
 363{
 364        struct fritz_adapter *adapter = bcs->adapter;
 365        unsigned long flags;
 366
 367        spin_lock_irqsave(&adapter->hw_lock, flags);
 368        __fcpnp_write_ctrl(bcs, which);
 369        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 370}
 371
 372// ----------------------------------------------------------------------
 373
 374static inline void B_L1L2(struct fritz_bcs *bcs, int pr, void *arg)
 375{
 376        struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if;
 377
 378        DBG(2, "pr %#x", pr);
 379        ifc->l1l2(ifc, pr, arg);
 380}
 381
 382static void hdlc_fill_fifo(struct fritz_bcs *bcs)
 383{
 384        struct fritz_adapter *adapter = bcs->adapter;
 385        struct sk_buff *skb = bcs->tx_skb;
 386        int count;
 387        unsigned long flags;
 388        unsigned char *p;
 389
 390        DBG(0x40, "hdlc_fill_fifo");
 391
 392        BUG_ON(skb->len == 0);
 393
 394        bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME;
 395        if (bcs->tx_skb->len > bcs->fifo_size) {
 396                count = bcs->fifo_size;
 397        } else {
 398                count = bcs->tx_skb->len;
 399                if (bcs->mode != L1_MODE_TRANS)
 400                        bcs->ctrl.sr.cmd |= HDLC_CMD_XME;
 401        }
 402        DBG(0x40, "hdlc_fill_fifo %d/%d", count, bcs->tx_skb->len);
 403        p = bcs->tx_skb->data;
 404        skb_pull(bcs->tx_skb, count);
 405        bcs->tx_cnt += count;
 406        bcs->ctrl.sr.xml = ((count == bcs->fifo_size) ? 0 : count);
 407
 408        switch (adapter->type) {
 409        case AVM_FRITZ_PCI:
 410                spin_lock_irqsave(&adapter->hw_lock, flags);
 411                // sets the correct AVM_INDEX, too
 412                __fcpci_write_ctrl(bcs, 3);
 413                outsl(adapter->io + AVM_DATA + HDLC_FIFO,
 414                      p, (count + 3) / 4);
 415                spin_unlock_irqrestore(&adapter->hw_lock, flags);
 416                break;
 417        case AVM_FRITZ_PCIV2:
 418                fcpci2_write_ctrl(bcs, 3);
 419                outsl(adapter->io +
 420                      (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),
 421                      p, (count + 3) / 4);
 422                break;
 423        case AVM_FRITZ_PNP:
 424                spin_lock_irqsave(&adapter->hw_lock, flags);
 425                // sets the correct AVM_INDEX, too
 426                __fcpnp_write_ctrl(bcs, 3);
 427                outsb(adapter->io + AVM_DATA, p, count);
 428                spin_unlock_irqrestore(&adapter->hw_lock, flags);
 429                break;
 430        }
 431}
 432
 433static inline void hdlc_empty_fifo(struct fritz_bcs *bcs, int count)
 434{
 435        struct fritz_adapter *adapter = bcs->adapter;
 436        unsigned char *p;
 437        unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
 438
 439        DBG(0x10, "hdlc_empty_fifo %d", count);
 440        if (bcs->rcvidx + count > HSCX_BUFMAX) {
 441                DBG(0x10, "hdlc_empty_fifo: incoming packet too large");
 442                return;
 443        }
 444        p = bcs->rcvbuf + bcs->rcvidx;
 445        bcs->rcvidx += count;
 446        switch (adapter->type) {
 447        case AVM_FRITZ_PCI:
 448                spin_lock(&adapter->hw_lock);
 449                outl(idx, adapter->io + AVM_INDEX);
 450                insl(adapter->io + AVM_DATA + HDLC_FIFO,
 451                     p, (count + 3) / 4);
 452                spin_unlock(&adapter->hw_lock);
 453                break;
 454        case AVM_FRITZ_PCIV2:
 455                insl(adapter->io +
 456                     (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),
 457                     p, (count + 3) / 4);
 458                break;
 459        case AVM_FRITZ_PNP:
 460                spin_lock(&adapter->hw_lock);
 461                outb(idx, adapter->io + AVM_INDEX);
 462                insb(adapter->io + AVM_DATA, p, count);
 463                spin_unlock(&adapter->hw_lock);
 464                break;
 465        }
 466}
 467
 468static inline void hdlc_rpr_irq(struct fritz_bcs *bcs, u32 stat)
 469{
 470        struct fritz_adapter *adapter = bcs->adapter;
 471        struct sk_buff *skb;
 472        int len;
 473
 474        if (stat & HDLC_STAT_RDO) {
 475                DBG(0x10, "RDO");
 476                bcs->ctrl.sr.xml = 0;
 477                bcs->ctrl.sr.cmd |= HDLC_CMD_RRS;
 478                adapter->write_ctrl(bcs, 1);
 479                bcs->ctrl.sr.cmd &= ~HDLC_CMD_RRS;
 480                adapter->write_ctrl(bcs, 1);
 481                bcs->rcvidx = 0;
 482                return;
 483        }
 484
 485        len = (stat & HDLC_STAT_RML_MASK) >> 8;
 486        if (len == 0)
 487                len = bcs->fifo_size;
 488
 489        hdlc_empty_fifo(bcs, len);
 490
 491        if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
 492                if (((stat & HDLC_STAT_CRCVFRRAB) == HDLC_STAT_CRCVFR) ||
 493                    (bcs->mode == L1_MODE_TRANS)) {
 494                        skb = dev_alloc_skb(bcs->rcvidx);
 495                        if (!skb) {
 496                                printk(KERN_WARNING "HDLC: receive out of memory\n");
 497                        } else {
 498                                skb_put_data(skb, bcs->rcvbuf, bcs->rcvidx);
 499                                DBG_SKB(1, skb);
 500                                B_L1L2(bcs, PH_DATA | INDICATION, skb);
 501                        }
 502                        bcs->rcvidx = 0;
 503                } else {
 504                        DBG(0x10, "ch%d invalid frame %#x",
 505                            bcs->channel, stat);
 506                        bcs->rcvidx = 0;
 507                }
 508        }
 509}
 510
 511static inline void hdlc_xdu_irq(struct fritz_bcs *bcs)
 512{
 513        struct fritz_adapter *adapter = bcs->adapter;
 514
 515
 516        /* Here we lost an TX interrupt, so
 517         * restart transmitting the whole frame.
 518         */
 519        bcs->ctrl.sr.xml = 0;
 520        bcs->ctrl.sr.cmd |= HDLC_CMD_XRS;
 521        adapter->write_ctrl(bcs, 1);
 522        bcs->ctrl.sr.cmd &= ~HDLC_CMD_XRS;
 523
 524        if (!bcs->tx_skb) {
 525                DBG(0x10, "XDU without skb");
 526                adapter->write_ctrl(bcs, 1);
 527                return;
 528        }
 529        /* only hdlc restarts the frame, transparent mode must continue */
 530        if (bcs->mode == L1_MODE_HDLC) {
 531                skb_push(bcs->tx_skb, bcs->tx_cnt);
 532                bcs->tx_cnt = 0;
 533        }
 534}
 535
 536static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
 537{
 538        struct sk_buff *skb;
 539
 540        skb = bcs->tx_skb;
 541        if (!skb)
 542                return;
 543
 544        if (skb->len) {
 545                hdlc_fill_fifo(bcs);
 546                return;
 547        }
 548        bcs->tx_cnt = 0;
 549        bcs->tx_skb = NULL;
 550        B_L1L2(bcs, PH_DATA | CONFIRM, (void *)(unsigned long)skb->truesize);
 551        dev_kfree_skb_irq(skb);
 552}
 553
 554static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
 555{
 556        DBG(0x10, "ch%d stat %#x", bcs->channel, stat);
 557        if (stat & HDLC_INT_RPR) {
 558                DBG(0x10, "RPR");
 559                hdlc_rpr_irq(bcs, stat);
 560        }
 561        if (stat & HDLC_INT_XDU) {
 562                DBG(0x10, "XDU");
 563                hdlc_xdu_irq(bcs);
 564                hdlc_xpr_irq(bcs);
 565                return;
 566        }
 567        if (stat & HDLC_INT_XPR) {
 568                DBG(0x10, "XPR");
 569                hdlc_xpr_irq(bcs);
 570        }
 571}
 572
 573static inline void hdlc_irq(struct fritz_adapter *adapter)
 574{
 575        int nr;
 576        u32 stat;
 577
 578        for (nr = 0; nr < 2; nr++) {
 579                stat = adapter->read_hdlc_status(adapter, nr);
 580                DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);
 581                if (stat & HDLC_INT_MASK)
 582                        hdlc_irq_one(&adapter->bcs[nr], stat);
 583        }
 584}
 585
 586static void modehdlc(struct fritz_bcs *bcs, int mode)
 587{
 588        struct fritz_adapter *adapter = bcs->adapter;
 589
 590        DBG(0x40, "hdlc %c mode %d --> %d",
 591            'A' + bcs->channel, bcs->mode, mode);
 592
 593        if (bcs->mode == mode)
 594                return;
 595
 596        bcs->fifo_size = 32;
 597        bcs->ctrl.ctrl = 0;
 598        bcs->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
 599        switch (mode) {
 600        case L1_MODE_NULL:
 601                bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
 602                adapter->write_ctrl(bcs, 5);
 603                break;
 604        case L1_MODE_TRANS:
 605        case L1_MODE_HDLC:
 606                bcs->rcvidx = 0;
 607                bcs->tx_cnt = 0;
 608                bcs->tx_skb = NULL;
 609                if (mode == L1_MODE_TRANS) {
 610                        bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
 611                } else {
 612                        bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
 613                }
 614                adapter->write_ctrl(bcs, 5);
 615                bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
 616                adapter->write_ctrl(bcs, 1);
 617                bcs->ctrl.sr.cmd = 0;
 618                break;
 619        }
 620        bcs->mode = mode;
 621}
 622
 623static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
 624{
 625        struct fritz_bcs *bcs = ifc->priv;
 626        struct sk_buff *skb = arg;
 627        int mode;
 628
 629        DBG(0x10, "pr %#x", pr);
 630
 631        switch (pr) {
 632        case PH_DATA | REQUEST:
 633                BUG_ON(bcs->tx_skb);
 634                bcs->tx_skb = skb;
 635                DBG_SKB(1, skb);
 636                hdlc_fill_fifo(bcs);
 637                break;
 638        case PH_ACTIVATE | REQUEST:
 639                mode = (long) arg;
 640                DBG(4, "B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
 641                modehdlc(bcs, mode);
 642                B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
 643                break;
 644        case PH_DEACTIVATE | REQUEST:
 645                DBG(4, "B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
 646                modehdlc(bcs, L1_MODE_NULL);
 647                B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
 648                break;
 649        }
 650}
 651
 652// ----------------------------------------------------------------------
 653
 654static irqreturn_t
 655fcpci2_irq(int intno, void *dev)
 656{
 657        struct fritz_adapter *adapter = dev;
 658        unsigned char val;
 659
 660        val = inb(adapter->io + AVM_STATUS0);
 661        if (!(val & AVM_STATUS0_IRQ_MASK))
 662                /* hopefully a shared  IRQ reqest */
 663                return IRQ_NONE;
 664        DBG(2, "STATUS0 %#x", val);
 665        if (val & AVM_STATUS0_IRQ_ISAC)
 666                isacsx_irq(&adapter->isac);
 667        if (val & AVM_STATUS0_IRQ_HDLC)
 668                hdlc_irq(adapter);
 669        if (val & AVM_STATUS0_IRQ_ISAC)
 670                isacsx_irq(&adapter->isac);
 671        return IRQ_HANDLED;
 672}
 673
 674static irqreturn_t
 675fcpci_irq(int intno, void *dev)
 676{
 677        struct fritz_adapter *adapter = dev;
 678        unsigned char sval;
 679
 680        sval = inb(adapter->io + 2);
 681        if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)
 682                /* possibly a shared  IRQ reqest */
 683                return IRQ_NONE;
 684        DBG(2, "sval %#x", sval);
 685        if (!(sval & AVM_STATUS0_IRQ_ISAC))
 686                isac_irq(&adapter->isac);
 687
 688        if (!(sval & AVM_STATUS0_IRQ_HDLC))
 689                hdlc_irq(adapter);
 690        return IRQ_HANDLED;
 691}
 692
 693// ----------------------------------------------------------------------
 694
 695static inline void fcpci2_init(struct fritz_adapter *adapter)
 696{
 697        outb(AVM_STATUS0_RES_TIMER, adapter->io + AVM_STATUS0);
 698        outb(AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
 699
 700}
 701
 702static inline void fcpci_init(struct fritz_adapter *adapter)
 703{
 704        outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
 705             AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
 706
 707        outb(AVM_STATUS1_ENA_IOM | adapter->irq,
 708             adapter->io + AVM_STATUS1);
 709        mdelay(10);
 710}
 711
 712// ----------------------------------------------------------------------
 713
 714static int fcpcipnp_setup(struct fritz_adapter *adapter)
 715{
 716        u32 val = 0;
 717        int retval;
 718
 719        DBG(1, "");
 720
 721        isac_init(&adapter->isac); // FIXME is this okay now
 722
 723        retval = -EBUSY;
 724        if (!request_region(adapter->io, 32, "fcpcipnp"))
 725                goto err;
 726
 727        switch (adapter->type) {
 728        case AVM_FRITZ_PCIV2:
 729        case AVM_FRITZ_PCI:
 730                val = inl(adapter->io);
 731                break;
 732        case AVM_FRITZ_PNP:
 733                val = inb(adapter->io);
 734                val |= inb(adapter->io + 1) << 8;
 735                break;
 736        }
 737
 738        DBG(1, "stat %#x Class %X Rev %d",
 739            val, val & 0xff, (val >> 8) & 0xff);
 740
 741        spin_lock_init(&adapter->hw_lock);
 742        adapter->isac.priv = adapter;
 743        switch (adapter->type) {
 744        case AVM_FRITZ_PCIV2:
 745                adapter->isac.read_isac       = &fcpci2_read_isac;
 746                adapter->isac.write_isac      = &fcpci2_write_isac;
 747                adapter->isac.read_isac_fifo  = &fcpci2_read_isac_fifo;
 748                adapter->isac.write_isac_fifo = &fcpci2_write_isac_fifo;
 749
 750                adapter->read_hdlc_status     = &fcpci2_read_hdlc_status;
 751                adapter->write_ctrl           = &fcpci2_write_ctrl;
 752                break;
 753        case AVM_FRITZ_PCI:
 754                adapter->isac.read_isac       = &fcpci_read_isac;
 755                adapter->isac.write_isac      = &fcpci_write_isac;
 756                adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;
 757                adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
 758
 759                adapter->read_hdlc_status     = &fcpci_read_hdlc_status;
 760                adapter->write_ctrl           = &fcpci_write_ctrl;
 761                break;
 762        case AVM_FRITZ_PNP:
 763                adapter->isac.read_isac       = &fcpci_read_isac;
 764                adapter->isac.write_isac      = &fcpci_write_isac;
 765                adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;
 766                adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
 767
 768                adapter->read_hdlc_status     = &fcpnp_read_hdlc_status;
 769                adapter->write_ctrl           = &fcpnp_write_ctrl;
 770                break;
 771        }
 772
 773        // Reset
 774        outb(0, adapter->io + AVM_STATUS0);
 775        mdelay(10);
 776        outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0);
 777        mdelay(10);
 778        outb(0, adapter->io + AVM_STATUS0);
 779        mdelay(10);
 780
 781        switch (adapter->type) {
 782        case AVM_FRITZ_PCIV2:
 783                retval = request_irq(adapter->irq, fcpci2_irq, IRQF_SHARED,
 784                                     "fcpcipnp", adapter);
 785                break;
 786        case AVM_FRITZ_PCI:
 787                retval = request_irq(adapter->irq, fcpci_irq, IRQF_SHARED,
 788                                     "fcpcipnp", adapter);
 789                break;
 790        case AVM_FRITZ_PNP:
 791                retval = request_irq(adapter->irq, fcpci_irq, 0,
 792                                     "fcpcipnp", adapter);
 793                break;
 794        }
 795        if (retval)
 796                goto err_region;
 797
 798        switch (adapter->type) {
 799        case AVM_FRITZ_PCIV2:
 800                fcpci2_init(adapter);
 801                isacsx_setup(&adapter->isac);
 802                break;
 803        case AVM_FRITZ_PCI:
 804        case AVM_FRITZ_PNP:
 805                fcpci_init(adapter);
 806                isac_setup(&adapter->isac);
 807                break;
 808        }
 809        val = adapter->read_hdlc_status(adapter, 0);
 810        DBG(0x20, "HDLC A STA %x", val);
 811        val = adapter->read_hdlc_status(adapter, 1);
 812        DBG(0x20, "HDLC B STA %x", val);
 813
 814        adapter->bcs[0].mode = -1;
 815        adapter->bcs[1].mode = -1;
 816        modehdlc(&adapter->bcs[0], L1_MODE_NULL);
 817        modehdlc(&adapter->bcs[1], L1_MODE_NULL);
 818
 819        return 0;
 820
 821err_region:
 822        release_region(adapter->io, 32);
 823err:
 824        return retval;
 825}
 826
 827static void fcpcipnp_release(struct fritz_adapter *adapter)
 828{
 829        DBG(1, "");
 830
 831        outb(0, adapter->io + AVM_STATUS0);
 832        free_irq(adapter->irq, adapter);
 833        release_region(adapter->io, 32);
 834}
 835
 836// ----------------------------------------------------------------------
 837
 838static struct fritz_adapter *new_adapter(void)
 839{
 840        struct fritz_adapter *adapter;
 841        struct hisax_b_if *b_if[2];
 842        int i;
 843
 844        adapter = kzalloc(sizeof(struct fritz_adapter), GFP_KERNEL);
 845        if (!adapter)
 846                return NULL;
 847
 848        adapter->isac.hisax_d_if.owner = THIS_MODULE;
 849        adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;
 850        adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;
 851
 852        for (i = 0; i < 2; i++) {
 853                adapter->bcs[i].adapter = adapter;
 854                adapter->bcs[i].channel = i;
 855                adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
 856                adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1;
 857        }
 858
 859        for (i = 0; i < 2; i++)
 860                b_if[i] = &adapter->bcs[i].b_if;
 861
 862        if (hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp",
 863                           protocol) != 0) {
 864                kfree(adapter);
 865                adapter = NULL;
 866        }
 867
 868        return adapter;
 869}
 870
 871static void delete_adapter(struct fritz_adapter *adapter)
 872{
 873        hisax_unregister(&adapter->isac.hisax_d_if);
 874        kfree(adapter);
 875}
 876
 877static int fcpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 878{
 879        struct fritz_adapter *adapter;
 880        int retval;
 881
 882        retval = -ENOMEM;
 883        adapter = new_adapter();
 884        if (!adapter)
 885                goto err;
 886
 887        pci_set_drvdata(pdev, adapter);
 888
 889        if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2)
 890                adapter->type = AVM_FRITZ_PCIV2;
 891        else
 892                adapter->type = AVM_FRITZ_PCI;
 893
 894        retval = pci_enable_device(pdev);
 895        if (retval)
 896                goto err_free;
 897
 898        adapter->io = pci_resource_start(pdev, 1);
 899        adapter->irq = pdev->irq;
 900
 901        printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
 902               (char *) ent->driver_data, pci_name(pdev));
 903
 904        retval = fcpcipnp_setup(adapter);
 905        if (retval)
 906                goto err_free;
 907
 908        return 0;
 909
 910err_free:
 911        delete_adapter(adapter);
 912err:
 913        return retval;
 914}
 915
 916#ifdef CONFIG_PNP
 917static int fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 918{
 919        struct fritz_adapter *adapter;
 920        int retval;
 921
 922        if (!pdev)
 923                return (-ENODEV);
 924
 925        retval = -ENOMEM;
 926        adapter = new_adapter();
 927        if (!adapter)
 928                goto err;
 929
 930        pnp_set_drvdata(pdev, adapter);
 931
 932        adapter->type = AVM_FRITZ_PNP;
 933
 934        pnp_disable_dev(pdev);
 935        retval = pnp_activate_dev(pdev);
 936        if (retval < 0) {
 937                printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __func__,
 938                       (char *)dev_id->driver_data, retval);
 939                goto err_free;
 940        }
 941        adapter->io = pnp_port_start(pdev, 0);
 942        adapter->irq = pnp_irq(pdev, 0);
 943        if (!adapter->io || adapter->irq == -1)
 944                goto err_free;
 945
 946        printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",
 947               (char *) dev_id->driver_data, adapter->io, adapter->irq);
 948
 949        retval = fcpcipnp_setup(adapter);
 950        if (retval)
 951                goto err_free;
 952
 953        return 0;
 954
 955err_free:
 956        delete_adapter(adapter);
 957err:
 958        return retval;
 959}
 960
 961static void fcpnp_remove(struct pnp_dev *pdev)
 962{
 963        struct fritz_adapter *adapter = pnp_get_drvdata(pdev);
 964
 965        if (adapter) {
 966                fcpcipnp_release(adapter);
 967                delete_adapter(adapter);
 968        }
 969        pnp_disable_dev(pdev);
 970}
 971
 972static struct pnp_driver fcpnp_driver = {
 973        .name           = "fcpnp",
 974        .probe          = fcpnp_probe,
 975        .remove         = fcpnp_remove,
 976        .id_table       = fcpnp_ids,
 977};
 978#endif
 979
 980static void fcpci_remove(struct pci_dev *pdev)
 981{
 982        struct fritz_adapter *adapter = pci_get_drvdata(pdev);
 983
 984        fcpcipnp_release(adapter);
 985        pci_disable_device(pdev);
 986        delete_adapter(adapter);
 987}
 988
 989static struct pci_driver fcpci_driver = {
 990        .name           = "fcpci",
 991        .probe          = fcpci_probe,
 992        .remove         = fcpci_remove,
 993        .id_table       = fcpci_ids,
 994};
 995
 996static int __init hisax_fcpcipnp_init(void)
 997{
 998        int retval;
 999
1000        printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
1001
1002        retval = pci_register_driver(&fcpci_driver);
1003        if (retval)
1004                return retval;
1005#ifdef CONFIG_PNP
1006        retval = pnp_register_driver(&fcpnp_driver);
1007        if (retval < 0) {
1008                pci_unregister_driver(&fcpci_driver);
1009                return retval;
1010        }
1011#endif
1012        return 0;
1013}
1014
1015static void __exit hisax_fcpcipnp_exit(void)
1016{
1017#ifdef CONFIG_PNP
1018        pnp_unregister_driver(&fcpnp_driver);
1019#endif
1020        pci_unregister_driver(&fcpci_driver);
1021}
1022
1023module_init(hisax_fcpcipnp_init);
1024module_exit(hisax_fcpcipnp_exit);
1025