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