1165 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * avm_fritz.c low level stuff for AVM FRITZ!CARD PCI ISDN cards4 * Thanks to AVM, Berlin for informations5 *6 * Author Karsten Keil <keil@isdn4linux.de>7 *8 * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>9 */10#include <linux/interrupt.h>11#include <linux/module.h>12#include <linux/pci.h>13#include <linux/delay.h>14#include <linux/mISDNhw.h>15#include <linux/slab.h>16#include <linux/unaligned.h>17#include "ipac.h"18 19 20#define AVMFRITZ_REV "2.3"21 22static int AVM_cnt;23static int debug;24 25enum {26 AVM_FRITZ_PCI,27 AVM_FRITZ_PCIV2,28};29 30#define HDLC_FIFO 0x031#define HDLC_STATUS 0x432#define CHIP_WINDOW 0x1033 34#define CHIP_INDEX 0x435#define AVM_HDLC_1 0x0036#define AVM_HDLC_2 0x0137#define AVM_ISAC_FIFO 0x0238#define AVM_ISAC_REG_LOW 0x0439#define AVM_ISAC_REG_HIGH 0x0640 41#define AVM_STATUS0_IRQ_ISAC 0x0142#define AVM_STATUS0_IRQ_HDLC 0x0243#define AVM_STATUS0_IRQ_TIMER 0x0444#define AVM_STATUS0_IRQ_MASK 0x0745 46#define AVM_STATUS0_RESET 0x0147#define AVM_STATUS0_DIS_TIMER 0x0248#define AVM_STATUS0_RES_TIMER 0x0449#define AVM_STATUS0_ENA_IRQ 0x0850#define AVM_STATUS0_TESTBIT 0x1051 52#define AVM_STATUS1_INT_SEL 0x0f53#define AVM_STATUS1_ENA_IOM 0x8054 55#define HDLC_MODE_ITF_FLG 0x0156#define HDLC_MODE_TRANS 0x0257#define HDLC_MODE_CCR_7 0x0458#define HDLC_MODE_CCR_16 0x0859#define HDLC_FIFO_SIZE_128 0x2060#define HDLC_MODE_TESTLOOP 0x8061 62#define HDLC_INT_XPR 0x8063#define HDLC_INT_XDU 0x4064#define HDLC_INT_RPR 0x2065#define HDLC_INT_MASK 0xE066 67#define HDLC_STAT_RME 0x0168#define HDLC_STAT_RDO 0x1069#define HDLC_STAT_CRCVFRRAB 0x0E70#define HDLC_STAT_CRCVFR 0x0671#define HDLC_STAT_RML_MASK_V1 0x3f0072#define HDLC_STAT_RML_MASK_V2 0x7f0073 74#define HDLC_CMD_XRS 0x8075#define HDLC_CMD_XME 0x0176#define HDLC_CMD_RRS 0x2077#define HDLC_CMD_XML_MASK 0x3f0078 79#define HDLC_FIFO_SIZE_V1 3280#define HDLC_FIFO_SIZE_V2 12881 82/* Fritz PCI v2.0 */83 84#define AVM_HDLC_FIFO_1 0x1085#define AVM_HDLC_FIFO_2 0x1886 87#define AVM_HDLC_STATUS_1 0x1488#define AVM_HDLC_STATUS_2 0x1c89 90#define AVM_ISACX_INDEX 0x0491#define AVM_ISACX_DATA 0x0892 93/* data struct */94#define LOG_SIZE 6395 96struct hdlc_stat_reg {97#ifdef __BIG_ENDIAN98 u8 fill;99 u8 mode;100 u8 xml;101 u8 cmd;102#else103 u8 cmd;104 u8 xml;105 u8 mode;106 u8 fill;107#endif108} __attribute__((packed));109 110struct hdlc_hw {111 union {112 u32 ctrl;113 struct hdlc_stat_reg sr;114 } ctrl;115 u32 stat;116};117 118struct fritzcard {119 struct list_head list;120 struct pci_dev *pdev;121 char name[MISDN_MAX_IDLEN];122 u8 type;123 u8 ctrlreg;124 u16 irq;125 u32 irqcnt;126 u32 addr;127 spinlock_t lock; /* hw lock */128 struct isac_hw isac;129 struct hdlc_hw hdlc[2];130 struct bchannel bch[2];131 char log[LOG_SIZE + 1];132};133 134static LIST_HEAD(Cards);135static DEFINE_RWLOCK(card_lock); /* protect Cards */136 137static void138_set_debug(struct fritzcard *card)139{140 card->isac.dch.debug = debug;141 card->bch[0].debug = debug;142 card->bch[1].debug = debug;143}144 145static int146set_debug(const char *val, const struct kernel_param *kp)147{148 int ret;149 struct fritzcard *card;150 151 ret = param_set_uint(val, kp);152 if (!ret) {153 read_lock(&card_lock);154 list_for_each_entry(card, &Cards, list)155 _set_debug(card);156 read_unlock(&card_lock);157 }158 return ret;159}160 161MODULE_AUTHOR("Karsten Keil");162MODULE_DESCRIPTION("mISDN driver for AVM FRITZ!CARD PCI ISDN cards");163MODULE_LICENSE("GPL v2");164MODULE_VERSION(AVMFRITZ_REV);165module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);166MODULE_PARM_DESC(debug, "avmfritz debug mask");167 168/* Interface functions */169 170static u8171ReadISAC_V1(void *p, u8 offset)172{173 struct fritzcard *fc = p;174 u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;175 176 outb(idx, fc->addr + CHIP_INDEX);177 return inb(fc->addr + CHIP_WINDOW + (offset & 0xf));178}179 180static void181WriteISAC_V1(void *p, u8 offset, u8 value)182{183 struct fritzcard *fc = p;184 u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;185 186 outb(idx, fc->addr + CHIP_INDEX);187 outb(value, fc->addr + CHIP_WINDOW + (offset & 0xf));188}189 190static void191ReadFiFoISAC_V1(void *p, u8 off, u8 *data, int size)192{193 struct fritzcard *fc = p;194 195 outb(AVM_ISAC_FIFO, fc->addr + CHIP_INDEX);196 insb(fc->addr + CHIP_WINDOW, data, size);197}198 199static void200WriteFiFoISAC_V1(void *p, u8 off, u8 *data, int size)201{202 struct fritzcard *fc = p;203 204 outb(AVM_ISAC_FIFO, fc->addr + CHIP_INDEX);205 outsb(fc->addr + CHIP_WINDOW, data, size);206}207 208static u8209ReadISAC_V2(void *p, u8 offset)210{211 struct fritzcard *fc = p;212 213 outl(offset, fc->addr + AVM_ISACX_INDEX);214 return 0xff & inl(fc->addr + AVM_ISACX_DATA);215}216 217static void218WriteISAC_V2(void *p, u8 offset, u8 value)219{220 struct fritzcard *fc = p;221 222 outl(offset, fc->addr + AVM_ISACX_INDEX);223 outl(value, fc->addr + AVM_ISACX_DATA);224}225 226static void227ReadFiFoISAC_V2(void *p, u8 off, u8 *data, int size)228{229 struct fritzcard *fc = p;230 int i;231 232 outl(off, fc->addr + AVM_ISACX_INDEX);233 for (i = 0; i < size; i++)234 data[i] = 0xff & inl(fc->addr + AVM_ISACX_DATA);235}236 237static void238WriteFiFoISAC_V2(void *p, u8 off, u8 *data, int size)239{240 struct fritzcard *fc = p;241 int i;242 243 outl(off, fc->addr + AVM_ISACX_INDEX);244 for (i = 0; i < size; i++)245 outl(data[i], fc->addr + AVM_ISACX_DATA);246}247 248static struct bchannel *249Sel_BCS(struct fritzcard *fc, u32 channel)250{251 if (test_bit(FLG_ACTIVE, &fc->bch[0].Flags) &&252 (fc->bch[0].nr & channel))253 return &fc->bch[0];254 else if (test_bit(FLG_ACTIVE, &fc->bch[1].Flags) &&255 (fc->bch[1].nr & channel))256 return &fc->bch[1];257 else258 return NULL;259}260 261static inline void262__write_ctrl_pci(struct fritzcard *fc, struct hdlc_hw *hdlc, u32 channel) {263 u32 idx = channel == 2 ? AVM_HDLC_2 : AVM_HDLC_1;264 265 outl(idx, fc->addr + CHIP_INDEX);266 outl(hdlc->ctrl.ctrl, fc->addr + CHIP_WINDOW + HDLC_STATUS);267}268 269static inline void270__write_ctrl_pciv2(struct fritzcard *fc, struct hdlc_hw *hdlc, u32 channel) {271 outl(hdlc->ctrl.ctrl, fc->addr + (channel == 2 ? AVM_HDLC_STATUS_2 :272 AVM_HDLC_STATUS_1));273}274 275static void276write_ctrl(struct bchannel *bch, int which) {277 struct fritzcard *fc = bch->hw;278 struct hdlc_hw *hdlc;279 280 hdlc = &fc->hdlc[(bch->nr - 1) & 1];281 pr_debug("%s: hdlc %c wr%x ctrl %x\n", fc->name, '@' + bch->nr,282 which, hdlc->ctrl.ctrl);283 switch (fc->type) {284 case AVM_FRITZ_PCIV2:285 __write_ctrl_pciv2(fc, hdlc, bch->nr);286 break;287 case AVM_FRITZ_PCI:288 __write_ctrl_pci(fc, hdlc, bch->nr);289 break;290 }291}292 293 294static inline u32295__read_status_pci(u_long addr, u32 channel)296{297 outl(channel == 2 ? AVM_HDLC_2 : AVM_HDLC_1, addr + CHIP_INDEX);298 return inl(addr + CHIP_WINDOW + HDLC_STATUS);299}300 301static inline u32302__read_status_pciv2(u_long addr, u32 channel)303{304 return inl(addr + (channel == 2 ? AVM_HDLC_STATUS_2 :305 AVM_HDLC_STATUS_1));306}307 308 309static u32310read_status(struct fritzcard *fc, u32 channel)311{312 switch (fc->type) {313 case AVM_FRITZ_PCIV2:314 return __read_status_pciv2(fc->addr, channel);315 case AVM_FRITZ_PCI:316 return __read_status_pci(fc->addr, channel);317 }318 /* dummy */319 return 0;320}321 322static void323enable_hwirq(struct fritzcard *fc)324{325 fc->ctrlreg |= AVM_STATUS0_ENA_IRQ;326 outb(fc->ctrlreg, fc->addr + 2);327}328 329static void330disable_hwirq(struct fritzcard *fc)331{332 fc->ctrlreg &= ~AVM_STATUS0_ENA_IRQ;333 outb(fc->ctrlreg, fc->addr + 2);334}335 336static int337modehdlc(struct bchannel *bch, int protocol)338{339 struct fritzcard *fc = bch->hw;340 struct hdlc_hw *hdlc;341 u8 mode;342 343 hdlc = &fc->hdlc[(bch->nr - 1) & 1];344 pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name,345 '@' + bch->nr, bch->state, protocol, bch->nr);346 hdlc->ctrl.ctrl = 0;347 mode = (fc->type == AVM_FRITZ_PCIV2) ? HDLC_FIFO_SIZE_128 : 0;348 349 switch (protocol) {350 case -1: /* used for init */351 bch->state = -1;352 fallthrough;353 case ISDN_P_NONE:354 if (bch->state == ISDN_P_NONE)355 break;356 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;357 hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;358 write_ctrl(bch, 5);359 bch->state = ISDN_P_NONE;360 test_and_clear_bit(FLG_HDLC, &bch->Flags);361 test_and_clear_bit(FLG_TRANSPARENT, &bch->Flags);362 break;363 case ISDN_P_B_RAW:364 bch->state = protocol;365 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;366 hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;367 write_ctrl(bch, 5);368 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;369 write_ctrl(bch, 1);370 hdlc->ctrl.sr.cmd = 0;371 test_and_set_bit(FLG_TRANSPARENT, &bch->Flags);372 break;373 case ISDN_P_B_HDLC:374 bch->state = protocol;375 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;376 hdlc->ctrl.sr.mode = mode | HDLC_MODE_ITF_FLG;377 write_ctrl(bch, 5);378 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;379 write_ctrl(bch, 1);380 hdlc->ctrl.sr.cmd = 0;381 test_and_set_bit(FLG_HDLC, &bch->Flags);382 break;383 default:384 pr_info("%s: protocol not known %x\n", fc->name, protocol);385 return -ENOPROTOOPT;386 }387 return 0;388}389 390static void391hdlc_empty_fifo(struct bchannel *bch, int count)392{393 u32 *ptr;394 u8 *p;395 u32 val, addr;396 int cnt;397 struct fritzcard *fc = bch->hw;398 399 pr_debug("%s: %s %d\n", fc->name, __func__, count);400 if (test_bit(FLG_RX_OFF, &bch->Flags)) {401 p = NULL;402 bch->dropcnt += count;403 } else {404 cnt = bchannel_get_rxbuf(bch, count);405 if (cnt < 0) {406 pr_warn("%s.B%d: No bufferspace for %d bytes\n",407 fc->name, bch->nr, count);408 return;409 }410 p = skb_put(bch->rx_skb, count);411 }412 ptr = (u32 *)p;413 if (fc->type == AVM_FRITZ_PCIV2)414 addr = fc->addr + (bch->nr == 2 ?415 AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);416 else {417 addr = fc->addr + CHIP_WINDOW;418 outl(bch->nr == 2 ? AVM_HDLC_2 : AVM_HDLC_1, fc->addr);419 }420 cnt = 0;421 while (cnt < count) {422 val = le32_to_cpu(inl(addr));423 if (p) {424 put_unaligned(val, ptr);425 ptr++;426 }427 cnt += 4;428 }429 if (p && (debug & DEBUG_HW_BFIFO)) {430 snprintf(fc->log, LOG_SIZE, "B%1d-recv %s %d ",431 bch->nr, fc->name, count);432 print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count);433 }434}435 436static void437hdlc_fill_fifo(struct bchannel *bch)438{439 struct fritzcard *fc = bch->hw;440 struct hdlc_hw *hdlc;441 int count, fs, cnt = 0, idx;442 bool fillempty = false;443 u8 *p;444 u32 *ptr, val, addr;445 446 idx = (bch->nr - 1) & 1;447 hdlc = &fc->hdlc[idx];448 fs = (fc->type == AVM_FRITZ_PCIV2) ?449 HDLC_FIFO_SIZE_V2 : HDLC_FIFO_SIZE_V1;450 if (!bch->tx_skb) {451 if (!test_bit(FLG_TX_EMPTY, &bch->Flags))452 return;453 count = fs;454 p = bch->fill;455 fillempty = true;456 } else {457 count = bch->tx_skb->len - bch->tx_idx;458 if (count <= 0)459 return;460 p = bch->tx_skb->data + bch->tx_idx;461 }462 hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;463 if (count > fs) {464 count = fs;465 } else {466 if (test_bit(FLG_HDLC, &bch->Flags))467 hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;468 }469 ptr = (u32 *)p;470 if (!fillempty) {471 pr_debug("%s.B%d: %d/%d/%d", fc->name, bch->nr, count,472 bch->tx_idx, bch->tx_skb->len);473 bch->tx_idx += count;474 } else {475 pr_debug("%s.B%d: fillempty %d\n", fc->name, bch->nr, count);476 }477 hdlc->ctrl.sr.xml = ((count == fs) ? 0 : count);478 if (fc->type == AVM_FRITZ_PCIV2) {479 __write_ctrl_pciv2(fc, hdlc, bch->nr);480 addr = fc->addr + (bch->nr == 2 ?481 AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);482 } else {483 __write_ctrl_pci(fc, hdlc, bch->nr);484 addr = fc->addr + CHIP_WINDOW;485 }486 if (fillempty) {487 while (cnt < count) {488 /* all bytes the same - no worry about endian */489 outl(*ptr, addr);490 cnt += 4;491 }492 } else {493 while (cnt < count) {494 val = get_unaligned(ptr);495 outl(cpu_to_le32(val), addr);496 ptr++;497 cnt += 4;498 }499 }500 if ((debug & DEBUG_HW_BFIFO) && !fillempty) {501 snprintf(fc->log, LOG_SIZE, "B%1d-send %s %d ",502 bch->nr, fc->name, count);503 print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count);504 }505}506 507static void508HDLC_irq_xpr(struct bchannel *bch)509{510 if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) {511 hdlc_fill_fifo(bch);512 } else {513 dev_kfree_skb(bch->tx_skb);514 if (get_next_bframe(bch)) {515 hdlc_fill_fifo(bch);516 test_and_clear_bit(FLG_TX_EMPTY, &bch->Flags);517 } else if (test_bit(FLG_TX_EMPTY, &bch->Flags)) {518 hdlc_fill_fifo(bch);519 }520 }521}522 523static void524HDLC_irq(struct bchannel *bch, u32 stat)525{526 struct fritzcard *fc = bch->hw;527 int len, fs;528 u32 rmlMask;529 struct hdlc_hw *hdlc;530 531 hdlc = &fc->hdlc[(bch->nr - 1) & 1];532 pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat);533 if (fc->type == AVM_FRITZ_PCIV2) {534 rmlMask = HDLC_STAT_RML_MASK_V2;535 fs = HDLC_FIFO_SIZE_V2;536 } else {537 rmlMask = HDLC_STAT_RML_MASK_V1;538 fs = HDLC_FIFO_SIZE_V1;539 }540 if (stat & HDLC_INT_RPR) {541 if (stat & HDLC_STAT_RDO) {542 pr_warn("%s: ch%d stat %x RDO\n",543 fc->name, bch->nr, stat);544 hdlc->ctrl.sr.xml = 0;545 hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS;546 write_ctrl(bch, 1);547 hdlc->ctrl.sr.cmd &= ~HDLC_CMD_RRS;548 write_ctrl(bch, 1);549 if (bch->rx_skb)550 skb_trim(bch->rx_skb, 0);551 } else {552 len = (stat & rmlMask) >> 8;553 if (!len)554 len = fs;555 hdlc_empty_fifo(bch, len);556 if (!bch->rx_skb)557 goto handle_tx;558 if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {559 recv_Bchannel(bch, 0, false);560 } else if (stat & HDLC_STAT_RME) {561 if ((stat & HDLC_STAT_CRCVFRRAB) ==562 HDLC_STAT_CRCVFR) {563 recv_Bchannel(bch, 0, false);564 } else {565 pr_warn("%s: got invalid frame\n",566 fc->name);567 skb_trim(bch->rx_skb, 0);568 }569 }570 }571 }572handle_tx:573 if (stat & HDLC_INT_XDU) {574 /* Here we lost an TX interrupt, so575 * restart transmitting the whole frame on HDLC576 * in transparent mode we send the next data577 */578 pr_warn("%s: ch%d stat %x XDU %s\n", fc->name, bch->nr,579 stat, bch->tx_skb ? "tx_skb" : "no tx_skb");580 if (bch->tx_skb && bch->tx_skb->len) {581 if (!test_bit(FLG_TRANSPARENT, &bch->Flags))582 bch->tx_idx = 0;583 } else if (test_bit(FLG_FILLEMPTY, &bch->Flags)) {584 test_and_set_bit(FLG_TX_EMPTY, &bch->Flags);585 }586 hdlc->ctrl.sr.xml = 0;587 hdlc->ctrl.sr.cmd |= HDLC_CMD_XRS;588 write_ctrl(bch, 1);589 hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XRS;590 HDLC_irq_xpr(bch);591 return;592 } else if (stat & HDLC_INT_XPR)593 HDLC_irq_xpr(bch);594}595 596static inline void597HDLC_irq_main(struct fritzcard *fc)598{599 u32 stat;600 struct bchannel *bch;601 602 stat = read_status(fc, 1);603 if (stat & HDLC_INT_MASK) {604 bch = Sel_BCS(fc, 1);605 if (bch)606 HDLC_irq(bch, stat);607 else608 pr_debug("%s: spurious ch1 IRQ\n", fc->name);609 }610 stat = read_status(fc, 2);611 if (stat & HDLC_INT_MASK) {612 bch = Sel_BCS(fc, 2);613 if (bch)614 HDLC_irq(bch, stat);615 else616 pr_debug("%s: spurious ch2 IRQ\n", fc->name);617 }618}619 620static irqreturn_t621avm_fritz_interrupt(int intno, void *dev_id)622{623 struct fritzcard *fc = dev_id;624 u8 val;625 u8 sval;626 627 spin_lock(&fc->lock);628 sval = inb(fc->addr + 2);629 pr_debug("%s: irq stat0 %x\n", fc->name, sval);630 if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) {631 /* shared IRQ from other HW */632 spin_unlock(&fc->lock);633 return IRQ_NONE;634 }635 fc->irqcnt++;636 637 if (!(sval & AVM_STATUS0_IRQ_ISAC)) {638 val = ReadISAC_V1(fc, ISAC_ISTA);639 mISDNisac_irq(&fc->isac, val);640 }641 if (!(sval & AVM_STATUS0_IRQ_HDLC))642 HDLC_irq_main(fc);643 spin_unlock(&fc->lock);644 return IRQ_HANDLED;645}646 647static irqreturn_t648avm_fritzv2_interrupt(int intno, void *dev_id)649{650 struct fritzcard *fc = dev_id;651 u8 val;652 u8 sval;653 654 spin_lock(&fc->lock);655 sval = inb(fc->addr + 2);656 pr_debug("%s: irq stat0 %x\n", fc->name, sval);657 if (!(sval & AVM_STATUS0_IRQ_MASK)) {658 /* shared IRQ from other HW */659 spin_unlock(&fc->lock);660 return IRQ_NONE;661 }662 fc->irqcnt++;663 664 if (sval & AVM_STATUS0_IRQ_HDLC)665 HDLC_irq_main(fc);666 if (sval & AVM_STATUS0_IRQ_ISAC) {667 val = ReadISAC_V2(fc, ISACX_ISTA);668 mISDNisac_irq(&fc->isac, val);669 }670 if (sval & AVM_STATUS0_IRQ_TIMER) {671 pr_debug("%s: timer irq\n", fc->name);672 outb(fc->ctrlreg | AVM_STATUS0_RES_TIMER, fc->addr + 2);673 udelay(1);674 outb(fc->ctrlreg, fc->addr + 2);675 }676 spin_unlock(&fc->lock);677 return IRQ_HANDLED;678}679 680static int681avm_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)682{683 struct bchannel *bch = container_of(ch, struct bchannel, ch);684 struct fritzcard *fc = bch->hw;685 int ret = -EINVAL;686 struct mISDNhead *hh = mISDN_HEAD_P(skb);687 unsigned long flags;688 689 switch (hh->prim) {690 case PH_DATA_REQ:691 spin_lock_irqsave(&fc->lock, flags);692 ret = bchannel_senddata(bch, skb);693 if (ret > 0) { /* direct TX */694 hdlc_fill_fifo(bch);695 ret = 0;696 }697 spin_unlock_irqrestore(&fc->lock, flags);698 return ret;699 case PH_ACTIVATE_REQ:700 spin_lock_irqsave(&fc->lock, flags);701 if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))702 ret = modehdlc(bch, ch->protocol);703 else704 ret = 0;705 spin_unlock_irqrestore(&fc->lock, flags);706 if (!ret)707 _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,708 NULL, GFP_KERNEL);709 break;710 case PH_DEACTIVATE_REQ:711 spin_lock_irqsave(&fc->lock, flags);712 mISDN_clear_bchannel(bch);713 modehdlc(bch, ISDN_P_NONE);714 spin_unlock_irqrestore(&fc->lock, flags);715 _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,716 NULL, GFP_KERNEL);717 ret = 0;718 break;719 }720 if (!ret)721 dev_kfree_skb(skb);722 return ret;723}724 725static void726inithdlc(struct fritzcard *fc)727{728 modehdlc(&fc->bch[0], -1);729 modehdlc(&fc->bch[1], -1);730}731 732static void733clear_pending_hdlc_ints(struct fritzcard *fc)734{735 u32 val;736 737 val = read_status(fc, 1);738 pr_debug("%s: HDLC 1 STA %x\n", fc->name, val);739 val = read_status(fc, 2);740 pr_debug("%s: HDLC 2 STA %x\n", fc->name, val);741}742 743static void744reset_avm(struct fritzcard *fc)745{746 switch (fc->type) {747 case AVM_FRITZ_PCI:748 fc->ctrlreg = AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER;749 break;750 case AVM_FRITZ_PCIV2:751 fc->ctrlreg = AVM_STATUS0_RESET;752 break;753 }754 if (debug & DEBUG_HW)755 pr_notice("%s: reset\n", fc->name);756 disable_hwirq(fc);757 mdelay(5);758 switch (fc->type) {759 case AVM_FRITZ_PCI:760 fc->ctrlreg = AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER;761 disable_hwirq(fc);762 outb(AVM_STATUS1_ENA_IOM, fc->addr + 3);763 break;764 case AVM_FRITZ_PCIV2:765 fc->ctrlreg = 0;766 disable_hwirq(fc);767 break;768 }769 mdelay(1);770 if (debug & DEBUG_HW)771 pr_notice("%s: S0/S1 %x/%x\n", fc->name,772 inb(fc->addr + 2), inb(fc->addr + 3));773}774 775static int776init_card(struct fritzcard *fc)777{778 int ret, cnt = 3;779 u_long flags;780 781 reset_avm(fc); /* disable IRQ */782 if (fc->type == AVM_FRITZ_PCIV2)783 ret = request_irq(fc->irq, avm_fritzv2_interrupt,784 IRQF_SHARED, fc->name, fc);785 else786 ret = request_irq(fc->irq, avm_fritz_interrupt,787 IRQF_SHARED, fc->name, fc);788 if (ret) {789 pr_info("%s: couldn't get interrupt %d\n",790 fc->name, fc->irq);791 return ret;792 }793 while (cnt--) {794 spin_lock_irqsave(&fc->lock, flags);795 ret = fc->isac.init(&fc->isac);796 if (ret) {797 spin_unlock_irqrestore(&fc->lock, flags);798 pr_info("%s: ISAC init failed with %d\n",799 fc->name, ret);800 break;801 }802 clear_pending_hdlc_ints(fc);803 inithdlc(fc);804 enable_hwirq(fc);805 /* RESET Receiver and Transmitter */806 if (fc->type == AVM_FRITZ_PCIV2) {807 WriteISAC_V2(fc, ISACX_MASK, 0);808 WriteISAC_V2(fc, ISACX_CMDRD, 0x41);809 } else {810 WriteISAC_V1(fc, ISAC_MASK, 0);811 WriteISAC_V1(fc, ISAC_CMDR, 0x41);812 }813 spin_unlock_irqrestore(&fc->lock, flags);814 /* Timeout 10ms */815 msleep_interruptible(10);816 if (debug & DEBUG_HW)817 pr_notice("%s: IRQ %d count %d\n", fc->name,818 fc->irq, fc->irqcnt);819 if (!fc->irqcnt) {820 pr_info("%s: IRQ(%d) getting no IRQs during init %d\n",821 fc->name, fc->irq, 3 - cnt);822 reset_avm(fc);823 } else824 return 0;825 }826 free_irq(fc->irq, fc);827 return -EIO;828}829 830static int831channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)832{833 return mISDN_ctrl_bchannel(bch, cq);834}835 836static int837avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)838{839 struct bchannel *bch = container_of(ch, struct bchannel, ch);840 struct fritzcard *fc = bch->hw;841 int ret = -EINVAL;842 u_long flags;843 844 pr_debug("%s: %s cmd:%x %p\n", fc->name, __func__, cmd, arg);845 switch (cmd) {846 case CLOSE_CHANNEL:847 test_and_clear_bit(FLG_OPEN, &bch->Flags);848 cancel_work_sync(&bch->workq);849 spin_lock_irqsave(&fc->lock, flags);850 mISDN_clear_bchannel(bch);851 modehdlc(bch, ISDN_P_NONE);852 spin_unlock_irqrestore(&fc->lock, flags);853 ch->protocol = ISDN_P_NONE;854 ch->peer = NULL;855 module_put(THIS_MODULE);856 ret = 0;857 break;858 case CONTROL_CHANNEL:859 ret = channel_bctrl(bch, arg);860 break;861 default:862 pr_info("%s: %s unknown prim(%x)\n", fc->name, __func__, cmd);863 }864 return ret;865}866 867static int868channel_ctrl(struct fritzcard *fc, struct mISDN_ctrl_req *cq)869{870 int ret = 0;871 872 switch (cq->op) {873 case MISDN_CTRL_GETOP:874 cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;875 break;876 case MISDN_CTRL_LOOP:877 /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */878 if (cq->channel < 0 || cq->channel > 3) {879 ret = -EINVAL;880 break;881 }882 ret = fc->isac.ctrl(&fc->isac, HW_TESTLOOP, cq->channel);883 break;884 case MISDN_CTRL_L1_TIMER3:885 ret = fc->isac.ctrl(&fc->isac, HW_TIMER3_VALUE, cq->p1);886 break;887 default:888 pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op);889 ret = -EINVAL;890 break;891 }892 return ret;893}894 895static int896open_bchannel(struct fritzcard *fc, struct channel_req *rq)897{898 struct bchannel *bch;899 900 if (rq->adr.channel == 0 || rq->adr.channel > 2)901 return -EINVAL;902 if (rq->protocol == ISDN_P_NONE)903 return -EINVAL;904 bch = &fc->bch[rq->adr.channel - 1];905 if (test_and_set_bit(FLG_OPEN, &bch->Flags))906 return -EBUSY; /* b-channel can be only open once */907 bch->ch.protocol = rq->protocol;908 rq->ch = &bch->ch;909 return 0;910}911 912/*913 * device control function914 */915static int916avm_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)917{918 struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);919 struct dchannel *dch = container_of(dev, struct dchannel, dev);920 struct fritzcard *fc = dch->hw;921 struct channel_req *rq;922 int err = 0;923 924 pr_debug("%s: %s cmd:%x %p\n", fc->name, __func__, cmd, arg);925 switch (cmd) {926 case OPEN_CHANNEL:927 rq = arg;928 if (rq->protocol == ISDN_P_TE_S0)929 err = fc->isac.open(&fc->isac, rq);930 else931 err = open_bchannel(fc, rq);932 if (err)933 break;934 if (!try_module_get(THIS_MODULE))935 pr_info("%s: cannot get module\n", fc->name);936 break;937 case CLOSE_CHANNEL:938 pr_debug("%s: dev(%d) close from %p\n", fc->name, dch->dev.id,939 __builtin_return_address(0));940 module_put(THIS_MODULE);941 break;942 case CONTROL_CHANNEL:943 err = channel_ctrl(fc, arg);944 break;945 default:946 pr_debug("%s: %s unknown command %x\n",947 fc->name, __func__, cmd);948 return -EINVAL;949 }950 return err;951}952 953static int954setup_fritz(struct fritzcard *fc)955{956 u32 val, ver;957 958 if (!request_region(fc->addr, 32, fc->name)) {959 pr_info("%s: AVM config port %x-%x already in use\n",960 fc->name, fc->addr, fc->addr + 31);961 return -EIO;962 }963 switch (fc->type) {964 case AVM_FRITZ_PCI:965 val = inl(fc->addr);966 outl(AVM_HDLC_1, fc->addr + CHIP_INDEX);967 ver = inl(fc->addr + CHIP_WINDOW + HDLC_STATUS) >> 24;968 if (debug & DEBUG_HW) {969 pr_notice("%s: PCI stat %#x\n", fc->name, val);970 pr_notice("%s: PCI Class %X Rev %d\n", fc->name,971 val & 0xff, (val >> 8) & 0xff);972 pr_notice("%s: HDLC version %x\n", fc->name, ver & 0xf);973 }974 ASSIGN_FUNC(V1, ISAC, fc->isac);975 fc->isac.type = IPAC_TYPE_ISAC;976 break;977 case AVM_FRITZ_PCIV2:978 val = inl(fc->addr);979 ver = inl(fc->addr + AVM_HDLC_STATUS_1) >> 24;980 if (debug & DEBUG_HW) {981 pr_notice("%s: PCI V2 stat %#x\n", fc->name, val);982 pr_notice("%s: PCI V2 Class %X Rev %d\n", fc->name,983 val & 0xff, (val >> 8) & 0xff);984 pr_notice("%s: HDLC version %x\n", fc->name, ver & 0xf);985 }986 ASSIGN_FUNC(V2, ISAC, fc->isac);987 fc->isac.type = IPAC_TYPE_ISACX;988 break;989 default:990 release_region(fc->addr, 32);991 pr_info("%s: AVM unknown type %d\n", fc->name, fc->type);992 return -ENODEV;993 }994 pr_notice("%s: %s config irq:%d base:0x%X\n", fc->name,995 (fc->type == AVM_FRITZ_PCI) ? "AVM Fritz!CARD PCI" :996 "AVM Fritz!CARD PCIv2", fc->irq, fc->addr);997 return 0;998}999 1000static void1001release_card(struct fritzcard *card)1002{1003 u_long flags;1004 1005 disable_hwirq(card);1006 spin_lock_irqsave(&card->lock, flags);1007 modehdlc(&card->bch[0], ISDN_P_NONE);1008 modehdlc(&card->bch[1], ISDN_P_NONE);1009 spin_unlock_irqrestore(&card->lock, flags);1010 card->isac.release(&card->isac);1011 free_irq(card->irq, card);1012 mISDN_freebchannel(&card->bch[1]);1013 mISDN_freebchannel(&card->bch[0]);1014 mISDN_unregister_device(&card->isac.dch.dev);1015 release_region(card->addr, 32);1016 pci_disable_device(card->pdev);1017 pci_set_drvdata(card->pdev, NULL);1018 write_lock_irqsave(&card_lock, flags);1019 list_del(&card->list);1020 write_unlock_irqrestore(&card_lock, flags);1021 kfree(card);1022 AVM_cnt--;1023}1024 1025static int1026setup_instance(struct fritzcard *card)1027{1028 int i, err;1029 unsigned short minsize;1030 u_long flags;1031 1032 snprintf(card->name, MISDN_MAX_IDLEN - 1, "AVM.%d", AVM_cnt + 1);1033 write_lock_irqsave(&card_lock, flags);1034 list_add_tail(&card->list, &Cards);1035 write_unlock_irqrestore(&card_lock, flags);1036 1037 _set_debug(card);1038 card->isac.name = card->name;1039 spin_lock_init(&card->lock);1040 card->isac.hwlock = &card->lock;1041 mISDNisac_init(&card->isac, card);1042 1043 card->isac.dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |1044 (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));1045 card->isac.dch.dev.D.ctrl = avm_dctrl;1046 for (i = 0; i < 2; i++) {1047 card->bch[i].nr = i + 1;1048 set_channelmap(i + 1, card->isac.dch.dev.channelmap);1049 if (AVM_FRITZ_PCIV2 == card->type)1050 minsize = HDLC_FIFO_SIZE_V2;1051 else1052 minsize = HDLC_FIFO_SIZE_V1;1053 mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM, minsize);1054 card->bch[i].hw = card;1055 card->bch[i].ch.send = avm_l2l1B;1056 card->bch[i].ch.ctrl = avm_bctrl;1057 card->bch[i].ch.nr = i + 1;1058 list_add(&card->bch[i].ch.list, &card->isac.dch.dev.bchannels);1059 }1060 err = setup_fritz(card);1061 if (err)1062 goto error;1063 err = mISDN_register_device(&card->isac.dch.dev, &card->pdev->dev,1064 card->name);1065 if (err)1066 goto error_reg;1067 err = init_card(card);1068 if (!err) {1069 AVM_cnt++;1070 pr_notice("AVM %d cards installed DEBUG\n", AVM_cnt);1071 return 0;1072 }1073 mISDN_unregister_device(&card->isac.dch.dev);1074error_reg:1075 release_region(card->addr, 32);1076error:1077 card->isac.release(&card->isac);1078 mISDN_freebchannel(&card->bch[1]);1079 mISDN_freebchannel(&card->bch[0]);1080 write_lock_irqsave(&card_lock, flags);1081 list_del(&card->list);1082 write_unlock_irqrestore(&card_lock, flags);1083 kfree(card);1084 return err;1085}1086 1087static int1088fritzpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)1089{1090 int err = -ENOMEM;1091 struct fritzcard *card;1092 1093 card = kzalloc(sizeof(struct fritzcard), GFP_KERNEL);1094 if (!card) {1095 pr_info("No kmem for fritzcard\n");1096 return err;1097 }1098 if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2)1099 card->type = AVM_FRITZ_PCIV2;1100 else1101 card->type = AVM_FRITZ_PCI;1102 card->pdev = pdev;1103 err = pci_enable_device(pdev);1104 if (err) {1105 kfree(card);1106 return err;1107 }1108 1109 pr_notice("mISDN: found adapter %s at %s\n",1110 (char *) ent->driver_data, pci_name(pdev));1111 1112 card->addr = pci_resource_start(pdev, 1);1113 card->irq = pdev->irq;1114 pci_set_drvdata(pdev, card);1115 err = setup_instance(card);1116 if (err)1117 pci_set_drvdata(pdev, NULL);1118 return err;1119}1120 1121static void1122fritz_remove_pci(struct pci_dev *pdev)1123{1124 struct fritzcard *card = pci_get_drvdata(pdev);1125 1126 if (card)1127 release_card(card);1128 else1129 if (debug)1130 pr_info("%s: drvdata already removed\n", __func__);1131}1132 1133static const struct pci_device_id fcpci_ids[] = {1134 { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID,1135 0, 0, (unsigned long) "Fritz!Card PCI"},1136 { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID,1137 0, 0, (unsigned long) "Fritz!Card PCI v2" },1138 { }1139};1140MODULE_DEVICE_TABLE(pci, fcpci_ids);1141 1142static struct pci_driver fcpci_driver = {1143 .name = "fcpci",1144 .probe = fritzpci_probe,1145 .remove = fritz_remove_pci,1146 .id_table = fcpci_ids,1147};1148 1149static int __init AVM_init(void)1150{1151 int err;1152 1153 pr_notice("AVM Fritz PCI driver Rev. %s\n", AVMFRITZ_REV);1154 err = pci_register_driver(&fcpci_driver);1155 return err;1156}1157 1158static void __exit AVM_cleanup(void)1159{1160 pci_unregister_driver(&fcpci_driver);1161}1162 1163module_init(AVM_init);1164module_exit(AVM_cleanup);1165