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/pci.h>
  29#include <linux/isapnp.h>
  30#include <linux/kmod.h>
  31#include <linux/slab.h>
  32#include <linux/skbuff.h>
  33#include <linux/netdevice.h>
  34#include <linux/delay.h>
  35
  36#include <asm/io.h>
  37
  38#include "hisax_fcpcipnp.h"
  39
  40// debugging cruft
  41#define __debug_variable debug
  42#include "hisax_debug.h"
  43
  44#ifdef CONFIG_HISAX_DEBUG
  45static int debug = 0;
  46/* static int hdlcfifosize = 32; */
  47module_param(debug, int, 0);
  48/* module_param(hdlcfifosize, int, 0); */
  49#endif
  50
  51MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
  52MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
  53
  54static struct pci_device_id fcpci_ids[] = {
  55        { .vendor      = PCI_VENDOR_ID_AVM,
  56          .device      = PCI_DEVICE_ID_AVM_A1,
  57          .subvendor   = PCI_ANY_ID,
  58          .subdevice   = PCI_ANY_ID,
  59          .driver_data = (unsigned long) "Fritz!Card PCI",
  60        },
  61        { .vendor      = PCI_VENDOR_ID_AVM,
  62          .device      = PCI_DEVICE_ID_AVM_A1_V2,
  63          .subvendor   = PCI_ANY_ID,
  64          .subdevice   = PCI_ANY_ID,
  65          .driver_data = (unsigned long) "Fritz!Card PCI v2" },
  66        {}
  67};
  68
  69MODULE_DEVICE_TABLE(pci, fcpci_ids);
  70
  71#ifdef CONFIG_PNP
  72static struct pnp_device_id fcpnp_ids[] __devinitdata = {
  73        { 
  74                .id             = "AVM0900",
  75                .driver_data    = (unsigned long) "Fritz!Card PnP",
  76        },
  77};
  78
  79MODULE_DEVICE_TABLE(isapnp, fcpnp_ids);
  80#endif
  81
  82static int protocol = 2;       /* EURO-ISDN Default */
  83module_param(protocol, int, 0);
  84MODULE_LICENSE("GPL");
  85
  86// ----------------------------------------------------------------------
  87
  88#define  AVM_INDEX              0x04
  89#define  AVM_DATA               0x10
  90
  91#define  AVM_IDX_HDLC_1         0x00
  92#define  AVM_IDX_HDLC_2         0x01
  93#define  AVM_IDX_ISAC_FIFO      0x02
  94#define  AVM_IDX_ISAC_REG_LOW   0x04
  95#define  AVM_IDX_ISAC_REG_HIGH  0x06
  96
  97#define  AVM_STATUS0            0x02
  98
  99#define  AVM_STATUS0_IRQ_ISAC   0x01
 100#define  AVM_STATUS0_IRQ_HDLC   0x02
 101#define  AVM_STATUS0_IRQ_TIMER  0x04
 102#define  AVM_STATUS0_IRQ_MASK   0x07
 103
 104#define  AVM_STATUS0_RESET      0x01
 105#define  AVM_STATUS0_DIS_TIMER  0x02
 106#define  AVM_STATUS0_RES_TIMER  0x04
 107#define  AVM_STATUS0_ENA_IRQ    0x08
 108#define  AVM_STATUS0_TESTBIT    0x10
 109
 110#define  AVM_STATUS1            0x03
 111#define  AVM_STATUS1_ENA_IOM    0x80
 112
 113#define  HDLC_FIFO              0x0
 114#define  HDLC_STATUS            0x4
 115#define  HDLC_CTRL              0x4
 116
 117#define  HDLC_MODE_ITF_FLG      0x01
 118#define  HDLC_MODE_TRANS        0x02
 119#define  HDLC_MODE_CCR_7        0x04
 120#define  HDLC_MODE_CCR_16       0x08
 121#define  HDLC_MODE_TESTLOOP     0x80
 122
 123#define  HDLC_INT_XPR           0x80
 124#define  HDLC_INT_XDU           0x40
 125#define  HDLC_INT_RPR           0x20
 126#define  HDLC_INT_MASK          0xE0
 127
 128#define  HDLC_STAT_RME          0x01
 129#define  HDLC_STAT_RDO          0x10
 130#define  HDLC_STAT_CRCVFRRAB    0x0E
 131#define  HDLC_STAT_CRCVFR       0x06
 132#define  HDLC_STAT_RML_MASK     0xff00
 133
 134#define  HDLC_CMD_XRS           0x80
 135#define  HDLC_CMD_XME           0x01
 136#define  HDLC_CMD_RRS           0x20
 137#define  HDLC_CMD_XML_MASK      0xff00
 138
 139#define  AVM_HDLC_FIFO_1        0x10
 140#define  AVM_HDLC_FIFO_2        0x18
 141
 142#define  AVM_HDLC_STATUS_1      0x14
 143#define  AVM_HDLC_STATUS_2      0x1c
 144
 145#define  AVM_ISACSX_INDEX       0x04
 146#define  AVM_ISACSX_DATA        0x08
 147
 148// ----------------------------------------------------------------------
 149// Fritz!PCI
 150
 151static unsigned char fcpci_read_isac(struct isac *isac, unsigned char offset)
 152{
 153        struct fritz_adapter *adapter = isac->priv;
 154        unsigned char idx = (offset > 0x2f) ? 
 155                AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
 156        unsigned char val;
 157        unsigned long flags;
 158
 159        spin_lock_irqsave(&adapter->hw_lock, flags);
 160        outb(idx, adapter->io + AVM_INDEX);
 161        val = inb(adapter->io + AVM_DATA + (offset & 0xf));
 162        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 163        DBG(0x1000, " port %#x, value %#x",
 164            offset, val);
 165        return val;
 166}
 167
 168static void fcpci_write_isac(struct isac *isac, unsigned char offset,
 169                             unsigned char value)
 170{
 171        struct fritz_adapter *adapter = isac->priv;
 172        unsigned char idx = (offset > 0x2f) ? 
 173                AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
 174        unsigned long flags;
 175
 176        DBG(0x1000, " port %#x, value %#x",
 177            offset, value);
 178        spin_lock_irqsave(&adapter->hw_lock, flags);
 179        outb(idx, adapter->io + AVM_INDEX);
 180        outb(value, adapter->io + AVM_DATA + (offset & 0xf));
 181        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 182}
 183
 184static void fcpci_read_isac_fifo(struct isac *isac, unsigned char * data, 
 185                                 int size)
 186{
 187        struct fritz_adapter *adapter = isac->priv;
 188        unsigned long flags;
 189
 190        spin_lock_irqsave(&adapter->hw_lock, flags);
 191        outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);
 192        insb(adapter->io + AVM_DATA, data, size);
 193        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 194}
 195
 196static void fcpci_write_isac_fifo(struct isac *isac, unsigned char * data, 
 197                                  int size)
 198{
 199        struct fritz_adapter *adapter = isac->priv;
 200        unsigned long flags;
 201
 202        spin_lock_irqsave(&adapter->hw_lock, flags);
 203        outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);
 204        outsb(adapter->io + AVM_DATA, data, size);
 205        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 206}
 207
 208static u32 fcpci_read_hdlc_status(struct fritz_adapter *adapter, int nr)
 209{
 210        u32 val;
 211        int idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
 212        unsigned long flags;
 213
 214        spin_lock_irqsave(&adapter->hw_lock, flags);
 215        outl(idx, adapter->io + AVM_INDEX);
 216        val = inl(adapter->io + AVM_DATA + HDLC_STATUS);
 217        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 218        return val;
 219}
 220
 221static void __fcpci_write_ctrl(struct fritz_bcs *bcs, int which)
 222{
 223        struct fritz_adapter *adapter = bcs->adapter;
 224        int idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
 225
 226        DBG(0x40, "hdlc %c wr%x ctrl %x",
 227            'A' + bcs->channel, which, bcs->ctrl.ctrl);
 228
 229        outl(idx, adapter->io + AVM_INDEX);
 230        outl(bcs->ctrl.ctrl, adapter->io + AVM_DATA + HDLC_CTRL);
 231}
 232
 233static void fcpci_write_ctrl(struct fritz_bcs *bcs, int which)
 234{
 235        struct fritz_adapter *adapter = bcs->adapter;
 236        unsigned long flags;
 237
 238        spin_lock_irqsave(&adapter->hw_lock, flags);
 239        __fcpci_write_ctrl(bcs, which);
 240        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 241}
 242
 243// ----------------------------------------------------------------------
 244// Fritz!PCI v2
 245
 246static unsigned char fcpci2_read_isac(struct isac *isac, unsigned char offset)
 247{
 248        struct fritz_adapter *adapter = isac->priv;
 249        unsigned char val;
 250        unsigned long flags;
 251
 252        spin_lock_irqsave(&adapter->hw_lock, flags);
 253        outl(offset, adapter->io + AVM_ISACSX_INDEX);
 254        val = inl(adapter->io + AVM_ISACSX_DATA);
 255        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 256        DBG(0x1000, " port %#x, value %#x",
 257            offset, val);
 258
 259        return val;
 260}
 261
 262static void fcpci2_write_isac(struct isac *isac, unsigned char offset, 
 263                              unsigned char value)
 264{
 265        struct fritz_adapter *adapter = isac->priv;
 266        unsigned long flags;
 267
 268        DBG(0x1000, " port %#x, value %#x",
 269            offset, value);
 270        spin_lock_irqsave(&adapter->hw_lock, flags);
 271        outl(offset, adapter->io + AVM_ISACSX_INDEX);
 272        outl(value, adapter->io + AVM_ISACSX_DATA);
 273        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 274}
 275
 276static void fcpci2_read_isac_fifo(struct isac *isac, unsigned char * data, 
 277                                  int size)
 278{
 279        struct fritz_adapter *adapter = isac->priv;
 280        int i;
 281        unsigned long flags;
 282
 283        spin_lock_irqsave(&adapter->hw_lock, flags);
 284        outl(0, adapter->io + AVM_ISACSX_INDEX);
 285        for (i = 0; i < size; i++)
 286                data[i] = inl(adapter->io + AVM_ISACSX_DATA);
 287        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 288}
 289
 290static void fcpci2_write_isac_fifo(struct isac *isac, unsigned char * data, 
 291                                   int size)
 292{
 293        struct fritz_adapter *adapter = isac->priv;
 294        int i;
 295        unsigned long flags;
 296
 297        spin_lock_irqsave(&adapter->hw_lock, flags);
 298        outl(0, adapter->io + AVM_ISACSX_INDEX);
 299        for (i = 0; i < size; i++)
 300                outl(data[i], adapter->io + AVM_ISACSX_DATA);
 301        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 302}
 303
 304static u32 fcpci2_read_hdlc_status(struct fritz_adapter *adapter, int nr)
 305{
 306        int offset = nr ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;
 307
 308        return inl(adapter->io + offset);
 309}
 310
 311static void fcpci2_write_ctrl(struct fritz_bcs *bcs, int which)
 312{
 313        struct fritz_adapter *adapter = bcs->adapter;
 314        int offset = bcs->channel ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;
 315
 316        DBG(0x40, "hdlc %c wr%x ctrl %x",
 317            'A' + bcs->channel, which, bcs->ctrl.ctrl);
 318
 319        outl(bcs->ctrl.ctrl, adapter->io + offset);
 320}
 321
 322// ----------------------------------------------------------------------
 323// Fritz!PnP (ISAC access as for Fritz!PCI)
 324
 325static u32 fcpnp_read_hdlc_status(struct fritz_adapter *adapter, int nr)
 326{
 327        unsigned char idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
 328        u32 val;
 329        unsigned long flags;
 330
 331        spin_lock_irqsave(&adapter->hw_lock, flags);
 332        outb(idx, adapter->io + AVM_INDEX);
 333        val = inb(adapter->io + AVM_DATA + HDLC_STATUS);
 334        if (val & HDLC_INT_RPR)
 335                val |= inb(adapter->io + AVM_DATA + HDLC_STATUS + 1) << 8;
 336        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 337        return val;
 338}
 339
 340static void __fcpnp_write_ctrl(struct fritz_bcs *bcs, int which)
 341{
 342        struct fritz_adapter *adapter = bcs->adapter;
 343        unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
 344
 345        DBG(0x40, "hdlc %c wr%x ctrl %x",
 346            'A' + bcs->channel, which, bcs->ctrl.ctrl);
 347
 348        outb(idx, adapter->io + AVM_INDEX);
 349        if (which & 4)
 350                outb(bcs->ctrl.sr.mode, 
 351                     adapter->io + AVM_DATA + HDLC_STATUS + 2);
 352        if (which & 2)
 353                outb(bcs->ctrl.sr.xml, 
 354                     adapter->io + AVM_DATA + HDLC_STATUS + 1);
 355        if (which & 1)
 356                outb(bcs->ctrl.sr.cmd,
 357                     adapter->io + AVM_DATA + HDLC_STATUS + 0);
 358}
 359
 360static void fcpnp_write_ctrl(struct fritz_bcs *bcs, int which)
 361{
 362        struct fritz_adapter *adapter = bcs->adapter;
 363        unsigned long flags;
 364
 365        spin_lock_irqsave(&adapter->hw_lock, flags);
 366        __fcpnp_write_ctrl(bcs, which);
 367        spin_unlock_irqrestore(&adapter->hw_lock, flags);
 368}
 369
 370// ----------------------------------------------------------------------
 371
 372static inline void B_L1L2(struct fritz_bcs *bcs, int pr, void *arg)
 373{
 374        struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if;
 375
 376        DBG(2, "pr %#x", pr);
 377        ifc->l1l2(ifc, pr, arg);
 378}
 379
 380static void hdlc_fill_fifo(struct fritz_bcs *bcs)
 381{
 382        struct fritz_adapter *adapter = bcs->adapter;
 383        struct sk_buff *skb = bcs->tx_skb;
 384        int count;
 385        unsigned long flags;
 386        unsigned char *p;
 387
 388        DBG(0x40, "hdlc_fill_fifo");
 389
 390        BUG_ON(skb->len == 0);
 391
 392        bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME;
 393        if (bcs->tx_skb->len > bcs->fifo_size) {
 394                count = bcs->fifo_size;
 395        } else {
 396                count = bcs->tx_skb->len;
 397                if (bcs->mode != L1_MODE_TRANS)
 398                        bcs->ctrl.sr.cmd |= HDLC_CMD_XME;
 399        }
 400        DBG(0x40, "hdlc_fill_fifo %d/%d", count, bcs->tx_skb->len);
 401        p = bcs->tx_skb->data;
 402        skb_pull(bcs->tx_skb, count);
 403        bcs->tx_cnt += count;
 404        bcs->ctrl.sr.xml = ((count == bcs->fifo_size) ? 0 : count);
 405
 406        switch (adapter->type) {
 407        case AVM_FRITZ_PCI:
 408                spin_lock_irqsave(&adapter->hw_lock, flags);
 409                // sets the correct AVM_INDEX, too
 410                __fcpci_write_ctrl(bcs, 3);
 411                outsl(adapter->io + AVM_DATA + HDLC_FIFO,
 412                      p, (count + 3) / 4);
 413                spin_unlock_irqrestore(&adapter->hw_lock, flags);
 414                break;
 415        case AVM_FRITZ_PCIV2:
 416                fcpci2_write_ctrl(bcs, 3);
 417                outsl(adapter->io + 
 418                      (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),
 419                      p, (count + 3) / 4);
 420                break;
 421        case AVM_FRITZ_PNP:
 422                spin_lock_irqsave(&adapter->hw_lock, flags);
 423                // sets the correct AVM_INDEX, too
 424                __fcpnp_write_ctrl(bcs, 3);
 425                outsb(adapter->io + AVM_DATA, p, count);
 426                spin_unlock_irqrestore(&adapter->hw_lock, flags);
 427                break;
 428        }
 429}
 430
 431static inline void hdlc_empty_fifo(struct fritz_bcs *bcs, int count)
 432{
 433        struct fritz_adapter *adapter = bcs->adapter;
 434        unsigned char *p;
 435        unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
 436
 437        DBG(0x10, "hdlc_empty_fifo %d", count);
 438        if (bcs->rcvidx + count > HSCX_BUFMAX) {
 439                DBG(0x10, "hdlc_empty_fifo: incoming packet too large");
 440                return;
 441        }
 442        p = bcs->rcvbuf + bcs->rcvidx;
 443        bcs->rcvidx += count;
 444        switch (adapter->type) {
 445        case AVM_FRITZ_PCI:
 446                spin_lock(&adapter->hw_lock);
 447                outl(idx, adapter->io + AVM_INDEX);
 448                insl(adapter->io + AVM_DATA + HDLC_FIFO, 
 449                     p, (count + 3) / 4);
 450                spin_unlock(&adapter->hw_lock);
 451                break;
 452        case AVM_FRITZ_PCIV2:
 453                insl(adapter->io + 
 454                     (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),
 455                     p, (count + 3) / 4);
 456                break;
 457        case AVM_FRITZ_PNP:
 458                spin_lock(&adapter->hw_lock);
 459                outb(idx, adapter->io + AVM_INDEX);
 460                insb(adapter->io + AVM_DATA, p, count);
 461                spin_unlock(&adapter->hw_lock);
 462                break;
 463        }
 464}
 465
 466static inline void hdlc_rpr_irq(struct fritz_bcs *bcs, u32 stat)
 467{
 468        struct fritz_adapter *adapter = bcs->adapter;
 469        struct sk_buff *skb;
 470        int len;
 471
 472        if (stat & HDLC_STAT_RDO) {
 473                DBG(0x10, "RDO");
 474                bcs->ctrl.sr.xml = 0;
 475                bcs->ctrl.sr.cmd |= HDLC_CMD_RRS;
 476                adapter->write_ctrl(bcs, 1);
 477                bcs->ctrl.sr.cmd &= ~HDLC_CMD_RRS;
 478                adapter->write_ctrl(bcs, 1);
 479                bcs->rcvidx = 0;
 480                return;
 481        }
 482
 483        len = (stat & HDLC_STAT_RML_MASK) >> 8;
 484        if (len == 0)
 485                len = bcs->fifo_size;
 486
 487        hdlc_empty_fifo(bcs, len);
 488
 489        if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
 490                if (((stat & HDLC_STAT_CRCVFRRAB)== HDLC_STAT_CRCVFR) ||
 491                    (bcs->mode == L1_MODE_TRANS)) {
 492                        skb = dev_alloc_skb(bcs->rcvidx);
 493                        if (!skb) {
 494                                printk(KERN_WARNING "HDLC: receive out of memory\n");
 495                        } else {
 496                                memcpy(skb_put(skb, bcs->rcvidx), bcs->rcvbuf,
 497                                       bcs->rcvidx);
 498                                DBG_SKB(1, skb);
 499                                B_L1L2(bcs, PH_DATA | INDICATION, skb);
 500                        }
 501                        bcs->rcvidx = 0;
 502                } else {
 503                        DBG(0x10, "ch%d invalid frame %#x",
 504                            bcs->channel, stat);
 505                        bcs->rcvidx = 0;
 506                }
 507        }
 508}
 509
 510static inline void hdlc_xdu_irq(struct fritz_bcs *bcs)
 511{
 512        struct fritz_adapter *adapter = bcs->adapter;
 513        
 514
 515        /* Here we lost an TX interrupt, so
 516         * restart transmitting the whole frame.
 517         */
 518        bcs->ctrl.sr.xml = 0;
 519        bcs->ctrl.sr.cmd |= HDLC_CMD_XRS;
 520        adapter->write_ctrl(bcs, 1);
 521        bcs->ctrl.sr.cmd &= ~HDLC_CMD_XRS;
 522
 523        if (!bcs->tx_skb) {
 524                DBG(0x10, "XDU without skb");
 525                adapter->write_ctrl(bcs, 1);
 526                return;
 527        }
 528        /* only hdlc restarts the frame, transparent mode must continue */
 529        if (bcs->mode == L1_MODE_HDLC) {
 530                skb_push(bcs->tx_skb, bcs->tx_cnt);
 531                bcs->tx_cnt = 0;
 532        }
 533}
 534
 535static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
 536{
 537        struct sk_buff *skb;
 538
 539        skb = bcs->tx_skb;
 540        if (!skb)
 541                return;
 542
 543        if (skb->len) {
 544                hdlc_fill_fifo(bcs);
 545                return;
 546        }
 547        bcs->tx_cnt = 0;
 548        bcs->tx_skb = NULL;
 549        B_L1L2(bcs, PH_DATA | CONFIRM, (void *)(unsigned long)skb->truesize);
 550        dev_kfree_skb_irq(skb);
 551}
 552
 553static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
 554{
 555        DBG(0x10, "ch%d stat %#x", bcs->channel, stat);
 556        if (stat & HDLC_INT_RPR) {
 557                DBG(0x10, "RPR");
 558                hdlc_rpr_irq(bcs, stat);
 559        }
 560        if (stat & HDLC_INT_XDU) {
 561                DBG(0x10, "XDU");
 562                hdlc_xdu_irq(bcs);
 563                hdlc_xpr_irq(bcs);
 564                return;
 565        }
 566        if (stat & HDLC_INT_XPR) {
 567                DBG(0x10, "XPR");
 568                hdlc_xpr_irq(bcs);
 569        }
 570}
 571
 572static inline void hdlc_irq(struct fritz_adapter *adapter)
 573{
 574        int nr;
 575        u32 stat;
 576
 577        for (nr = 0; nr < 2; nr++) {
 578                stat = adapter->read_hdlc_status(adapter, nr);
 579                DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);
 580                if (stat & HDLC_INT_MASK)
 581                        hdlc_irq_one(&adapter->bcs[nr], stat);
 582        }
 583}
 584
 585static void modehdlc(struct fritz_bcs *bcs, int mode)
 586{
 587        struct fritz_adapter *adapter = bcs->adapter;
 588        
 589        DBG(0x40, "hdlc %c mode %d --> %d",
 590            'A' + bcs->channel, bcs->mode, mode);
 591
 592        if (bcs->mode == mode)
 593                return;
 594
 595        bcs->fifo_size = 32;
 596        bcs->ctrl.ctrl = 0;
 597        bcs->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
 598        switch (mode) {
 599        case L1_MODE_NULL:
 600                bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
 601                adapter->write_ctrl(bcs, 5);
 602                break;
 603        case L1_MODE_TRANS:
 604        case L1_MODE_HDLC:
 605                bcs->rcvidx = 0;
 606                bcs->tx_cnt = 0;
 607                bcs->tx_skb = NULL;
 608                if (mode == L1_MODE_TRANS) {
 609                        bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
 610                } else {
 611                        bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
 612                }
 613                adapter->write_ctrl(bcs, 5);
 614                bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
 615                adapter->write_ctrl(bcs, 1);
 616                bcs->ctrl.sr.cmd = 0;
 617                break;
 618        }
 619        bcs->mode = mode;
 620}
 621
 622static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
 623{
 624        struct fritz_bcs *bcs = ifc->priv;
 625        struct sk_buff *skb = arg;
 626        int mode;
 627
 628        DBG(0x10, "pr %#x", pr);
 629
 630        switch (pr) {
 631        case PH_DATA | REQUEST:
 632                BUG_ON(bcs->tx_skb);
 633                bcs->tx_skb = skb;
 634                DBG_SKB(1, skb);
 635                hdlc_fill_fifo(bcs);
 636                break;
 637        case PH_ACTIVATE | REQUEST:
 638                mode = (long) arg;
 639                DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
 640                modehdlc(bcs, mode);
 641                B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
 642                break;
 643        case PH_DEACTIVATE | REQUEST:
 644                DBG(4,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
 645                modehdlc(bcs, L1_MODE_NULL);
 646                B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
 647                break;
 648        }
 649}
 650
 651// ----------------------------------------------------------------------
 652
 653static irqreturn_t
 654fcpci2_irq(int intno, void *dev)
 655{
 656        struct fritz_adapter *adapter = dev;
 657        unsigned char val;
 658
 659        val = inb(adapter->io + AVM_STATUS0);
 660        if (!(val & AVM_STATUS0_IRQ_MASK))
 661                /* hopefully a shared  IRQ reqest */
 662                return IRQ_NONE;
 663        DBG(2, "STATUS0 %#x", val);
 664        if (val & AVM_STATUS0_IRQ_ISAC)
 665                isacsx_irq(&adapter->isac);
 666        if (val & AVM_STATUS0_IRQ_HDLC)
 667                hdlc_irq(adapter);
 668        if (val & AVM_STATUS0_IRQ_ISAC)
 669                isacsx_irq(&adapter->isac);
 670        return IRQ_HANDLED;
 671}
 672
 673static irqreturn_t
 674fcpci_irq(int intno, void *dev)
 675{
 676        struct fritz_adapter *adapter = dev;
 677        unsigned char sval;
 678
 679        sval = inb(adapter->io + 2);
 680        if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)
 681                /* possibly a shared  IRQ reqest */
 682                return IRQ_NONE;
 683        DBG(2, "sval %#x", sval);
 684        if (!(sval & AVM_STATUS0_IRQ_ISAC))
 685                isac_irq(&adapter->isac);
 686
 687        if (!(sval & AVM_STATUS0_IRQ_HDLC))
 688                hdlc_irq(adapter);
 689        return IRQ_HANDLED;
 690}
 691
 692// ----------------------------------------------------------------------
 693
 694static inline void fcpci2_init(struct fritz_adapter *adapter)
 695{
 696        outb(AVM_STATUS0_RES_TIMER, adapter->io + AVM_STATUS0);
 697        outb(AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
 698
 699}
 700
 701static inline void fcpci_init(struct fritz_adapter *adapter)
 702{
 703        outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | 
 704             AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
 705
 706        outb(AVM_STATUS1_ENA_IOM | adapter->irq, 
 707             adapter->io + AVM_STATUS1);
 708        mdelay(10);
 709}
 710
 711// ----------------------------------------------------------------------
 712
 713static int __devinit fcpcipnp_setup(struct fritz_adapter *adapter)
 714{
 715        u32 val = 0;
 716        int retval;
 717
 718        DBG(1,"");
 719
 720        isac_init(&adapter->isac); // FIXME is this okay now
 721
 722        retval = -EBUSY;
 723        if (!request_region(adapter->io, 32, "fcpcipnp"))
 724                goto err;
 725
 726        switch (adapter->type) {
 727        case AVM_FRITZ_PCIV2:
 728        case AVM_FRITZ_PCI:
 729                val = inl(adapter->io);
 730                break;
 731        case AVM_FRITZ_PNP:
 732                val = inb(adapter->io);
 733                val |= inb(adapter->io + 1) << 8;
 734                break;
 735        }
 736
 737        DBG(1, "stat %#x Class %X Rev %d",
 738            val, val & 0xff, (val>>8) & 0xff);
 739
 740        spin_lock_init(&adapter->hw_lock);
 741        adapter->isac.priv = adapter;
 742        switch (adapter->type) {
 743        case AVM_FRITZ_PCIV2:
 744                adapter->isac.read_isac       = &fcpci2_read_isac;
 745                adapter->isac.write_isac      = &fcpci2_write_isac;
 746                adapter->isac.read_isac_fifo  = &fcpci2_read_isac_fifo;
 747                adapter->isac.write_isac_fifo = &fcpci2_write_isac_fifo;
 748
 749                adapter->read_hdlc_status     = &fcpci2_read_hdlc_status;
 750                adapter->write_ctrl           = &fcpci2_write_ctrl;
 751                break;
 752        case AVM_FRITZ_PCI:
 753                adapter->isac.read_isac       = &fcpci_read_isac;
 754                adapter->isac.write_isac      = &fcpci_write_isac;
 755                adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;
 756                adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
 757
 758                adapter->read_hdlc_status     = &fcpci_read_hdlc_status;
 759                adapter->write_ctrl           = &fcpci_write_ctrl;
 760                break;
 761        case AVM_FRITZ_PNP:
 762                adapter->isac.read_isac       = &fcpci_read_isac;
 763                adapter->isac.write_isac      = &fcpci_write_isac;
 764                adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;
 765                adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
 766
 767                adapter->read_hdlc_status     = &fcpnp_read_hdlc_status;
 768                adapter->write_ctrl           = &fcpnp_write_ctrl;
 769                break;
 770        }
 771
 772        // Reset
 773        outb(0, adapter->io + AVM_STATUS0);
 774        mdelay(10);
 775        outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0);
 776        mdelay(10);
 777        outb(0, adapter->io + AVM_STATUS0);
 778        mdelay(10);
 779
 780        switch (adapter->type) {
 781        case AVM_FRITZ_PCIV2:
 782                retval = request_irq(adapter->irq, fcpci2_irq, IRQF_SHARED,
 783                                     "fcpcipnp", adapter);
 784                break;
 785        case AVM_FRITZ_PCI:
 786                retval = request_irq(adapter->irq, fcpci_irq, IRQF_SHARED,
 787                                     "fcpcipnp", adapter);
 788                break;
 789        case AVM_FRITZ_PNP:
 790                retval = request_irq(adapter->irq, fcpci_irq, 0,
 791                                     "fcpcipnp", adapter);
 792                break;
 793        }
 794        if (retval)
 795                goto err_region;
 796
 797        switch (adapter->type) {
 798        case AVM_FRITZ_PCIV2:
 799                fcpci2_init(adapter);
 800                isacsx_setup(&adapter->isac);
 801                break;
 802        case AVM_FRITZ_PCI:
 803        case AVM_FRITZ_PNP:
 804                fcpci_init(adapter);
 805                isac_setup(&adapter->isac);
 806                break;
 807        }
 808        val = adapter->read_hdlc_status(adapter, 0);
 809        DBG(0x20, "HDLC A STA %x", val);
 810        val = adapter->read_hdlc_status(adapter, 1);
 811        DBG(0x20, "HDLC B STA %x", val);
 812
 813        adapter->bcs[0].mode = -1;
 814        adapter->bcs[1].mode = -1;
 815        modehdlc(&adapter->bcs[0], L1_MODE_NULL);
 816        modehdlc(&adapter->bcs[1], L1_MODE_NULL);
 817
 818        return 0;
 819
 820 err_region:
 821        release_region(adapter->io, 32);
 822 err:
 823        return retval;
 824}
 825
 826static void __devexit fcpcipnp_release(struct fritz_adapter *adapter)
 827{
 828        DBG(1,"");
 829
 830        outb(0, adapter->io + AVM_STATUS0);
 831        free_irq(adapter->irq, adapter);
 832        release_region(adapter->io, 32);
 833}
 834
 835// ----------------------------------------------------------------------
 836
 837static struct fritz_adapter * __devinit 
 838new_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 __devinit fcpci_probe(struct pci_dev *pdev,
 878                                 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        
 911 err_free:
 912        delete_adapter(adapter);
 913 err:
 914        return retval;
 915}
 916
 917#ifdef CONFIG_PNP
 918static int __devinit 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        
 954 err_free:
 955        delete_adapter(adapter);
 956 err:
 957        return retval;
 958}
 959
 960static void __devexit 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         = __devexit_p(fcpnp_remove),
 975        .id_table       = fcpnp_ids,
 976};
 977#endif
 978
 979static void __devexit 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         = __devexit_p(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