linux/drivers/isdn/hisax/avm_pci.c
<<
>>
Prefs
   1/* $Id: avm_pci.c,v 1.29.2.4 2004/02/11 13:21:32 keil Exp $
   2 *
   3 * low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
   4 *
   5 * Author       Karsten Keil
   6 * Copyright    by Karsten Keil      <keil@isdn4linux.de>
   7 *
   8 * This software may be used and distributed according to the terms
   9 * of the GNU General Public License, incorporated herein by reference.
  10 *
  11 * Thanks to AVM, Berlin for information
  12 *
  13 */
  14
  15#include <linux/init.h>
  16#include "hisax.h"
  17#include "isac.h"
  18#include "isdnl1.h"
  19#include <linux/pci.h>
  20#include <linux/slab.h>
  21#include <linux/isapnp.h>
  22#include <linux/interrupt.h>
  23
  24static const char *avm_pci_rev = "$Revision: 1.29.2.4 $";
  25
  26#define  AVM_FRITZ_PCI          1
  27#define  AVM_FRITZ_PNP          2
  28
  29#define  HDLC_FIFO              0x0
  30#define  HDLC_STATUS            0x4
  31
  32#define  AVM_HDLC_1             0x00
  33#define  AVM_HDLC_2             0x01
  34#define  AVM_ISAC_FIFO          0x02
  35#define  AVM_ISAC_REG_LOW       0x04
  36#define  AVM_ISAC_REG_HIGH      0x06
  37
  38#define  AVM_STATUS0_IRQ_ISAC   0x01
  39#define  AVM_STATUS0_IRQ_HDLC   0x02
  40#define  AVM_STATUS0_IRQ_TIMER  0x04
  41#define  AVM_STATUS0_IRQ_MASK   0x07
  42
  43#define  AVM_STATUS0_RESET      0x01
  44#define  AVM_STATUS0_DIS_TIMER  0x02
  45#define  AVM_STATUS0_RES_TIMER  0x04
  46#define  AVM_STATUS0_ENA_IRQ    0x08
  47#define  AVM_STATUS0_TESTBIT    0x10
  48
  49#define  AVM_STATUS1_INT_SEL    0x0f
  50#define  AVM_STATUS1_ENA_IOM    0x80
  51
  52#define  HDLC_MODE_ITF_FLG      0x01
  53#define  HDLC_MODE_TRANS        0x02
  54#define  HDLC_MODE_CCR_7        0x04
  55#define  HDLC_MODE_CCR_16       0x08
  56#define  HDLC_MODE_TESTLOOP     0x80
  57
  58#define  HDLC_INT_XPR           0x80
  59#define  HDLC_INT_XDU           0x40
  60#define  HDLC_INT_RPR           0x20
  61#define  HDLC_INT_MASK          0xE0
  62
  63#define  HDLC_STAT_RME          0x01
  64#define  HDLC_STAT_RDO          0x10
  65#define  HDLC_STAT_CRCVFRRAB    0x0E
  66#define  HDLC_STAT_CRCVFR       0x06
  67#define  HDLC_STAT_RML_MASK     0x3f00
  68
  69#define  HDLC_CMD_XRS           0x80
  70#define  HDLC_CMD_XME           0x01
  71#define  HDLC_CMD_RRS           0x20
  72#define  HDLC_CMD_XML_MASK      0x3f00
  73
  74
  75/* Interface functions */
  76
  77static u_char
  78ReadISAC(struct IsdnCardState *cs, u_char offset)
  79{
  80        register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
  81        register u_char val;
  82
  83        outb(idx, cs->hw.avm.cfg_reg + 4);
  84        val = inb(cs->hw.avm.isac + (offset & 0xf));
  85        return (val);
  86}
  87
  88static void
  89WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  90{
  91        register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
  92
  93        outb(idx, cs->hw.avm.cfg_reg + 4);
  94        outb(value, cs->hw.avm.isac + (offset & 0xf));
  95}
  96
  97static void
  98ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
  99{
 100        outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
 101        insb(cs->hw.avm.isac, data, size);
 102}
 103
 104static void
 105WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
 106{
 107        outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
 108        outsb(cs->hw.avm.isac, data, size);
 109}
 110
 111static inline u_int
 112ReadHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset)
 113{
 114        register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
 115        register u_int val;
 116
 117        outl(idx, cs->hw.avm.cfg_reg + 4);
 118        val = inl(cs->hw.avm.isac + offset);
 119        return (val);
 120}
 121
 122static inline void
 123WriteHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset, u_int value)
 124{
 125        register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
 126
 127        outl(idx, cs->hw.avm.cfg_reg + 4);
 128        outl(value, cs->hw.avm.isac + offset);
 129}
 130
 131static inline u_char
 132ReadHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset)
 133{
 134        register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
 135        register u_char val;
 136
 137        outb(idx, cs->hw.avm.cfg_reg + 4);
 138        val = inb(cs->hw.avm.isac + offset);
 139        return (val);
 140}
 141
 142static inline void
 143WriteHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
 144{
 145        register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
 146
 147        outb(idx, cs->hw.avm.cfg_reg + 4);
 148        outb(value, cs->hw.avm.isac + offset);
 149}
 150
 151static u_char
 152ReadHDLC_s(struct IsdnCardState *cs, int chan, u_char offset)
 153{
 154        return (0xff & ReadHDLCPCI(cs, chan, offset));
 155}
 156
 157static void
 158WriteHDLC_s(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
 159{
 160        WriteHDLCPCI(cs, chan, offset, value);
 161}
 162
 163static inline
 164struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel)
 165{
 166        if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
 167                return (&cs->bcs[0]);
 168        else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
 169                return (&cs->bcs[1]);
 170        else
 171                return (NULL);
 172}
 173
 174static void
 175write_ctrl(struct BCState *bcs, int which) {
 176
 177        if (bcs->cs->debug & L1_DEB_HSCX)
 178                debugl1(bcs->cs, "hdlc %c wr%x ctrl %x",
 179                        'A' + bcs->channel, which, bcs->hw.hdlc.ctrl.ctrl);
 180        if (bcs->cs->subtyp == AVM_FRITZ_PCI) {
 181                WriteHDLCPCI(bcs->cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl.ctrl);
 182        } else {
 183                if (which & 4)
 184                        WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS + 2,
 185                                     bcs->hw.hdlc.ctrl.sr.mode);
 186                if (which & 2)
 187                        WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS + 1,
 188                                     bcs->hw.hdlc.ctrl.sr.xml);
 189                if (which & 1)
 190                        WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS,
 191                                     bcs->hw.hdlc.ctrl.sr.cmd);
 192        }
 193}
 194
 195static void
 196modehdlc(struct BCState *bcs, int mode, int bc)
 197{
 198        struct IsdnCardState *cs = bcs->cs;
 199        int hdlc = bcs->channel;
 200
 201        if (cs->debug & L1_DEB_HSCX)
 202                debugl1(cs, "hdlc %c mode %d --> %d ichan %d --> %d",
 203                        'A' + hdlc, bcs->mode, mode, hdlc, bc);
 204        bcs->hw.hdlc.ctrl.ctrl = 0;
 205        switch (mode) {
 206        case (-1): /* used for init */
 207                bcs->mode = 1;
 208                bcs->channel = bc;
 209                bc = 0;
 210        case (L1_MODE_NULL):
 211                if (bcs->mode == L1_MODE_NULL)
 212                        return;
 213                bcs->hw.hdlc.ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
 214                bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS;
 215                write_ctrl(bcs, 5);
 216                bcs->mode = L1_MODE_NULL;
 217                bcs->channel = bc;
 218                break;
 219        case (L1_MODE_TRANS):
 220                bcs->mode = mode;
 221                bcs->channel = bc;
 222                bcs->hw.hdlc.ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
 223                bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS;
 224                write_ctrl(bcs, 5);
 225                bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
 226                write_ctrl(bcs, 1);
 227                bcs->hw.hdlc.ctrl.sr.cmd = 0;
 228                schedule_event(bcs, B_XMTBUFREADY);
 229                break;
 230        case (L1_MODE_HDLC):
 231                bcs->mode = mode;
 232                bcs->channel = bc;
 233                bcs->hw.hdlc.ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
 234                bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_ITF_FLG;
 235                write_ctrl(bcs, 5);
 236                bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
 237                write_ctrl(bcs, 1);
 238                bcs->hw.hdlc.ctrl.sr.cmd = 0;
 239                schedule_event(bcs, B_XMTBUFREADY);
 240                break;
 241        }
 242}
 243
 244static inline void
 245hdlc_empty_fifo(struct BCState *bcs, int count)
 246{
 247        register u_int *ptr;
 248        u_char *p;
 249        u_char idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1;
 250        int cnt = 0;
 251        struct IsdnCardState *cs = bcs->cs;
 252
 253        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 254                debugl1(cs, "hdlc_empty_fifo %d", count);
 255        if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) {
 256                if (cs->debug & L1_DEB_WARN)
 257                        debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
 258                return;
 259        }
 260        p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
 261        ptr = (u_int *)p;
 262        bcs->hw.hdlc.rcvidx += count;
 263        if (cs->subtyp == AVM_FRITZ_PCI) {
 264                outl(idx, cs->hw.avm.cfg_reg + 4);
 265                while (cnt < count) {
 266#ifdef __powerpc__
 267                        *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac + _IO_BASE));
 268#else
 269                        *ptr++ = inl(cs->hw.avm.isac);
 270#endif /* __powerpc__ */
 271                        cnt += 4;
 272                }
 273        } else {
 274                outb(idx, cs->hw.avm.cfg_reg + 4);
 275                while (cnt < count) {
 276                        *p++ = inb(cs->hw.avm.isac);
 277                        cnt++;
 278                }
 279        }
 280        if (cs->debug & L1_DEB_HSCX_FIFO) {
 281                char *t = bcs->blog;
 282
 283                if (cs->subtyp == AVM_FRITZ_PNP)
 284                        p = (u_char *) ptr;
 285                t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
 286                             bcs->channel ? 'B' : 'A', count);
 287                QuickHex(t, p, count);
 288                debugl1(cs, bcs->blog);
 289        }
 290}
 291
 292static inline void
 293hdlc_fill_fifo(struct BCState *bcs)
 294{
 295        struct IsdnCardState *cs = bcs->cs;
 296        int count, cnt = 0;
 297        int fifo_size = 32;
 298        u_char *p;
 299        u_int *ptr;
 300
 301        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 302                debugl1(cs, "hdlc_fill_fifo");
 303        if (!bcs->tx_skb)
 304                return;
 305        if (bcs->tx_skb->len <= 0)
 306                return;
 307
 308        bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME;
 309        if (bcs->tx_skb->len > fifo_size) {
 310                count = fifo_size;
 311        } else {
 312                count = bcs->tx_skb->len;
 313                if (bcs->mode != L1_MODE_TRANS)
 314                        bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME;
 315        }
 316        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 317                debugl1(cs, "hdlc_fill_fifo %d/%u", count, bcs->tx_skb->len);
 318        p = bcs->tx_skb->data;
 319        ptr = (u_int *)p;
 320        skb_pull(bcs->tx_skb, count);
 321        bcs->tx_cnt -= count;
 322        bcs->hw.hdlc.count += count;
 323        bcs->hw.hdlc.ctrl.sr.xml = ((count == fifo_size) ? 0 : count);
 324        write_ctrl(bcs, 3);  /* sets the correct index too */
 325        if (cs->subtyp == AVM_FRITZ_PCI) {
 326                while (cnt < count) {
 327#ifdef __powerpc__
 328                        out_be32((unsigned *)(cs->hw.avm.isac + _IO_BASE), *ptr++);
 329#else
 330                        outl(*ptr++, cs->hw.avm.isac);
 331#endif /* __powerpc__ */
 332                        cnt += 4;
 333                }
 334        } else {
 335                while (cnt < count) {
 336                        outb(*p++, cs->hw.avm.isac);
 337                        cnt++;
 338                }
 339        }
 340        if (cs->debug & L1_DEB_HSCX_FIFO) {
 341                char *t = bcs->blog;
 342
 343                if (cs->subtyp == AVM_FRITZ_PNP)
 344                        p = (u_char *) ptr;
 345                t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
 346                             bcs->channel ? 'B' : 'A', count);
 347                QuickHex(t, p, count);
 348                debugl1(cs, bcs->blog);
 349        }
 350}
 351
 352static void
 353HDLC_irq(struct BCState *bcs, u_int stat) {
 354        int len;
 355        struct sk_buff *skb;
 356
 357        if (bcs->cs->debug & L1_DEB_HSCX)
 358                debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
 359        if (stat & HDLC_INT_RPR) {
 360                if (stat & HDLC_STAT_RDO) {
 361                        if (bcs->cs->debug & L1_DEB_HSCX)
 362                                debugl1(bcs->cs, "RDO");
 363                        else
 364                                debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
 365                        bcs->hw.hdlc.ctrl.sr.xml = 0;
 366                        bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_RRS;
 367                        write_ctrl(bcs, 1);
 368                        bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS;
 369                        write_ctrl(bcs, 1);
 370                        bcs->hw.hdlc.rcvidx = 0;
 371                } else {
 372                        if (!(len = (stat & HDLC_STAT_RML_MASK) >> 8))
 373                                len = 32;
 374                        hdlc_empty_fifo(bcs, len);
 375                        if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
 376                                if (((stat & HDLC_STAT_CRCVFRRAB) == HDLC_STAT_CRCVFR) ||
 377                                    (bcs->mode == L1_MODE_TRANS)) {
 378                                        if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx)))
 379                                                printk(KERN_WARNING "HDLC: receive out of memory\n");
 380                                        else {
 381                                                memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx),
 382                                                       bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx);
 383                                                skb_queue_tail(&bcs->rqueue, skb);
 384                                        }
 385                                        bcs->hw.hdlc.rcvidx = 0;
 386                                        schedule_event(bcs, B_RCVBUFREADY);
 387                                } else {
 388                                        if (bcs->cs->debug & L1_DEB_HSCX)
 389                                                debugl1(bcs->cs, "invalid frame");
 390                                        else
 391                                                debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat);
 392                                        bcs->hw.hdlc.rcvidx = 0;
 393                                }
 394                        }
 395                }
 396        }
 397        if (stat & HDLC_INT_XDU) {
 398                /* Here we lost an TX interrupt, so
 399                 * restart transmitting the whole frame.
 400                 */
 401                if (bcs->tx_skb) {
 402                        skb_push(bcs->tx_skb, bcs->hw.hdlc.count);
 403                        bcs->tx_cnt += bcs->hw.hdlc.count;
 404                        bcs->hw.hdlc.count = 0;
 405                        if (bcs->cs->debug & L1_DEB_WARN)
 406                                debugl1(bcs->cs, "ch%d XDU", bcs->channel);
 407                } else if (bcs->cs->debug & L1_DEB_WARN)
 408                        debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel);
 409                bcs->hw.hdlc.ctrl.sr.xml = 0;
 410                bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
 411                write_ctrl(bcs, 1);
 412                bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
 413                write_ctrl(bcs, 1);
 414                hdlc_fill_fifo(bcs);
 415        } else if (stat & HDLC_INT_XPR) {
 416                if (bcs->tx_skb) {
 417                        if (bcs->tx_skb->len) {
 418                                hdlc_fill_fifo(bcs);
 419                                return;
 420                        } else {
 421                                if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) &&
 422                                    (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
 423                                        u_long flags;
 424                                        spin_lock_irqsave(&bcs->aclock, flags);
 425                                        bcs->ackcnt += bcs->hw.hdlc.count;
 426                                        spin_unlock_irqrestore(&bcs->aclock, flags);
 427                                        schedule_event(bcs, B_ACKPENDING);
 428                                }
 429                                dev_kfree_skb_irq(bcs->tx_skb);
 430                                bcs->hw.hdlc.count = 0;
 431                                bcs->tx_skb = NULL;
 432                        }
 433                }
 434                if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
 435                        bcs->hw.hdlc.count = 0;
 436                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 437                        hdlc_fill_fifo(bcs);
 438                } else {
 439                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 440                        schedule_event(bcs, B_XMTBUFREADY);
 441                }
 442        }
 443}
 444
 445static inline void
 446HDLC_irq_main(struct IsdnCardState *cs)
 447{
 448        u_int stat;
 449        struct BCState *bcs;
 450
 451        if (cs->subtyp == AVM_FRITZ_PCI) {
 452                stat = ReadHDLCPCI(cs, 0, HDLC_STATUS);
 453        } else {
 454                stat = ReadHDLCPnP(cs, 0, HDLC_STATUS);
 455                if (stat & HDLC_INT_RPR)
 456                        stat |= (ReadHDLCPnP(cs, 0, HDLC_STATUS + 1)) << 8;
 457        }
 458        if (stat & HDLC_INT_MASK) {
 459                if (!(bcs = Sel_BCS(cs, 0))) {
 460                        if (cs->debug)
 461                                debugl1(cs, "hdlc spurious channel 0 IRQ");
 462                } else
 463                        HDLC_irq(bcs, stat);
 464        }
 465        if (cs->subtyp == AVM_FRITZ_PCI) {
 466                stat = ReadHDLCPCI(cs, 1, HDLC_STATUS);
 467        } else {
 468                stat = ReadHDLCPnP(cs, 1, HDLC_STATUS);
 469                if (stat & HDLC_INT_RPR)
 470                        stat |= (ReadHDLCPnP(cs, 1, HDLC_STATUS + 1)) << 8;
 471        }
 472        if (stat & HDLC_INT_MASK) {
 473                if (!(bcs = Sel_BCS(cs, 1))) {
 474                        if (cs->debug)
 475                                debugl1(cs, "hdlc spurious channel 1 IRQ");
 476                } else
 477                        HDLC_irq(bcs, stat);
 478        }
 479}
 480
 481static void
 482hdlc_l2l1(struct PStack *st, int pr, void *arg)
 483{
 484        struct BCState *bcs = st->l1.bcs;
 485        struct sk_buff *skb = arg;
 486        u_long flags;
 487
 488        switch (pr) {
 489        case (PH_DATA | REQUEST):
 490                spin_lock_irqsave(&bcs->cs->lock, flags);
 491                if (bcs->tx_skb) {
 492                        skb_queue_tail(&bcs->squeue, skb);
 493                } else {
 494                        bcs->tx_skb = skb;
 495                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 496                        bcs->hw.hdlc.count = 0;
 497                        bcs->cs->BC_Send_Data(bcs);
 498                }
 499                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 500                break;
 501        case (PH_PULL | INDICATION):
 502                spin_lock_irqsave(&bcs->cs->lock, flags);
 503                if (bcs->tx_skb) {
 504                        printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n");
 505                } else {
 506                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 507                        bcs->tx_skb = skb;
 508                        bcs->hw.hdlc.count = 0;
 509                        bcs->cs->BC_Send_Data(bcs);
 510                }
 511                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 512                break;
 513        case (PH_PULL | REQUEST):
 514                if (!bcs->tx_skb) {
 515                        test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 516                        st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 517                } else
 518                        test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 519                break;
 520        case (PH_ACTIVATE | REQUEST):
 521                spin_lock_irqsave(&bcs->cs->lock, flags);
 522                test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
 523                modehdlc(bcs, st->l1.mode, st->l1.bc);
 524                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 525                l1_msg_b(st, pr, arg);
 526                break;
 527        case (PH_DEACTIVATE | REQUEST):
 528                l1_msg_b(st, pr, arg);
 529                break;
 530        case (PH_DEACTIVATE | CONFIRM):
 531                spin_lock_irqsave(&bcs->cs->lock, flags);
 532                test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
 533                test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 534                modehdlc(bcs, 0, st->l1.bc);
 535                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 536                st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 537                break;
 538        }
 539}
 540
 541static void
 542close_hdlcstate(struct BCState *bcs)
 543{
 544        modehdlc(bcs, 0, 0);
 545        if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
 546                kfree(bcs->hw.hdlc.rcvbuf);
 547                bcs->hw.hdlc.rcvbuf = NULL;
 548                kfree(bcs->blog);
 549                bcs->blog = NULL;
 550                skb_queue_purge(&bcs->rqueue);
 551                skb_queue_purge(&bcs->squeue);
 552                if (bcs->tx_skb) {
 553                        dev_kfree_skb_any(bcs->tx_skb);
 554                        bcs->tx_skb = NULL;
 555                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 556                }
 557        }
 558}
 559
 560static int
 561open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
 562{
 563        if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
 564                if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
 565                        printk(KERN_WARNING
 566                               "HiSax: No memory for hdlc.rcvbuf\n");
 567                        return (1);
 568                }
 569                if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
 570                        printk(KERN_WARNING
 571                               "HiSax: No memory for bcs->blog\n");
 572                        test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
 573                        kfree(bcs->hw.hdlc.rcvbuf);
 574                        bcs->hw.hdlc.rcvbuf = NULL;
 575                        return (2);
 576                }
 577                skb_queue_head_init(&bcs->rqueue);
 578                skb_queue_head_init(&bcs->squeue);
 579        }
 580        bcs->tx_skb = NULL;
 581        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 582        bcs->event = 0;
 583        bcs->hw.hdlc.rcvidx = 0;
 584        bcs->tx_cnt = 0;
 585        return (0);
 586}
 587
 588static int
 589setstack_hdlc(struct PStack *st, struct BCState *bcs)
 590{
 591        bcs->channel = st->l1.bc;
 592        if (open_hdlcstate(st->l1.hardware, bcs))
 593                return (-1);
 594        st->l1.bcs = bcs;
 595        st->l2.l2l1 = hdlc_l2l1;
 596        setstack_manager(st);
 597        bcs->st = st;
 598        setstack_l1_B(st);
 599        return (0);
 600}
 601
 602#if 0
 603void __init
 604clear_pending_hdlc_ints(struct IsdnCardState *cs)
 605{
 606        u_int val;
 607
 608        if (cs->subtyp == AVM_FRITZ_PCI) {
 609                val = ReadHDLCPCI(cs, 0, HDLC_STATUS);
 610                debugl1(cs, "HDLC 1 STA %x", val);
 611                val = ReadHDLCPCI(cs, 1, HDLC_STATUS);
 612                debugl1(cs, "HDLC 2 STA %x", val);
 613        } else {
 614                val = ReadHDLCPnP(cs, 0, HDLC_STATUS);
 615                debugl1(cs, "HDLC 1 STA %x", val);
 616                val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 1);
 617                debugl1(cs, "HDLC 1 RML %x", val);
 618                val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 2);
 619                debugl1(cs, "HDLC 1 MODE %x", val);
 620                val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 3);
 621                debugl1(cs, "HDLC 1 VIN %x", val);
 622                val = ReadHDLCPnP(cs, 1, HDLC_STATUS);
 623                debugl1(cs, "HDLC 2 STA %x", val);
 624                val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 1);
 625                debugl1(cs, "HDLC 2 RML %x", val);
 626                val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 2);
 627                debugl1(cs, "HDLC 2 MODE %x", val);
 628                val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3);
 629                debugl1(cs, "HDLC 2 VIN %x", val);
 630        }
 631}
 632#endif  /*  0  */
 633
 634static void
 635inithdlc(struct IsdnCardState *cs)
 636{
 637        cs->bcs[0].BC_SetStack = setstack_hdlc;
 638        cs->bcs[1].BC_SetStack = setstack_hdlc;
 639        cs->bcs[0].BC_Close = close_hdlcstate;
 640        cs->bcs[1].BC_Close = close_hdlcstate;
 641        modehdlc(cs->bcs, -1, 0);
 642        modehdlc(cs->bcs + 1, -1, 1);
 643}
 644
 645static irqreturn_t
 646avm_pcipnp_interrupt(int intno, void *dev_id)
 647{
 648        struct IsdnCardState *cs = dev_id;
 649        u_long flags;
 650        u_char val;
 651        u_char sval;
 652
 653        spin_lock_irqsave(&cs->lock, flags);
 654        sval = inb(cs->hw.avm.cfg_reg + 2);
 655        if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) {
 656                /* possible a shared  IRQ reqest */
 657                spin_unlock_irqrestore(&cs->lock, flags);
 658                return IRQ_NONE;
 659        }
 660        if (!(sval & AVM_STATUS0_IRQ_ISAC)) {
 661                val = ReadISAC(cs, ISAC_ISTA);
 662                isac_interrupt(cs, val);
 663        }
 664        if (!(sval & AVM_STATUS0_IRQ_HDLC)) {
 665                HDLC_irq_main(cs);
 666        }
 667        WriteISAC(cs, ISAC_MASK, 0xFF);
 668        WriteISAC(cs, ISAC_MASK, 0x0);
 669        spin_unlock_irqrestore(&cs->lock, flags);
 670        return IRQ_HANDLED;
 671}
 672
 673static void
 674reset_avmpcipnp(struct IsdnCardState *cs)
 675{
 676        printk(KERN_INFO "AVM PCI/PnP: reset\n");
 677        outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2);
 678        mdelay(10);
 679        outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
 680        outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3);
 681        mdelay(10);
 682        printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3));
 683}
 684
 685static int
 686AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 687{
 688        u_long flags;
 689
 690        switch (mt) {
 691        case CARD_RESET:
 692                spin_lock_irqsave(&cs->lock, flags);
 693                reset_avmpcipnp(cs);
 694                spin_unlock_irqrestore(&cs->lock, flags);
 695                return (0);
 696        case CARD_RELEASE:
 697                outb(0, cs->hw.avm.cfg_reg + 2);
 698                release_region(cs->hw.avm.cfg_reg, 32);
 699                return (0);
 700        case CARD_INIT:
 701                spin_lock_irqsave(&cs->lock, flags);
 702                reset_avmpcipnp(cs);
 703                clear_pending_isac_ints(cs);
 704                initisac(cs);
 705                inithdlc(cs);
 706                outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,
 707                     cs->hw.avm.cfg_reg + 2);
 708                WriteISAC(cs, ISAC_MASK, 0);
 709                outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
 710                     AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
 711                /* RESET Receiver and Transmitter */
 712                WriteISAC(cs, ISAC_CMDR, 0x41);
 713                spin_unlock_irqrestore(&cs->lock, flags);
 714                return (0);
 715        case CARD_TEST:
 716                return (0);
 717        }
 718        return (0);
 719}
 720
 721static int avm_setup_rest(struct IsdnCardState *cs)
 722{
 723        u_int val, ver;
 724
 725        cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
 726        if (!request_region(cs->hw.avm.cfg_reg, 32,
 727                            (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) {
 728                printk(KERN_WARNING
 729                       "HiSax: Fritz!PCI/PNP config port %x-%x already in use\n",
 730                       cs->hw.avm.cfg_reg,
 731                       cs->hw.avm.cfg_reg + 31);
 732                return (0);
 733        }
 734        switch (cs->subtyp) {
 735        case AVM_FRITZ_PCI:
 736                val = inl(cs->hw.avm.cfg_reg);
 737                printk(KERN_INFO "AVM PCI: stat %#x\n", val);
 738                printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
 739                       val & 0xff, (val >> 8) & 0xff);
 740                cs->BC_Read_Reg = &ReadHDLC_s;
 741                cs->BC_Write_Reg = &WriteHDLC_s;
 742                break;
 743        case AVM_FRITZ_PNP:
 744                val = inb(cs->hw.avm.cfg_reg);
 745                ver = inb(cs->hw.avm.cfg_reg + 1);
 746                printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
 747                cs->BC_Read_Reg = &ReadHDLCPnP;
 748                cs->BC_Write_Reg = &WriteHDLCPnP;
 749                break;
 750        default:
 751                printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp);
 752                return (0);
 753        }
 754        printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
 755               (cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
 756               cs->irq, cs->hw.avm.cfg_reg);
 757
 758        setup_isac(cs);
 759        cs->readisac = &ReadISAC;
 760        cs->writeisac = &WriteISAC;
 761        cs->readisacfifo = &ReadISACfifo;
 762        cs->writeisacfifo = &WriteISACfifo;
 763        cs->BC_Send_Data = &hdlc_fill_fifo;
 764        cs->cardmsg = &AVM_card_msg;
 765        cs->irq_func = &avm_pcipnp_interrupt;
 766        cs->writeisac(cs, ISAC_MASK, 0xFF);
 767        ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");
 768        return (1);
 769}
 770
 771#ifndef __ISAPNP__
 772
 773static int avm_pnp_setup(struct IsdnCardState *cs)
 774{
 775        return (1);     /* no-op: success */
 776}
 777
 778#else
 779
 780static struct pnp_card *pnp_avm_c = NULL;
 781
 782static int avm_pnp_setup(struct IsdnCardState *cs)
 783{
 784        struct pnp_dev *pnp_avm_d = NULL;
 785
 786        if (!isapnp_present())
 787                return (1);     /* no-op: success */
 788
 789        if ((pnp_avm_c = pnp_find_card(
 790                     ISAPNP_VENDOR('A', 'V', 'M'),
 791                     ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
 792                if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
 793                                              ISAPNP_VENDOR('A', 'V', 'M'),
 794                                              ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
 795                        int err;
 796
 797                        pnp_disable_dev(pnp_avm_d);
 798                        err = pnp_activate_dev(pnp_avm_d);
 799                        if (err < 0) {
 800                                printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
 801                                       __func__, err);
 802                                return (0);
 803                        }
 804                        cs->hw.avm.cfg_reg =
 805                                pnp_port_start(pnp_avm_d, 0);
 806                        cs->irq = pnp_irq(pnp_avm_d, 0);
 807                        if (!cs->irq) {
 808                                printk(KERN_ERR "FritzPnP:No IRQ\n");
 809                                return (0);
 810                        }
 811                        if (!cs->hw.avm.cfg_reg) {
 812                                printk(KERN_ERR "FritzPnP:No IO address\n");
 813                                return (0);
 814                        }
 815                        cs->subtyp = AVM_FRITZ_PNP;
 816
 817                        return (2);     /* goto 'ready' label */
 818                }
 819        }
 820
 821        return (1);
 822}
 823
 824#endif /* __ISAPNP__ */
 825
 826#ifndef CONFIG_PCI
 827
 828static int avm_pci_setup(struct IsdnCardState *cs)
 829{
 830        return (1);     /* no-op: success */
 831}
 832
 833#else
 834
 835static struct pci_dev *dev_avm = NULL;
 836
 837static int avm_pci_setup(struct IsdnCardState *cs)
 838{
 839        if ((dev_avm = hisax_find_pci_device(PCI_VENDOR_ID_AVM,
 840                                             PCI_DEVICE_ID_AVM_A1, dev_avm))) {
 841
 842                if (pci_enable_device(dev_avm))
 843                        return (0);
 844
 845                cs->irq = dev_avm->irq;
 846                if (!cs->irq) {
 847                        printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
 848                        return (0);
 849                }
 850
 851                cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
 852                if (!cs->hw.avm.cfg_reg) {
 853                        printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
 854                        return (0);
 855                }
 856
 857                cs->subtyp = AVM_FRITZ_PCI;
 858        } else {
 859                printk(KERN_WARNING "FritzPCI: No PCI card found\n");
 860                return (0);
 861        }
 862
 863        cs->irq_flags |= IRQF_SHARED;
 864
 865        return (1);
 866}
 867
 868#endif /* CONFIG_PCI */
 869
 870int setup_avm_pcipnp(struct IsdnCard *card)
 871{
 872        struct IsdnCardState *cs = card->cs;
 873        char tmp[64];
 874        int rc;
 875
 876        strcpy(tmp, avm_pci_rev);
 877        printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
 878
 879        if (cs->typ != ISDN_CTYPE_FRITZPCI)
 880                return (0);
 881
 882        if (card->para[1]) {
 883                /* old manual method */
 884                cs->hw.avm.cfg_reg = card->para[1];
 885                cs->irq = card->para[0];
 886                cs->subtyp = AVM_FRITZ_PNP;
 887                goto ready;
 888        }
 889
 890        rc = avm_pnp_setup(cs);
 891        if (rc < 1)
 892                return (0);
 893        if (rc == 2)
 894                goto ready;
 895
 896        rc = avm_pci_setup(cs);
 897        if (rc < 1)
 898                return (0);
 899
 900ready:
 901        return avm_setup_rest(cs);
 902}
 903