|
@@ -30,7 +30,7 @@
|
|
|
#include "ipac.h"
|
|
|
|
|
|
|
|
|
-#define AVMFRITZ_REV "2.1"
|
|
|
+#define AVMFRITZ_REV "2.2"
|
|
|
|
|
|
static int AVM_cnt;
|
|
|
static int debug;
|
|
@@ -69,6 +69,7 @@ enum {
|
|
|
#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
|
|
@@ -80,13 +81,16 @@ enum {
|
|
|
#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 */
|
|
|
|
|
@@ -346,11 +350,14 @@ modehdlc(struct bchannel *bch, int protocol)
|
|
|
{
|
|
|
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;
|
|
@@ -358,7 +365,7 @@ modehdlc(struct bchannel *bch, int protocol)
|
|
|
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);
|
|
@@ -367,7 +374,7 @@ modehdlc(struct bchannel *bch, int protocol)
|
|
|
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);
|
|
@@ -377,7 +384,7 @@ modehdlc(struct bchannel *bch, int protocol)
|
|
|
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);
|
|
@@ -416,7 +423,7 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
|
|
|
}
|
|
|
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 {
|
|
@@ -441,7 +448,7 @@ hdlc_fill_fifo(struct bchannel *bch)
|
|
|
{
|
|
|
struct fritzcard *fc = bch->hw;
|
|
|
struct hdlc_hw *hdlc;
|
|
|
- int count, cnt = 0;
|
|
|
+ int count, fs, cnt = 0;
|
|
|
u8 *p;
|
|
|
u32 *ptr, val, addr;
|
|
|
|
|
@@ -451,10 +458,12 @@ hdlc_fill_fifo(struct bchannel *bch)
|
|
|
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;
|
|
@@ -463,8 +472,8 @@ hdlc_fill_fifo(struct bchannel *bch)
|
|
|
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);
|
|
@@ -502,13 +511,23 @@ static void
|
|
|
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);
|
|
@@ -517,21 +536,21 @@ HDLC_irq(struct bchannel *bch, u32 stat)
|
|
|
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);
|
|
|
}
|
|
|
}
|
|
@@ -543,13 +562,8 @@ handle_tx:
|
|
|
* 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;
|
|
@@ -774,7 +788,7 @@ init_card(struct fritzcard *fc)
|
|
|
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 {
|