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 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                                memcpy(skb_put(skb, bcs->rcvidx), bcs->rcvbuf,
 499                                       bcs->rcvidx);
 500                                DBG_SKB(1, skb);
 501                                B_L1L2(bcs, PH_DATA | INDICATION, skb);
 502                        }
 503                        bcs->rcvidx = 0;
 504                } else {
 505                        DBG(0x10, "ch%d invalid frame %#x",
 506                            bcs->channel, stat);
 507                        bcs->rcvidx = 0;
 508                }
 509        }
 510}
 511
 512static inline void hdlc_xdu_irq(struct fritz_bcs *bcs)
 513{
 514        struct fritz_adapter *adapter = bcs->adapter;
 515
 516
 517        /* Here we lost an TX interrupt, so
 518         * restart transmitting the whole frame.
 519         */
 520        bcs->ctrl.sr.xml = 0;
 521        bcs->ctrl.sr.cmd |= HDLC_CMD_XRS;
 522        adapter->write_ctrl(bcs, 1);
 523        bcs->ctrl.sr.cmd &= ~HDLC_CMD_XRS;
 524
 525        if (!bcs->tx_skb) {
 526                DBG(0x10, "XDU without skb");
 527                adapter->write_ctrl(bcs, 1);
 528                return;
 529        }
 530        /* only hdlc restarts the frame, transparent mode must continue */
 531        if (bcs->mode == L1_MODE_HDLC) {
 532                skb_push(bcs->tx_skb, bcs->tx_cnt);
 533                bcs->tx_cnt = 0;
 534        }
 535}
 536
 537static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
 538{
 539        struct sk_buff *skb;
 540
 541        skb = bcs->tx_skb;
 542        if (!skb)
 543                return;
 544
 545        if (skb->len) {
 546                hdlc_fill_fifo(bcs);
 547                return;
 548        }
 549        bcs->tx_cnt = 0;
 550        bcs->tx_skb = NULL;
 551        B_L1L2(bcs, PH_DATA | CONFIRM, (void *)(unsigned long)skb->truesize);
 552        dev_kfree_skb_irq(skb);
 553}
 554
 555static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
 556{
 557        DBG(0x10, "ch%d stat %#x", bcs->channel, stat);
 558        if (stat & HDLC_INT_RPR) {
 559                DBG(0x10, "RPR");
 560                hdlc_rpr_irq(bcs, stat);
 561        }
 562        if (stat & HDLC_INT_XDU) {
 563                DBG(0x10, "XDU");
 564                hdlc_xdu_irq(bcs);
 565                hdlc_xpr_irq(bcs);
 566                return;
 567        }
 568        if (stat & HDLC_INT_XPR) {
 569                DBG(0x10, "XPR");
 570                hdlc_xpr_irq(bcs);
 571        }
 572}
 573
 574static inline void hdlc_irq(struct fritz_adapter *adapter)
 575{
 576        int nr;
 577        u32 stat;
 578
 579        for (nr = 0; nr < 2; nr++) {
 580                stat = adapter->read_hdlc_status(adapter, nr);
 581                DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);
 582                if (stat & HDLC_INT_MASK)
 583                        hdlc_irq_one(&adapter->bcs[nr], stat);
 584        }
 585}
 586
 587static void modehdlc(struct fritz_bcs *bcs, int mode)
 588{
 589        struct fritz_adapter *adapter = bcs->adapter;
 590
 591        DBG(0x40, "hdlc %c mode %d --> %d",
 592            'A' + bcs->channel, bcs->mode, mode);
 593
 594        if (bcs->mode == mode)
 595                return;
 596
 597        bcs->fifo_size = 32;
 598        bcs->ctrl.ctrl = 0;
 599        bcs->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
 600        switch (mode) {
 601        case L1_MODE_NULL:
 602                bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
 603                adapter->write_ctrl(bcs, 5);
 604                break;
 605        case L1_MODE_TRANS:
 606        case L1_MODE_HDLC:
 607                bcs->rcvidx = 0;
 608                bcs->tx_cnt = 0;
 609                bcs->tx_skb = NULL;
 610                if (mode == L1_MODE_TRANS) {
 611                        bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
 612                } else {
 613                        bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
 614                }
 615                adapter->write_ctrl(bcs, 5);
 616                bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
 617                adapter->write_ctrl(bcs, 1);
 618                bcs->ctrl.sr.cmd = 0;
 619                break;
 620        }
 621        bcs->mode = mode;
 622}
 623
 624static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
 625{
 626        struct fritz_bcs *bcs = ifc->priv;
 627        struct sk_buff *skb = arg;
 628        int mode;
 629
 630        DBG(0x10, "pr %#x", pr);
 631
 632        switch (pr) {
 633        case PH_DATA | REQUEST:
 634                BUG_ON(bcs->tx_skb);
 635                bcs->tx_skb = skb;
 636                DBG_SKB(1, skb);
 637                hdlc_fill_fifo(bcs);
 638                break;
 639        case PH_ACTIVATE | REQUEST:
 640                mode = (long) arg;
 641                DBG(4, "B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
 642                modehdlc(bcs, mode);
 643                B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
 644                break;
 645        case PH_DEACTIVATE | REQUEST:
 646                DBG(4, "B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
 647                modehdlc(bcs, L1_MODE_NULL);
 648                B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
 649                break;
 650        }
 651}
 652
 653// ----------------------------------------------------------------------
 654
 655static irqreturn_t
 656fcpci2_irq(int intno, void *dev)
 657{
 658        struct fritz_adapter *adapter = dev;
 659        unsigned char val;
 660
 661        val = inb(adapter->io + AVM_STATUS0);
 662        if (!(val & AVM_STATUS0_IRQ_MASK))
 663                /* hopefully a shared  IRQ reqest */
 664                return IRQ_NONE;
 665        DBG(2, "STATUS0 %#x", val);
 666        if (val & AVM_STATUS0_IRQ_ISAC)
 667                isacsx_irq(&adapter->isac);
 668        if (val & AVM_STATUS0_IRQ_HDLC)
 669                hdlc_irq(adapter);
 670        if (val & AVM_STATUS0_IRQ_ISAC)
 671                isacsx_irq(&adapter->isac);
 672        return IRQ_HANDLED;
 673}
 674
 675static irqreturn_t
 676fcpci_irq(int intno, void *dev)
 677{
 678        struct fritz_adapter *adapter = dev;
 679        unsigned char sval;
 680
 681        sval = inb(adapter->io + 2);
 682        if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)
 683                /* possibly a shared  IRQ reqest */
 684                return IRQ_NONE;
 685        DBG(2, "sval %#x", sval);
 686        if (!(sval & AVM_STATUS0_IRQ_ISAC))
 687                isac_irq(&adapter->isac);
 688
 689        if (!(sval & AVM_STATUS0_IRQ_HDLC))
 690                hdlc_irq(adapter);
 691        return IRQ_HANDLED;
 692}
 693
 694// ----------------------------------------------------------------------
 695
 696static inline void fcpci2_init(struct fritz_adapter *adapter)
 697{
 698        outb(AVM_STATUS0_RES_TIMER, adapter->io + AVM_STATUS0);
 699        outb(AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
 700
 701}
 702
 703static inline void fcpci_init(struct fritz_adapter *adapter)
 704{
 705        outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
 706             AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
 707
 708        outb(AVM_STATUS1_ENA_IOM | adapter->irq,
 709             adapter->io + AVM_STATUS1);
 710        mdelay(10);
 711}
 712
 713// ----------------------------------------------------------------------
 714
 715static int fcpcipnp_setup(struct fritz_adapter *adapter)
 716{
 717        u32 val = 0;
 718        int retval;
 719
 720        DBG(1, "");
 721
 722        isac_init(&adapter->isac); // FIXME is this okay now
 723
 724        retval = -EBUSY;
 725        if (!request_region(adapter->io, 32, "fcpcipnp"))
 726                goto err;
 727
 728        switch (adapter->type) {
 729        case AVM_FRITZ_PCIV2:
 730        case AVM_FRITZ_PCI:
 731                val = inl(adapter->io);
 732                break;
 733        case AVM_FRITZ_PNP:
 734                val = inb(adapter->io);
 735                val |= inb(adapter->io + 1) << 8;
 736                break;
 737        }
 738
 739        DBG(1, "stat %#x Class %X Rev %d",
 740            val, val & 0xff, (val >> 8) & 0xff);
 741
 742        spin_lock_init(&adapter->hw_lock);
 743        adapter->isac.priv = adapter;
 744        switch (adapter->type) {
 745        case AVM_FRITZ_PCIV2:
 746                adapter->isac.read_isac       = &fcpci2_read_isac;
 747                adapter->isac.write_isac      = &fcpci2_write_isac;
 748                adapter->isac.read_isac_fifo  = &fcpci2_read_isac_fifo;
 749                adapter->isac.write_isac_fifo = &fcpci2_write_isac_fifo;
 750
 751                adapter->read_hdlc_status     = &fcpci2_read_hdlc_status;
 752                adapter->write_ctrl           = &fcpci2_write_ctrl;
 753                break;
 754        case AVM_FRITZ_PCI:
 755                adapter->isac.read_isac       = &fcpci_read_isac;
 756                adapter->isac.write_isac      = &fcpci_write_isac;
 757                adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;
 758                adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
 759
 760                adapter->read_hdlc_status     = &fcpci_read_hdlc_status;
 761                adapter->write_ctrl           = &fcpci_write_ctrl;
 762                break;
 763        case AVM_FRITZ_PNP:
 764                adapter->isac.read_isac       = &fcpci_read_isac;
 765                adapter->isac.write_isac      = &fcpci_write_isac;
 766                adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;
 767                adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
 768
 769                adapter->read_hdlc_status     = &fcpnp_read_hdlc_status;
 770                adapter->write_ctrl           = &fcpnp_write_ctrl;
 771                break;
 772        }
 773
 774        // Reset
 775        outb(0, adapter->io + AVM_STATUS0);
 776        mdelay(10);
 777        outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0);
 778        mdelay(10);
 779        outb(0, adapter->io + AVM_STATUS0);
 780        mdelay(10);
 781
 782        switch (adapter->type) {
 783        case AVM_FRITZ_PCIV2:
 784                retval = request_irq(adapter->irq, fcpci2_irq, IRQF_SHARED,
 785                                     "fcpcipnp", adapter);
 786                break;
 787        case AVM_FRITZ_PCI:
 788                retval = request_irq(adapter->irq, fcpci_irq, IRQF_SHARED,
 789                                     "fcpcipnp", adapter);
 790                break;
 791        case AVM_FRITZ_PNP:
 792                retval = request_irq(adapter->irq, fcpci_irq, 0,
 793                                     "fcpcipnp", adapter);
 794                break;
 795        }
 796        if (retval)
 797                goto err_region;
 798
 799        switch (adapter->type) {
 800        case AVM_FRITZ_PCIV2:
 801                fcpci2_init(adapter);
 802                isacsx_setup(&adapter->isac);
 803                break;
 804        case AVM_FRITZ_PCI:
 805        case AVM_FRITZ_PNP:
 806                fcpci_init(adapter);
 807                isac_setup(&adapter->isac);
 808                break;
 809        }
 810        val = adapter->read_hdlc_status(adapter, 0);
 811        DBG(0x20, "HDLC A STA %x", val);
 812        val = adapter->read_hdlc_status(adapter, 1);
 813        DBG(0x20, "HDLC B STA %x", val);
 814
 815        adapter->bcs[0].mode = -1;
 816        adapter->bcs[1].mode = -1;
 817        modehdlc(&adapter->bcs[0], L1_MODE_NULL);
 818        modehdlc(&adapter->bcs[1], L1_MODE_NULL);
 819
 820        return 0;
 821
 822err_region:
 823        release_region(adapter->io, 32);
 824err:
 825        return retval;
 826}
 827
 828static void fcpcipnp_release(struct fritz_adapter *adapter)
 829{
 830        DBG(1, "");
 831
 832        outb(0, adapter->io + AVM_STATUS0);
 833        free_irq(adapter->irq, adapter);
 834        release_region(adapter->io, 32);
 835}
 836
 837// ----------------------------------------------------------------------
 838
 839static struct fritz_adapter *new_adapter(void)
 840{
 841        struct fritz_adapter *adapter;
 842        struct hisax_b_if *b_if[2];
 843        int i;
 844
 845        adapter = kzalloc(sizeof(struct fritz_adapter), GFP_KERNEL);
 846        if (!adapter)
 847                return NULL;
 848
 849        adapter->isac.hisax_d_if.owner = THIS_MODULE;
 850        adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;
 851        adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;
 852
 853        for (i = 0; i < 2; i++) {
 854                adapter->bcs[i].adapter = adapter;
 855                adapter->bcs[i].channel = i;
 856                adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
 857                adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1;
 858        }
 859
 860        for (i = 0; i < 2; i++)
 861                b_if[i] = &adapter->bcs[i].b_if;
 862
 863        if (hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp",
 864                           protocol) != 0) {
 865                kfree(adapter);
 866                adapter = NULL;
 867        }
 868
 869        return adapter;
 870}
 871
 872static void delete_adapter(struct fritz_adapter *adapter)
 873{
 874        hisax_unregister(&adapter->isac.hisax_d_if);
 875        kfree(adapter);
 876}
 877
 878static int fcpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 879{
 880        struct fritz_adapter *adapter;
 881        int retval;
 882
 883        retval = -ENOMEM;
 884        adapter = new_adapter();
 885        if (!adapter)
 886                goto err;
 887
 888        pci_set_drvdata(pdev, adapter);
 889
 890        if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2)
 891                adapter->type = AVM_FRITZ_PCIV2;
 892        else
 893                adapter->type = AVM_FRITZ_PCI;
 894
 895        retval = pci_enable_device(pdev);
 896        if (retval)
 897                goto err_free;
 898
 899        adapter->io = pci_resource_start(pdev, 1);
 900        adapter->irq = pdev->irq;
 901
 902        printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
 903               (char *) ent->driver_data, pci_name(pdev));
 904
 905        retval = fcpcipnp_setup(adapter);
 906        if (retval)
 907                goto err_free;
 908
 909        return 0;
 910
 911err_free:
 912        delete_adapter(adapter);
 913err:
 914        return retval;
 915}
 916
 917#ifdef CONFIG_PNP
 918static int fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 919{
 920        struct fritz_adapter *adapter;
 921        int retval;
 922
 923        if (!pdev)
 924                return (-ENODEV);
 925
 926        retval = -ENOMEM;
 927        adapter = new_adapter();
 928        if (!adapter)
 929                goto err;
 930
 931        pnp_set_drvdata(pdev, adapter);
 932
 933        adapter->type = AVM_FRITZ_PNP;
 934
 935        pnp_disable_dev(pdev);
 936        retval = pnp_activate_dev(pdev);
 937        if (retval < 0) {
 938                printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __func__,
 939                       (char *)dev_id->driver_data, retval);
 940                goto err_free;
 941        }
 942        adapter->io = pnp_port_start(pdev, 0);
 943        adapter->irq = pnp_irq(pdev, 0);
 944
 945        printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",
 946               (char *) dev_id->driver_data, adapter->io, adapter->irq);
 947
 948        retval = fcpcipnp_setup(adapter);
 949        if (retval)
 950                goto err_free;
 951
 952        return 0;
 953
 954err_free:
 955        delete_adapter(adapter);
 956err:
 957        return retval;
 958}
 959
 960static void fcpnp_remove(struct pnp_dev *pdev)
 961{
 962        struct fritz_adapter *adapter = pnp_get_drvdata(pdev);
 963
 964        if (adapter) {
 965                fcpcipnp_release(adapter);
 966                delete_adapter(adapter);
 967        }
 968        pnp_disable_dev(pdev);
 969}
 970
 971static struct pnp_driver fcpnp_driver = {
 972        .name           = "fcpnp",
 973        .probe          = fcpnp_probe,
 974        .remove         = fcpnp_remove,
 975        .id_table       = fcpnp_ids,
 976};
 977#endif
 978
 979static void fcpci_remove(struct pci_dev *pdev)
 980{
 981        struct fritz_adapter *adapter = pci_get_drvdata(pdev);
 982
 983        fcpcipnp_release(adapter);
 984        pci_disable_device(pdev);
 985        delete_adapter(adapter);
 986}
 987
 988static struct pci_driver fcpci_driver = {
 989        .name           = "fcpci",
 990        .probe          = fcpci_probe,
 991        .remove         = fcpci_remove,
 992        .id_table       = fcpci_ids,
 993};
 994
 995static int __init hisax_fcpcipnp_init(void)
 996{
 997        int retval;
 998
 999        printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
1000
1001        retval = pci_register_driver(&fcpci_driver);
1002        if (retval)
1003                return retval;
1004#ifdef CONFIG_PNP
1005        retval = pnp_register_driver(&fcpnp_driver);
1006        if (retval < 0) {
1007                pci_unregister_driver(&fcpci_driver);
1008                return retval;
1009        }
1010#endif
1011        return 0;
1012}
1013
1014static void __exit hisax_fcpcipnp_exit(void)
1015{
1016#ifdef CONFIG_PNP
1017        pnp_unregister_driver(&fcpnp_driver);
1018#endif
1019        pci_unregister_driver(&fcpci_driver);
1020}
1021
1022module_init(hisax_fcpcipnp_init);
1023module_exit(hisax_fcpcipnp_exit);
1024