#include "ipac.h"
 
 
-#define AVMFRITZ_REV   "2.1"
+#define AVMFRITZ_REV   "2.2"
 
 static int AVM_cnt;
 static int debug;
 #define HDLC_MODE_TRANS                0x02
 #define HDLC_MODE_CCR_7                0x04
 #define HDLC_MODE_CCR_16       0x08
+#define HDLC_FIFO_SIZE_128     0x20
 #define HDLC_MODE_TESTLOOP     0x80
 
 #define HDLC_INT_XPR           0x80
 #define HDLC_STAT_RDO          0x10
 #define HDLC_STAT_CRCVFRRAB    0x0E
 #define HDLC_STAT_CRCVFR       0x06
-#define HDLC_STAT_RML_MASK     0x3f00
+#define HDLC_STAT_RML_MASK_V1  0x3f00
+#define HDLC_STAT_RML_MASK_V2  0x7f00
 
 #define HDLC_CMD_XRS           0x80
 #define HDLC_CMD_XME           0x01
 #define HDLC_CMD_RRS           0x20
 #define HDLC_CMD_XML_MASK      0x3f00
-#define HDLC_FIFO_SIZE         32
+
+#define HDLC_FIFO_SIZE_V1      32
+#define HDLC_FIFO_SIZE_V2      128
 
 /* Fritz PCI v2.0 */
 
 {
        struct fritzcard *fc = bch->hw;
        struct hdlc_hw *hdlc;
+       u8 mode;
 
        hdlc = &fc->hdlc[(bch->nr - 1) & 1];
        pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name,
                 '@' + bch->nr, bch->state, protocol, bch->nr);
        hdlc->ctrl.ctrl = 0;
+       mode = (fc->type == AVM_FRITZ_PCIV2) ? HDLC_FIFO_SIZE_128 : 0;
+
        switch (protocol) {
        case -1: /* used for init */
                bch->state = -1;
                if (bch->state == ISDN_P_NONE)
                        break;
                hdlc->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
-               hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
+               hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;
                write_ctrl(bch, 5);
                bch->state = ISDN_P_NONE;
                test_and_clear_bit(FLG_HDLC, &bch->Flags);
        case ISDN_P_B_RAW:
                bch->state = protocol;
                hdlc->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
-               hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
+               hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;
                write_ctrl(bch, 5);
                hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
                write_ctrl(bch, 1);
        case ISDN_P_B_HDLC:
                bch->state = protocol;
                hdlc->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
-               hdlc->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
+               hdlc->ctrl.sr.mode = mode | HDLC_MODE_ITF_FLG;
                write_ctrl(bch, 5);
                hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
                write_ctrl(bch, 1);
        }
        p = skb_put(bch->rx_skb, count);
        ptr = (u32 *)p;
-       if (AVM_FRITZ_PCIV2 == fc->type)
+       if (fc->type == AVM_FRITZ_PCIV2)
                addr = fc->addr + (bch->nr == 2 ?
                                   AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
        else {
 {
        struct fritzcard *fc = bch->hw;
        struct hdlc_hw *hdlc;
-       int count, cnt = 0;
+       int count, fs, cnt = 0;
        u8 *p;
        u32 *ptr, val, addr;
 
        count = bch->tx_skb->len - bch->tx_idx;
        if (count <= 0)
                return;
+       fs = (fc->type == AVM_FRITZ_PCIV2) ?
+               HDLC_FIFO_SIZE_V2 : HDLC_FIFO_SIZE_V1;
        p = bch->tx_skb->data + bch->tx_idx;
        hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;
-       if (count > HDLC_FIFO_SIZE) {
-               count = HDLC_FIFO_SIZE;
+       if (count > fs) {
+               count = fs;
        } else {
                if (test_bit(FLG_HDLC, &bch->Flags))
                        hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
                 bch->tx_idx, bch->tx_skb->len);
        ptr = (u32 *)p;
        bch->tx_idx += count;
-       hdlc->ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count);
-       if (AVM_FRITZ_PCIV2 == fc->type) {
+       hdlc->ctrl.sr.xml = ((count == fs) ? 0 : count);
+       if (fc->type == AVM_FRITZ_PCIV2) {
                __write_ctrl_pciv2(fc, hdlc, bch->nr);
                addr = fc->addr + (bch->nr == 2 ?
                                   AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
 HDLC_irq(struct bchannel *bch, u32 stat)
 {
        struct fritzcard *fc = bch->hw;
-       int             len;
+       int             len, fs;
+       u32             rmlMask;
        struct hdlc_hw  *hdlc;
 
        hdlc = &fc->hdlc[(bch->nr - 1) & 1];
        pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat);
+       if (fc->type == AVM_FRITZ_PCIV2) {
+               rmlMask = HDLC_STAT_RML_MASK_V2;
+               fs = HDLC_FIFO_SIZE_V2;
+       } else {
+               rmlMask = HDLC_STAT_RML_MASK_V1;
+               fs = HDLC_FIFO_SIZE_V1;
+       }
        if (stat & HDLC_INT_RPR) {
                if (stat & HDLC_STAT_RDO) {
+                       pr_warning("%s: ch%d stat %x RDO\n",
+                                  fc->name, bch->nr, stat);
                        hdlc->ctrl.sr.xml = 0;
                        hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS;
                        write_ctrl(bch, 1);
                        if (bch->rx_skb)
                                skb_trim(bch->rx_skb, 0);
                } else {
-                       len = (stat & HDLC_STAT_RML_MASK) >> 8;
+                       len = (stat & rmlMask) >> 8;
                        if (!len)
-                               len = 32;
+                               len = fs;
                        hdlc_empty_fifo(bch, len);
                        if (!bch->rx_skb)
                                goto handle_tx;
-                       if ((stat & HDLC_STAT_RME) || test_bit(FLG_TRANSPARENT,
-                                                              &bch->Flags)) {
+                       if (test_bit(FLG_TRANSPARENT, &bch->Flags) ||
+                           (stat & HDLC_STAT_RME)) {
                                if (((stat & HDLC_STAT_CRCVFRRAB) ==
                                     HDLC_STAT_CRCVFR) ||
                                    test_bit(FLG_TRANSPARENT, &bch->Flags)) {
                                        recv_Bchannel(bch, 0);
                                } else {
-                                       pr_debug("%s: got invalid frame\n",
-                                                fc->name);
+                                       pr_warning("%s: got invalid frame\n",
+                                                  fc->name);
                                        skb_trim(bch->rx_skb, 0);
                                }
                        }
                 * restart transmitting the whole frame on HDLC
                 * in transparent mode we send the next data
                 */
-               if (bch->tx_skb)
-                       pr_debug("%s: ch%d XDU len(%d) idx(%d) Flags(%lx)\n",
-                                fc->name, bch->nr, bch->tx_skb->len,
-                                bch->tx_idx, bch->Flags);
-               else
-                       pr_debug("%s: ch%d XDU no tx_skb Flags(%lx)\n",
-                                fc->name, bch->nr, bch->Flags);
+               pr_warning("%s: ch%d stat %x XDU %s\n", fc->name, bch->nr,
+                          stat, bch->tx_skb ? "tx_skb" : "no tx_skb");
                if (bch->tx_skb && bch->tx_skb->len) {
                        if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
                                bch->tx_idx = 0;
                inithdlc(fc);
                enable_hwirq(fc);
                /* RESET Receiver and Transmitter */
-               if (AVM_FRITZ_PCIV2 == fc->type) {
+               if (fc->type == AVM_FRITZ_PCIV2) {
                        WriteISAC_V2(fc, ISACX_MASK, 0);
                        WriteISAC_V2(fc, ISACX_CMDRD, 0x41);
                } else {