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