From fd042dc021fdabf981a71eed77b8c680c373529b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 7 Jul 2009 03:54:43 +0200 Subject: [PATCH] --- yaml --- r: 159068 b: refs/heads/master c: 99783e2cde6eccbd31efeb03a79f26bb5f239c36 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/isdn/Kconfig | 6 +- trunk/drivers/isdn/act2000/capi.c | 3 +- trunk/drivers/isdn/act2000/module.c | 31 +- trunk/drivers/isdn/hardware/eicon/message.c | 4 +- trunk/drivers/isdn/hardware/eicon/os_4bri.c | 3 +- trunk/drivers/isdn/hardware/mISDN/Kconfig | 51 - trunk/drivers/isdn/hardware/mISDN/Makefile | 8 - trunk/drivers/isdn/hardware/mISDN/avmfritz.c | 1152 ----------- trunk/drivers/isdn/hardware/mISDN/hfcmulti.c | 23 +- trunk/drivers/isdn/hardware/mISDN/hfcpci.c | 16 +- trunk/drivers/isdn/hardware/mISDN/hfcsusb.c | 16 +- trunk/drivers/isdn/hardware/mISDN/iohelper.h | 109 -- trunk/drivers/isdn/hardware/mISDN/ipac.h | 405 ---- trunk/drivers/isdn/hardware/mISDN/isar.h | 269 --- .../isdn/hardware/mISDN/mISDNinfineon.c | 1178 ----------- trunk/drivers/isdn/hardware/mISDN/mISDNipac.c | 1655 ---------------- trunk/drivers/isdn/hardware/mISDN/mISDNisar.c | 1726 ----------------- trunk/drivers/isdn/hardware/mISDN/netjet.c | 1156 ----------- trunk/drivers/isdn/hardware/mISDN/netjet.h | 58 - trunk/drivers/isdn/hardware/mISDN/speedfax.c | 526 ----- trunk/drivers/isdn/hardware/mISDN/w6692.c | 1440 -------------- trunk/drivers/isdn/hardware/mISDN/w6692.h | 190 -- trunk/drivers/isdn/hisax/Kconfig | 6 +- trunk/drivers/isdn/hisax/Makefile | 4 + trunk/drivers/isdn/hisax/amd7930_fn.c | 2 + trunk/drivers/isdn/hisax/callc.c | 4 +- trunk/drivers/isdn/hisax/hfc_pci.c | 2 + trunk/drivers/isdn/hisax/hfc_sx.c | 2 + trunk/drivers/isdn/hisax/icc.c | 2 + trunk/drivers/isdn/hisax/isac.c | 2 + trunk/drivers/isdn/{i4l => hisax}/isdnhdlc.c | 429 ++-- trunk/drivers/isdn/hisax/isdnhdlc.h | 70 + trunk/drivers/isdn/hisax/isdnl1.c | 12 +- trunk/drivers/isdn/hisax/isdnl2.c | 4 +- trunk/drivers/isdn/hisax/isdnl3.c | 4 +- trunk/drivers/isdn/hisax/l3_1tr6.c | 20 +- trunk/drivers/isdn/hisax/l3dss1.c | 26 +- trunk/drivers/isdn/hisax/l3ni1.c | 26 +- trunk/drivers/isdn/hisax/q931.c | 24 +- trunk/drivers/isdn/hisax/st5481.h | 2 +- trunk/drivers/isdn/hisax/st5481_b.c | 5 +- trunk/drivers/isdn/hisax/st5481_d.c | 2 +- trunk/drivers/isdn/hisax/st5481_usb.c | 11 +- trunk/drivers/isdn/hisax/tei.c | 4 +- trunk/drivers/isdn/hisax/w6692.c | 2 + trunk/drivers/isdn/i4l/Kconfig | 11 - trunk/drivers/isdn/i4l/Makefile | 1 - trunk/drivers/isdn/mISDN/hwchannel.c | 15 +- trunk/drivers/isdn/mISDN/layer2.c | 2 + trunk/drivers/net/igb/e1000_82575.c | 193 +- trunk/drivers/net/igb/e1000_82575.h | 6 +- trunk/drivers/net/igb/e1000_defines.h | 8 - trunk/drivers/net/igb/e1000_hw.h | 18 +- trunk/drivers/net/igb/e1000_mac.c | 175 +- trunk/drivers/net/igb/e1000_mac.h | 3 - trunk/drivers/net/igb/e1000_phy.c | 4 +- trunk/drivers/net/igb/e1000_regs.h | 1 - trunk/drivers/net/igb/igb_ethtool.c | 65 +- trunk/drivers/net/igb/igb_main.c | 121 +- trunk/drivers/net/igbvf/netdev.c | 5 +- trunk/include/linux/isdn/hdlc.h | 82 - trunk/include/linux/mISDNhw.h | 1 - trunk/include/linux/mISDNif.h | 16 +- trunk/net/mac80211/cfg.c | 2 +- 65 files changed, 754 insertions(+), 10667 deletions(-) delete mode 100644 trunk/drivers/isdn/hardware/mISDN/avmfritz.c delete mode 100644 trunk/drivers/isdn/hardware/mISDN/iohelper.h delete mode 100644 trunk/drivers/isdn/hardware/mISDN/ipac.h delete mode 100644 trunk/drivers/isdn/hardware/mISDN/isar.h delete mode 100644 trunk/drivers/isdn/hardware/mISDN/mISDNinfineon.c delete mode 100644 trunk/drivers/isdn/hardware/mISDN/mISDNipac.c delete mode 100644 trunk/drivers/isdn/hardware/mISDN/mISDNisar.c delete mode 100644 trunk/drivers/isdn/hardware/mISDN/netjet.c delete mode 100644 trunk/drivers/isdn/hardware/mISDN/netjet.h delete mode 100644 trunk/drivers/isdn/hardware/mISDN/speedfax.c delete mode 100644 trunk/drivers/isdn/hardware/mISDN/w6692.c delete mode 100644 trunk/drivers/isdn/hardware/mISDN/w6692.h rename trunk/drivers/isdn/{i4l => hisax}/isdnhdlc.c (54%) create mode 100644 trunk/drivers/isdn/hisax/isdnhdlc.h delete mode 100644 trunk/include/linux/isdn/hdlc.h diff --git a/[refs] b/[refs] index 6fe1cbaf5c0b..a0f971734611 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 436b355b96042ab6564f43a7dabd5c61d9634ff7 +refs/heads/master: 99783e2cde6eccbd31efeb03a79f26bb5f239c36 diff --git a/trunk/drivers/isdn/Kconfig b/trunk/drivers/isdn/Kconfig index 022a19452953..02bdca6f95c3 100644 --- a/trunk/drivers/isdn/Kconfig +++ b/trunk/drivers/isdn/Kconfig @@ -21,6 +21,8 @@ menuconfig ISDN if ISDN +source "drivers/isdn/mISDN/Kconfig" + menuconfig ISDN_I4L tristate "Old ISDN4Linux (deprecated)" ---help--- @@ -39,9 +41,9 @@ menuconfig ISDN_I4L It is still available, though, for use with adapters that are not supported by the new CAPI subsystem yet. -source "drivers/isdn/mISDN/Kconfig" - +if ISDN_I4L source "drivers/isdn/i4l/Kconfig" +endif menuconfig ISDN_CAPI tristate "CAPI 2.0 subsystem" diff --git a/trunk/drivers/isdn/act2000/capi.c b/trunk/drivers/isdn/act2000/capi.c index 1f0a94906465..946c38cf6f8a 100644 --- a/trunk/drivers/isdn/act2000/capi.c +++ b/trunk/drivers/isdn/act2000/capi.c @@ -78,6 +78,7 @@ static actcapi_msgdsc valid_msg[] = { #endif {{ 0x00, 0x00}, NULL}, }; +#define num_valid_msg (sizeof(valid_msg)/sizeof(actcapi_msgdsc)) #define num_valid_imsg 27 /* MANUFACTURER_IND */ /* @@ -1024,7 +1025,7 @@ actcapi_debug_msg(struct sk_buff *skb, int direction) #ifdef DEBUG_DUMP_SKB dump_skb(skb); #endif - for (i = 0; i < ARRAY_SIZE(valid_msg); i++) + for (i = 0; i < num_valid_msg; i++) if ((msg->hdr.cmd.cmd == valid_msg[i].cmd.cmd) && (msg->hdr.cmd.subcmd == valid_msg[i].cmd.subcmd)) { descr = valid_msg[i].description; diff --git a/trunk/drivers/isdn/act2000/module.c b/trunk/drivers/isdn/act2000/module.c index f774e12bb64d..8325022e2bed 100644 --- a/trunk/drivers/isdn/act2000/module.c +++ b/trunk/drivers/isdn/act2000/module.c @@ -23,6 +23,7 @@ static unsigned short act2000_isa_ports[] = 0x0200, 0x0240, 0x0280, 0x02c0, 0x0300, 0x0340, 0x0380, 0xcfe0, 0xcfa0, 0xcf60, 0xcf20, 0xcee0, 0xcea0, 0xce60, }; +#define ISA_NRPORTS (sizeof(act2000_isa_ports)/sizeof(unsigned short)) static act2000_card *cards = (act2000_card *) NULL; @@ -685,21 +686,21 @@ act2000_addcard(int bus, int port, int irq, char *id) * This may result in more than one card detected. */ switch (bus) { - case ACT2000_BUS_ISA: - for (i = 0; i < ARRAY_SIZE(act2000_isa_ports); i++) - if (act2000_isa_detect(act2000_isa_ports[i])) { - printk(KERN_INFO "act2000: Detected " - "ISA card at port 0x%x\n", - act2000_isa_ports[i]); - act2000_alloccard(bus, - act2000_isa_ports[i], irq, id); - } - break; - case ACT2000_BUS_MCA: - case ACT2000_BUS_PCMCIA: - default: - printk(KERN_WARNING - "act2000: addcard: Invalid BUS type %d\n", bus); + case ACT2000_BUS_ISA: + for (i = 0; i < ISA_NRPORTS; i++) + if (act2000_isa_detect(act2000_isa_ports[i])) { + printk(KERN_INFO + "act2000: Detected ISA card at port 0x%x\n", + act2000_isa_ports[i]); + act2000_alloccard(bus, act2000_isa_ports[i], irq, id); + } + break; + case ACT2000_BUS_MCA: + case ACT2000_BUS_PCMCIA: + default: + printk(KERN_WARNING + "act2000: addcard: Invalid BUS type %d\n", + bus); } } if (!cards) diff --git a/trunk/drivers/isdn/hardware/eicon/message.c b/trunk/drivers/isdn/hardware/eicon/message.c index 27d5dd68f4fb..31f91c18c698 100644 --- a/trunk/drivers/isdn/hardware/eicon/message.c +++ b/trunk/drivers/isdn/hardware/eicon/message.c @@ -551,7 +551,9 @@ word api_put(APPL * appl, CAPI_MSG * msg) dbug(1,dprintf("com=%x",msg->header.command)); for(j=0;jheader.command) { /* break loop if the message is correct, otherwise continue scan */ diff --git a/trunk/drivers/isdn/hardware/eicon/os_4bri.c b/trunk/drivers/isdn/hardware/eicon/os_4bri.c index cb7616c5b60a..c964b8d91ada 100644 --- a/trunk/drivers/isdn/hardware/eicon/os_4bri.c +++ b/trunk/drivers/isdn/hardware/eicon/os_4bri.c @@ -149,7 +149,8 @@ int diva_4bri_init_card(diva_os_xdi_adapter_t * a) diva_os_xdi_adapter_t *diva_current; diva_os_xdi_adapter_t *adapter_list[4]; PISDN_ADAPTER Slave; - unsigned long bar_length[ARRAY_SIZE(_4bri_bar_length)]; + unsigned long bar_length[sizeof(_4bri_bar_length) / + sizeof(_4bri_bar_length[0])]; int v2 = _4bri_is_rev_2_card(a->CardOrdinal); int tasks = _4bri_is_rev_2_bri_card(a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT; int factor = (tasks == 1) ? 1 : 2; diff --git a/trunk/drivers/isdn/hardware/mISDN/Kconfig b/trunk/drivers/isdn/hardware/mISDN/Kconfig index bde55d7287fa..3024566dd099 100644 --- a/trunk/drivers/isdn/hardware/mISDN/Kconfig +++ b/trunk/drivers/isdn/hardware/mISDN/Kconfig @@ -39,54 +39,3 @@ config MISDN_HFCUSB Enable support for USB ISDN TAs with Cologne Chip AG's HFC-S USB ISDN Controller -config MISDN_AVMFRITZ - tristate "Support for AVM FRITZ!CARD PCI" - depends on MISDN - depends on PCI - select MISDN_IPAC - help - Enable support for AVMs FRITZ!CARD PCI cards - -config MISDN_SPEEDFAX - tristate "Support for Sedlbauer Speedfax+" - depends on MISDN - depends on PCI - select MISDN_IPAC - select MISDN_ISAR - help - Enable support for Sedlbauer Speedfax+. - -config MISDN_INFINEON - tristate "Support for cards with Infineon chipset" - depends on MISDN - depends on PCI - select MISDN_IPAC - help - Enable support for cards with ISAC + HSCX, IPAC or IPAC-SX - chip from Infineon (former manufacturer Siemens). - -config MISDN_W6692 - tristate "Support for cards with Winbond 6692" - depends on MISDN - depends on PCI - help - Enable support for Winbond 6692 PCI chip based cards. - -config MISDN_NETJET - tristate "Support for NETJet cards" - depends on MISDN - depends on PCI - select MISDN_IPAC - select ISDN_HDLC - help - Enable support for Traverse Technologies NETJet PCI cards. - - -config MISDN_IPAC - tristate - depends on MISDN - -config MISDN_ISAR - tristate - depends on MISDN - diff --git a/trunk/drivers/isdn/hardware/mISDN/Makefile b/trunk/drivers/isdn/hardware/mISDN/Makefile index 2987d990993f..b0403526bbba 100644 --- a/trunk/drivers/isdn/hardware/mISDN/Makefile +++ b/trunk/drivers/isdn/hardware/mISDN/Makefile @@ -6,11 +6,3 @@ obj-$(CONFIG_MISDN_HFCPCI) += hfcpci.o obj-$(CONFIG_MISDN_HFCMULTI) += hfcmulti.o obj-$(CONFIG_MISDN_HFCUSB) += hfcsusb.o -obj-$(CONFIG_MISDN_AVMFRITZ) += avmfritz.o -obj-$(CONFIG_MISDN_SPEEDFAX) += speedfax.o -obj-$(CONFIG_MISDN_INFINEON) += mISDNinfineon.o -obj-$(CONFIG_MISDN_W6692) += w6692.o -obj-$(CONFIG_MISDN_NETJET) += netjet.o -# chip modules -obj-$(CONFIG_MISDN_IPAC) += mISDNipac.o -obj-$(CONFIG_MISDN_ISAR) += mISDNisar.o diff --git a/trunk/drivers/isdn/hardware/mISDN/avmfritz.c b/trunk/drivers/isdn/hardware/mISDN/avmfritz.c deleted file mode 100644 index 81ac541d40d9..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/avmfritz.c +++ /dev/null @@ -1,1152 +0,0 @@ -/* - * avm_fritz.c low level stuff for AVM FRITZ!CARD PCI ISDN cards - * Thanks to AVM, Berlin for informations - * - * Author Karsten Keil - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include -#include -#include -#include -#include -#include "ipac.h" - - -#define AVMFRITZ_REV "2.1" - -static int AVM_cnt; -static int debug; - -enum { - AVM_FRITZ_PCI, - AVM_FRITZ_PCIV2, -}; - -#define HDLC_FIFO 0x0 -#define HDLC_STATUS 0x4 -#define CHIP_WINDOW 0x10 - -#define CHIP_INDEX 0x4 -#define AVM_HDLC_1 0x00 -#define AVM_HDLC_2 0x01 -#define AVM_ISAC_FIFO 0x02 -#define AVM_ISAC_REG_LOW 0x04 -#define AVM_ISAC_REG_HIGH 0x06 - -#define AVM_STATUS0_IRQ_ISAC 0x01 -#define AVM_STATUS0_IRQ_HDLC 0x02 -#define AVM_STATUS0_IRQ_TIMER 0x04 -#define AVM_STATUS0_IRQ_MASK 0x07 - -#define AVM_STATUS0_RESET 0x01 -#define AVM_STATUS0_DIS_TIMER 0x02 -#define AVM_STATUS0_RES_TIMER 0x04 -#define AVM_STATUS0_ENA_IRQ 0x08 -#define AVM_STATUS0_TESTBIT 0x10 - -#define AVM_STATUS1_INT_SEL 0x0f -#define AVM_STATUS1_ENA_IOM 0x80 - -#define HDLC_MODE_ITF_FLG 0x01 -#define HDLC_MODE_TRANS 0x02 -#define HDLC_MODE_CCR_7 0x04 -#define HDLC_MODE_CCR_16 0x08 -#define HDLC_MODE_TESTLOOP 0x80 - -#define HDLC_INT_XPR 0x80 -#define HDLC_INT_XDU 0x40 -#define HDLC_INT_RPR 0x20 -#define HDLC_INT_MASK 0xE0 - -#define HDLC_STAT_RME 0x01 -#define HDLC_STAT_RDO 0x10 -#define HDLC_STAT_CRCVFRRAB 0x0E -#define HDLC_STAT_CRCVFR 0x06 -#define HDLC_STAT_RML_MASK 0x3f00 - -#define HDLC_CMD_XRS 0x80 -#define HDLC_CMD_XME 0x01 -#define HDLC_CMD_RRS 0x20 -#define HDLC_CMD_XML_MASK 0x3f00 -#define HDLC_FIFO_SIZE 32 - -/* Fritz PCI v2.0 */ - -#define AVM_HDLC_FIFO_1 0x10 -#define AVM_HDLC_FIFO_2 0x18 - -#define AVM_HDLC_STATUS_1 0x14 -#define AVM_HDLC_STATUS_2 0x1c - -#define AVM_ISACX_INDEX 0x04 -#define AVM_ISACX_DATA 0x08 - -/* data struct */ -#define LOG_SIZE 63 - -struct hdlc_stat_reg { -#ifdef __BIG_ENDIAN - u8 fill; - u8 mode; - u8 xml; - u8 cmd; -#else - u8 cmd; - u8 xml; - u8 mode; - u8 fill; -#endif -} __attribute__((packed)); - -struct hdlc_hw { - union { - u32 ctrl; - struct hdlc_stat_reg sr; - } ctrl; - u32 stat; -}; - -struct fritzcard { - struct list_head list; - struct pci_dev *pdev; - char name[MISDN_MAX_IDLEN]; - u8 type; - u8 ctrlreg; - u16 irq; - u32 irqcnt; - u32 addr; - spinlock_t lock; /* hw lock */ - struct isac_hw isac; - struct hdlc_hw hdlc[2]; - struct bchannel bch[2]; - char log[LOG_SIZE + 1]; -}; - -static LIST_HEAD(Cards); -static DEFINE_RWLOCK(card_lock); /* protect Cards */ - -static void -_set_debug(struct fritzcard *card) -{ - card->isac.dch.debug = debug; - card->bch[0].debug = debug; - card->bch[1].debug = debug; -} - -static int -set_debug(const char *val, struct kernel_param *kp) -{ - int ret; - struct fritzcard *card; - - ret = param_set_uint(val, kp); - if (!ret) { - read_lock(&card_lock); - list_for_each_entry(card, &Cards, list) - _set_debug(card); - read_unlock(&card_lock); - } - return ret; -} - -MODULE_AUTHOR("Karsten Keil"); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(AVMFRITZ_REV); -module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "avmfritz debug mask"); - -/* Interface functions */ - -static u8 -ReadISAC_V1(void *p, u8 offset) -{ - struct fritzcard *fc = p; - u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; - - outb(idx, fc->addr + CHIP_INDEX); - return inb(fc->addr + CHIP_WINDOW + (offset & 0xf)); -} - -static void -WriteISAC_V1(void *p, u8 offset, u8 value) -{ - struct fritzcard *fc = p; - u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; - - outb(idx, fc->addr + CHIP_INDEX); - outb(value, fc->addr + CHIP_WINDOW + (offset & 0xf)); -} - -static void -ReadFiFoISAC_V1(void *p, u8 off, u8 *data, int size) -{ - struct fritzcard *fc = p; - - outb(AVM_ISAC_FIFO, fc->addr + CHIP_INDEX); - insb(fc->addr + CHIP_WINDOW, data, size); -} - -static void -WriteFiFoISAC_V1(void *p, u8 off, u8 *data, int size) -{ - struct fritzcard *fc = p; - - outb(AVM_ISAC_FIFO, fc->addr + CHIP_INDEX); - outsb(fc->addr + CHIP_WINDOW, data, size); -} - -static u8 -ReadISAC_V2(void *p, u8 offset) -{ - struct fritzcard *fc = p; - - outl(offset, fc->addr + AVM_ISACX_INDEX); - return 0xff & inl(fc->addr + AVM_ISACX_DATA); -} - -static void -WriteISAC_V2(void *p, u8 offset, u8 value) -{ - struct fritzcard *fc = p; - - outl(offset, fc->addr + AVM_ISACX_INDEX); - outl(value, fc->addr + AVM_ISACX_DATA); -} - -static void -ReadFiFoISAC_V2(void *p, u8 off, u8 *data, int size) -{ - struct fritzcard *fc = p; - int i; - - outl(off, fc->addr + AVM_ISACX_INDEX); - for (i = 0; i < size; i++) - data[i] = 0xff & inl(fc->addr + AVM_ISACX_DATA); -} - -static void -WriteFiFoISAC_V2(void *p, u8 off, u8 *data, int size) -{ - struct fritzcard *fc = p; - int i; - - outl(off, fc->addr + AVM_ISACX_INDEX); - for (i = 0; i < size; i++) - outl(data[i], fc->addr + AVM_ISACX_DATA); -} - -static struct bchannel * -Sel_BCS(struct fritzcard *fc, u32 channel) -{ - if (test_bit(FLG_ACTIVE, &fc->bch[0].Flags) && - (fc->bch[0].nr & channel)) - return &fc->bch[0]; - else if (test_bit(FLG_ACTIVE, &fc->bch[1].Flags) && - (fc->bch[1].nr & channel)) - return &fc->bch[1]; - else - return NULL; -} - -static inline void -__write_ctrl_pci(struct fritzcard *fc, struct hdlc_hw *hdlc, u32 channel) { - u32 idx = channel == 2 ? AVM_HDLC_2 : AVM_HDLC_1; - - outl(idx, fc->addr + CHIP_INDEX); - outl(hdlc->ctrl.ctrl, fc->addr + CHIP_WINDOW + HDLC_STATUS); -} - -static inline void -__write_ctrl_pciv2(struct fritzcard *fc, struct hdlc_hw *hdlc, u32 channel) { - outl(hdlc->ctrl.ctrl, fc->addr + (channel == 2 ? AVM_HDLC_STATUS_2 : - AVM_HDLC_STATUS_1)); -} - -void -write_ctrl(struct bchannel *bch, int which) { - struct fritzcard *fc = bch->hw; - struct hdlc_hw *hdlc; - - hdlc = &fc->hdlc[(bch->nr - 1) & 1]; - pr_debug("%s: hdlc %c wr%x ctrl %x\n", fc->name, '@' + bch->nr, - which, hdlc->ctrl.ctrl); - switch (fc->type) { - case AVM_FRITZ_PCIV2: - __write_ctrl_pciv2(fc, hdlc, bch->nr); - break; - case AVM_FRITZ_PCI: - __write_ctrl_pci(fc, hdlc, bch->nr); - break; - } -} - - -static inline u32 -__read_status_pci(u_long addr, u32 channel) -{ - outl(channel == 2 ? AVM_HDLC_2 : AVM_HDLC_1, addr + CHIP_INDEX); - return inl(addr + CHIP_WINDOW + HDLC_STATUS); -} - -static inline u32 -__read_status_pciv2(u_long addr, u32 channel) -{ - return inl(addr + (channel == 2 ? AVM_HDLC_STATUS_2 : - AVM_HDLC_STATUS_1)); -} - - -static u32 -read_status(struct fritzcard *fc, u32 channel) -{ - switch (fc->type) { - case AVM_FRITZ_PCIV2: - return __read_status_pciv2(fc->addr, channel); - case AVM_FRITZ_PCI: - return __read_status_pci(fc->addr, channel); - } - /* dummy */ - return 0; -} - -static void -enable_hwirq(struct fritzcard *fc) -{ - fc->ctrlreg |= AVM_STATUS0_ENA_IRQ; - outb(fc->ctrlreg, fc->addr + 2); -} - -static void -disable_hwirq(struct fritzcard *fc) -{ - fc->ctrlreg &= ~AVM_STATUS0_ENA_IRQ; - outb(fc->ctrlreg, fc->addr + 2); -} - -static int -modehdlc(struct bchannel *bch, int protocol) -{ - struct fritzcard *fc = bch->hw; - struct hdlc_hw *hdlc; - - hdlc = &fc->hdlc[(bch->nr - 1) & 1]; - pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name, - '@' + bch->nr, bch->state, protocol, bch->nr); - hdlc->ctrl.ctrl = 0; - switch (protocol) { - case -1: /* used for init */ - bch->state = -1; - case ISDN_P_NONE: - if (bch->state == ISDN_P_NONE) - break; - hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; - hdlc->ctrl.sr.mode = HDLC_MODE_TRANS; - write_ctrl(bch, 5); - bch->state = ISDN_P_NONE; - test_and_clear_bit(FLG_HDLC, &bch->Flags); - test_and_clear_bit(FLG_TRANSPARENT, &bch->Flags); - break; - case ISDN_P_B_RAW: - bch->state = protocol; - hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; - hdlc->ctrl.sr.mode = HDLC_MODE_TRANS; - write_ctrl(bch, 5); - hdlc->ctrl.sr.cmd = HDLC_CMD_XRS; - write_ctrl(bch, 1); - hdlc->ctrl.sr.cmd = 0; - test_and_set_bit(FLG_TRANSPARENT, &bch->Flags); - break; - case ISDN_P_B_HDLC: - bch->state = protocol; - hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; - hdlc->ctrl.sr.mode = HDLC_MODE_ITF_FLG; - write_ctrl(bch, 5); - hdlc->ctrl.sr.cmd = HDLC_CMD_XRS; - write_ctrl(bch, 1); - hdlc->ctrl.sr.cmd = 0; - test_and_set_bit(FLG_HDLC, &bch->Flags); - break; - default: - pr_info("%s: protocol not known %x\n", fc->name, protocol); - return -ENOPROTOOPT; - } - return 0; -} - -static void -hdlc_empty_fifo(struct bchannel *bch, int count) -{ - u32 *ptr; - u8 *p; - u32 val, addr; - int cnt = 0; - struct fritzcard *fc = bch->hw; - - pr_debug("%s: %s %d\n", fc->name, __func__, count); - if (!bch->rx_skb) { - bch->rx_skb = mI_alloc_skb(bch->maxlen, GFP_ATOMIC); - if (!bch->rx_skb) { - pr_info("%s: B receive out of memory\n", - fc->name); - return; - } - } - if ((bch->rx_skb->len + count) > bch->maxlen) { - pr_debug("%s: overrun %d\n", fc->name, - bch->rx_skb->len + count); - return; - } - p = skb_put(bch->rx_skb, count); - ptr = (u32 *)p; - if (AVM_FRITZ_PCIV2 == fc->type) - addr = fc->addr + (bch->nr == 2 ? - AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1); - else { - addr = fc->addr + CHIP_WINDOW; - outl(bch->nr == 2 ? AVM_HDLC_2 : AVM_HDLC_1, fc->addr); - } - while (cnt < count) { - val = le32_to_cpu(inl(addr)); - put_unaligned(val, ptr); - ptr++; - cnt += 4; - } - if (debug & DEBUG_HW_BFIFO) { - snprintf(fc->log, LOG_SIZE, "B%1d-recv %s %d ", - bch->nr, fc->name, count); - print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count); - } -} - -static void -hdlc_fill_fifo(struct bchannel *bch) -{ - struct fritzcard *fc = bch->hw; - struct hdlc_hw *hdlc; - int count, cnt = 0; - u8 *p; - u32 *ptr, val, addr; - - hdlc = &fc->hdlc[(bch->nr - 1) & 1]; - if (!bch->tx_skb) - return; - count = bch->tx_skb->len - bch->tx_idx; - if (count <= 0) - return; - p = bch->tx_skb->data + bch->tx_idx; - hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME; - if (count > HDLC_FIFO_SIZE) { - count = HDLC_FIFO_SIZE; - } else { - if (test_bit(FLG_HDLC, &bch->Flags)) - hdlc->ctrl.sr.cmd |= HDLC_CMD_XME; - } - pr_debug("%s: %s %d/%d/%d", fc->name, __func__, count, - bch->tx_idx, bch->tx_skb->len); - ptr = (u32 *)p; - bch->tx_idx += count; - hdlc->ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count); - if (AVM_FRITZ_PCIV2 == fc->type) { - __write_ctrl_pciv2(fc, hdlc, bch->nr); - addr = fc->addr + (bch->nr == 2 ? - AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1); - } else { - __write_ctrl_pci(fc, hdlc, bch->nr); - addr = fc->addr + CHIP_WINDOW; - } - while (cnt < count) { - val = get_unaligned(ptr); - outl(cpu_to_le32(val), addr); - ptr++; - cnt += 4; - } - if (debug & DEBUG_HW_BFIFO) { - snprintf(fc->log, LOG_SIZE, "B%1d-send %s %d ", - bch->nr, fc->name, count); - print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count); - } -} - -static void -HDLC_irq_xpr(struct bchannel *bch) -{ - if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) - hdlc_fill_fifo(bch); - else { - if (bch->tx_skb) { - /* send confirm, on trans, free on hdlc. */ - if (test_bit(FLG_TRANSPARENT, &bch->Flags)) - confirm_Bsend(bch); - dev_kfree_skb(bch->tx_skb); - } - if (get_next_bframe(bch)) - hdlc_fill_fifo(bch); - } -} - -static void -HDLC_irq(struct bchannel *bch, u32 stat) -{ - struct fritzcard *fc = bch->hw; - int len; - struct hdlc_hw *hdlc; - - hdlc = &fc->hdlc[(bch->nr - 1) & 1]; - pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat); - if (stat & HDLC_INT_RPR) { - if (stat & HDLC_STAT_RDO) { - hdlc->ctrl.sr.xml = 0; - hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS; - write_ctrl(bch, 1); - hdlc->ctrl.sr.cmd &= ~HDLC_CMD_RRS; - write_ctrl(bch, 1); - if (bch->rx_skb) - skb_trim(bch->rx_skb, 0); - } else { - len = (stat & HDLC_STAT_RML_MASK) >> 8; - if (!len) - len = 32; - hdlc_empty_fifo(bch, len); - if (!bch->rx_skb) - goto handle_tx; - if ((stat & HDLC_STAT_RME) || test_bit(FLG_TRANSPARENT, - &bch->Flags)) { - if (((stat & HDLC_STAT_CRCVFRRAB) == - HDLC_STAT_CRCVFR) || - test_bit(FLG_TRANSPARENT, &bch->Flags)) { - recv_Bchannel(bch, 0); - } else { - pr_debug("%s: got invalid frame\n", - fc->name); - skb_trim(bch->rx_skb, 0); - } - } - } - } -handle_tx: - if (stat & HDLC_INT_XDU) { - /* Here we lost an TX interrupt, so - * restart transmitting the whole frame on HDLC - * in transparent mode we send the next data - */ - if (bch->tx_skb) - pr_debug("%s: ch%d XDU len(%d) idx(%d) Flags(%lx)\n", - fc->name, bch->nr, bch->tx_skb->len, - bch->tx_idx, bch->Flags); - else - pr_debug("%s: ch%d XDU no tx_skb Flags(%lx)\n", - fc->name, bch->nr, bch->Flags); - if (bch->tx_skb && bch->tx_skb->len) { - if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) - bch->tx_idx = 0; - } - hdlc->ctrl.sr.xml = 0; - hdlc->ctrl.sr.cmd |= HDLC_CMD_XRS; - write_ctrl(bch, 1); - hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XRS; - HDLC_irq_xpr(bch); - return; - } else if (stat & HDLC_INT_XPR) - HDLC_irq_xpr(bch); -} - -static inline void -HDLC_irq_main(struct fritzcard *fc) -{ - u32 stat; - struct bchannel *bch; - - stat = read_status(fc, 1); - if (stat & HDLC_INT_MASK) { - bch = Sel_BCS(fc, 1); - if (bch) - HDLC_irq(bch, stat); - else - pr_debug("%s: spurious ch1 IRQ\n", fc->name); - } - stat = read_status(fc, 2); - if (stat & HDLC_INT_MASK) { - bch = Sel_BCS(fc, 2); - if (bch) - HDLC_irq(bch, stat); - else - pr_debug("%s: spurious ch2 IRQ\n", fc->name); - } -} - -static irqreturn_t -avm_fritz_interrupt(int intno, void *dev_id) -{ - struct fritzcard *fc = dev_id; - u8 val; - u8 sval; - - spin_lock(&fc->lock); - sval = inb(fc->addr + 2); - pr_debug("%s: irq stat0 %x\n", fc->name, sval); - if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) { - /* shared IRQ from other HW */ - spin_unlock(&fc->lock); - return IRQ_NONE; - } - fc->irqcnt++; - - if (!(sval & AVM_STATUS0_IRQ_ISAC)) { - val = ReadISAC_V1(fc, ISAC_ISTA); - mISDNisac_irq(&fc->isac, val); - } - if (!(sval & AVM_STATUS0_IRQ_HDLC)) - HDLC_irq_main(fc); - spin_unlock(&fc->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -avm_fritzv2_interrupt(int intno, void *dev_id) -{ - struct fritzcard *fc = dev_id; - u8 val; - u8 sval; - - spin_lock(&fc->lock); - sval = inb(fc->addr + 2); - pr_debug("%s: irq stat0 %x\n", fc->name, sval); - if (!(sval & AVM_STATUS0_IRQ_MASK)) { - /* shared IRQ from other HW */ - spin_unlock(&fc->lock); - return IRQ_NONE; - } - fc->irqcnt++; - - if (sval & AVM_STATUS0_IRQ_HDLC) - HDLC_irq_main(fc); - if (sval & AVM_STATUS0_IRQ_ISAC) { - val = ReadISAC_V2(fc, ISACX_ISTA); - mISDNisac_irq(&fc->isac, val); - } - if (sval & AVM_STATUS0_IRQ_TIMER) { - pr_debug("%s: timer irq\n", fc->name); - outb(fc->ctrlreg | AVM_STATUS0_RES_TIMER, fc->addr + 2); - udelay(1); - outb(fc->ctrlreg, fc->addr + 2); - } - spin_unlock(&fc->lock); - return IRQ_HANDLED; -} - -static int -avm_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb) -{ - struct bchannel *bch = container_of(ch, struct bchannel, ch); - struct fritzcard *fc = bch->hw; - int ret = -EINVAL; - struct mISDNhead *hh = mISDN_HEAD_P(skb); - u32 id; - u_long flags; - - switch (hh->prim) { - case PH_DATA_REQ: - spin_lock_irqsave(&fc->lock, flags); - ret = bchannel_senddata(bch, skb); - if (ret > 0) { /* direct TX */ - id = hh->id; /* skb can be freed */ - hdlc_fill_fifo(bch); - ret = 0; - spin_unlock_irqrestore(&fc->lock, flags); - if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) - queue_ch_frame(ch, PH_DATA_CNF, id, NULL); - } else - spin_unlock_irqrestore(&fc->lock, flags); - return ret; - case PH_ACTIVATE_REQ: - spin_lock_irqsave(&fc->lock, flags); - if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) - ret = modehdlc(bch, ch->protocol); - else - ret = 0; - spin_unlock_irqrestore(&fc->lock, flags); - if (!ret) - _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, - NULL, GFP_KERNEL); - break; - case PH_DEACTIVATE_REQ: - spin_lock_irqsave(&fc->lock, flags); - mISDN_clear_bchannel(bch); - modehdlc(bch, ISDN_P_NONE); - spin_unlock_irqrestore(&fc->lock, flags); - _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, - NULL, GFP_KERNEL); - ret = 0; - break; - } - if (!ret) - dev_kfree_skb(skb); - return ret; -} - -static void -inithdlc(struct fritzcard *fc) -{ - modehdlc(&fc->bch[0], -1); - modehdlc(&fc->bch[1], -1); -} - -void -clear_pending_hdlc_ints(struct fritzcard *fc) -{ - u32 val; - - val = read_status(fc, 1); - pr_debug("%s: HDLC 1 STA %x\n", fc->name, val); - val = read_status(fc, 2); - pr_debug("%s: HDLC 2 STA %x\n", fc->name, val); -} - -static void -reset_avm(struct fritzcard *fc) -{ - switch (fc->type) { - case AVM_FRITZ_PCI: - fc->ctrlreg = AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER; - break; - case AVM_FRITZ_PCIV2: - fc->ctrlreg = AVM_STATUS0_RESET; - break; - } - if (debug & DEBUG_HW) - pr_notice("%s: reset\n", fc->name); - disable_hwirq(fc); - mdelay(5); - switch (fc->type) { - case AVM_FRITZ_PCI: - fc->ctrlreg = AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER; - disable_hwirq(fc); - outb(AVM_STATUS1_ENA_IOM, fc->addr + 3); - break; - case AVM_FRITZ_PCIV2: - fc->ctrlreg = 0; - disable_hwirq(fc); - break; - } - mdelay(1); - if (debug & DEBUG_HW) - pr_notice("%s: S0/S1 %x/%x\n", fc->name, - inb(fc->addr + 2), inb(fc->addr + 3)); -} - -static int -init_card(struct fritzcard *fc) -{ - int ret, cnt = 3; - u_long flags; - - reset_avm(fc); /* disable IRQ */ - if (fc->type == AVM_FRITZ_PCIV2) - ret = request_irq(fc->irq, avm_fritzv2_interrupt, - IRQF_SHARED, fc->name, fc); - else - ret = request_irq(fc->irq, avm_fritz_interrupt, - IRQF_SHARED, fc->name, fc); - if (ret) { - pr_info("%s: couldn't get interrupt %d\n", - fc->name, fc->irq); - return ret; - } - while (cnt--) { - spin_lock_irqsave(&fc->lock, flags); - ret = fc->isac.init(&fc->isac); - if (ret) { - spin_unlock_irqrestore(&fc->lock, flags); - pr_info("%s: ISAC init failed with %d\n", - fc->name, ret); - break; - } - clear_pending_hdlc_ints(fc); - inithdlc(fc); - enable_hwirq(fc); - /* RESET Receiver and Transmitter */ - if (AVM_FRITZ_PCIV2 == fc->type) { - WriteISAC_V2(fc, ISACX_MASK, 0); - WriteISAC_V2(fc, ISACX_CMDRD, 0x41); - } else { - WriteISAC_V1(fc, ISAC_MASK, 0); - WriteISAC_V1(fc, ISAC_CMDR, 0x41); - } - spin_unlock_irqrestore(&fc->lock, flags); - /* Timeout 10ms */ - msleep_interruptible(10); - if (debug & DEBUG_HW) - pr_notice("%s: IRQ %d count %d\n", fc->name, - fc->irq, fc->irqcnt); - if (!fc->irqcnt) { - pr_info("%s: IRQ(%d) getting no IRQs during init %d\n", - fc->name, fc->irq, 3 - cnt); - reset_avm(fc); - } else - return 0; - } - free_irq(fc->irq, fc); - return -EIO; -} - -static int -channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) -{ - int ret = 0; - struct fritzcard *fc = bch->hw; - - switch (cq->op) { - case MISDN_CTRL_GETOP: - cq->op = 0; - break; - /* Nothing implemented yet */ - case MISDN_CTRL_FILL_EMPTY: - default: - pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op); - ret = -EINVAL; - break; - } - return ret; -} - -static int -avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) -{ - struct bchannel *bch = container_of(ch, struct bchannel, ch); - struct fritzcard *fc = bch->hw; - int ret = -EINVAL; - u_long flags; - - pr_debug("%s: %s cmd:%x %p\n", fc->name, __func__, cmd, arg); - switch (cmd) { - case CLOSE_CHANNEL: - test_and_clear_bit(FLG_OPEN, &bch->Flags); - if (test_bit(FLG_ACTIVE, &bch->Flags)) { - spin_lock_irqsave(&fc->lock, flags); - mISDN_freebchannel(bch); - test_and_clear_bit(FLG_TX_BUSY, &bch->Flags); - test_and_clear_bit(FLG_ACTIVE, &bch->Flags); - modehdlc(bch, ISDN_P_NONE); - spin_unlock_irqrestore(&fc->lock, flags); - } - ch->protocol = ISDN_P_NONE; - ch->peer = NULL; - module_put(THIS_MODULE); - ret = 0; - break; - case CONTROL_CHANNEL: - ret = channel_bctrl(bch, arg); - break; - default: - pr_info("%s: %s unknown prim(%x)\n", fc->name, __func__, cmd); - } - return ret; -} - -static int -channel_ctrl(struct fritzcard *fc, struct mISDN_ctrl_req *cq) -{ - int ret = 0; - - switch (cq->op) { - case MISDN_CTRL_GETOP: - cq->op = MISDN_CTRL_LOOP; - break; - case MISDN_CTRL_LOOP: - /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */ - if (cq->channel < 0 || cq->channel > 3) { - ret = -EINVAL; - break; - } - ret = fc->isac.ctrl(&fc->isac, HW_TESTLOOP, cq->channel); - break; - default: - pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op); - ret = -EINVAL; - break; - } - return ret; -} - -static int -open_bchannel(struct fritzcard *fc, struct channel_req *rq) -{ - struct bchannel *bch; - - if (rq->adr.channel > 2) - return -EINVAL; - if (rq->protocol == ISDN_P_NONE) - return -EINVAL; - bch = &fc->bch[rq->adr.channel - 1]; - if (test_and_set_bit(FLG_OPEN, &bch->Flags)) - return -EBUSY; /* b-channel can be only open once */ - test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); - bch->ch.protocol = rq->protocol; - rq->ch = &bch->ch; - return 0; -} - -/* - * device control function - */ -static int -avm_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg) -{ - struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); - struct dchannel *dch = container_of(dev, struct dchannel, dev); - struct fritzcard *fc = dch->hw; - struct channel_req *rq; - int err = 0; - - pr_debug("%s: %s cmd:%x %p\n", fc->name, __func__, cmd, arg); - switch (cmd) { - case OPEN_CHANNEL: - rq = arg; - if (rq->protocol == ISDN_P_TE_S0) - err = fc->isac.open(&fc->isac, rq); - else - err = open_bchannel(fc, rq); - if (err) - break; - if (!try_module_get(THIS_MODULE)) - pr_info("%s: cannot get module\n", fc->name); - break; - case CLOSE_CHANNEL: - pr_debug("%s: dev(%d) close from %p\n", fc->name, dch->dev.id, - __builtin_return_address(0)); - module_put(THIS_MODULE); - break; - case CONTROL_CHANNEL: - err = channel_ctrl(fc, arg); - break; - default: - pr_debug("%s: %s unknown command %x\n", - fc->name, __func__, cmd); - return -EINVAL; - } - return err; -} - -int -setup_fritz(struct fritzcard *fc) -{ - u32 val, ver; - - if (!request_region(fc->addr, 32, fc->name)) { - pr_info("%s: AVM config port %x-%x already in use\n", - fc->name, fc->addr, fc->addr + 31); - return -EIO; - } - switch (fc->type) { - case AVM_FRITZ_PCI: - val = inl(fc->addr); - outl(AVM_HDLC_1, fc->addr + CHIP_INDEX); - ver = inl(fc->addr + CHIP_WINDOW + HDLC_STATUS) >> 24; - if (debug & DEBUG_HW) { - pr_notice("%s: PCI stat %#x\n", fc->name, val); - pr_notice("%s: PCI Class %X Rev %d\n", fc->name, - val & 0xff, (val >> 8) & 0xff); - pr_notice("%s: HDLC version %x\n", fc->name, ver & 0xf); - } - ASSIGN_FUNC(V1, ISAC, fc->isac); - fc->isac.type = IPAC_TYPE_ISAC; - break; - case AVM_FRITZ_PCIV2: - val = inl(fc->addr); - ver = inl(fc->addr + AVM_HDLC_STATUS_1) >> 24; - if (debug & DEBUG_HW) { - pr_notice("%s: PCI V2 stat %#x\n", fc->name, val); - pr_notice("%s: PCI V2 Class %X Rev %d\n", fc->name, - val & 0xff, (val>>8) & 0xff); - pr_notice("%s: HDLC version %x\n", fc->name, ver & 0xf); - } - ASSIGN_FUNC(V2, ISAC, fc->isac); - fc->isac.type = IPAC_TYPE_ISACX; - break; - default: - release_region(fc->addr, 32); - pr_info("%s: AVM unknown type %d\n", fc->name, fc->type); - return -ENODEV; - } - pr_notice("%s: %s config irq:%d base:0x%X\n", fc->name, - (fc->type == AVM_FRITZ_PCI) ? "AVM Fritz!CARD PCI" : - "AVM Fritz!CARD PCIv2", fc->irq, fc->addr); - return 0; -} - -static void -release_card(struct fritzcard *card) -{ - u_long flags; - - disable_hwirq(card); - spin_lock_irqsave(&card->lock, flags); - modehdlc(&card->bch[0], ISDN_P_NONE); - modehdlc(&card->bch[1], ISDN_P_NONE); - spin_unlock_irqrestore(&card->lock, flags); - card->isac.release(&card->isac); - free_irq(card->irq, card); - mISDN_freebchannel(&card->bch[1]); - mISDN_freebchannel(&card->bch[0]); - mISDN_unregister_device(&card->isac.dch.dev); - release_region(card->addr, 32); - pci_disable_device(card->pdev); - pci_set_drvdata(card->pdev, NULL); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - kfree(card); - AVM_cnt--; -} - -static int __devinit -setup_instance(struct fritzcard *card) -{ - int i, err; - u_long flags; - - snprintf(card->name, MISDN_MAX_IDLEN - 1, "AVM.%d", AVM_cnt + 1); - write_lock_irqsave(&card_lock, flags); - list_add_tail(&card->list, &Cards); - write_unlock_irqrestore(&card_lock, flags); - - _set_debug(card); - card->isac.name = card->name; - spin_lock_init(&card->lock); - card->isac.hwlock = &card->lock; - mISDNisac_init(&card->isac, card); - - card->isac.dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | - (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); - card->isac.dch.dev.D.ctrl = avm_dctrl; - for (i = 0; i < 2; i++) { - card->bch[i].nr = i + 1; - set_channelmap(i + 1, card->isac.dch.dev.channelmap); - mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM); - card->bch[i].hw = card; - card->bch[i].ch.send = avm_l2l1B; - card->bch[i].ch.ctrl = avm_bctrl; - card->bch[i].ch.nr = i + 1; - list_add(&card->bch[i].ch.list, &card->isac.dch.dev.bchannels); - } - err = setup_fritz(card); - if (err) - goto error; - err = mISDN_register_device(&card->isac.dch.dev, &card->pdev->dev, - card->name); - if (err) - goto error_reg; - err = init_card(card); - if (!err) { - AVM_cnt++; - pr_notice("AVM %d cards installed DEBUG\n", AVM_cnt); - return 0; - } - mISDN_unregister_device(&card->isac.dch.dev); -error_reg: - release_region(card->addr, 32); -error: - card->isac.release(&card->isac); - mISDN_freebchannel(&card->bch[1]); - mISDN_freebchannel(&card->bch[0]); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - kfree(card); - return err; -} - -static int __devinit -fritzpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int err = -ENOMEM; - struct fritzcard *card; - - card = kzalloc(sizeof(struct fritzcard), GFP_KERNEL); - if (!card) { - pr_info("No kmem for fritzcard\n"); - return err; - } - if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2) - card->type = AVM_FRITZ_PCIV2; - else - card->type = AVM_FRITZ_PCI; - card->pdev = pdev; - err = pci_enable_device(pdev); - if (err) { - kfree(card); - return err; - } - - pr_notice("mISDN: found adapter %s at %s\n", - (char *) ent->driver_data, pci_name(pdev)); - - card->addr = pci_resource_start(pdev, 1); - card->irq = pdev->irq; - pci_set_drvdata(pdev, card); - err = setup_instance(card); - if (err) - pci_set_drvdata(pdev, NULL); - return err; -} - -static void __devexit -fritz_remove_pci(struct pci_dev *pdev) -{ - struct fritzcard *card = pci_get_drvdata(pdev); - - if (card) - release_card(card); - else - if (debug) - pr_info("%s: drvdata allready removed\n", __func__); -} - -static struct pci_device_id fcpci_ids[] __devinitdata = { - { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, (unsigned long) "Fritz!Card PCI"}, - { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, (unsigned long) "Fritz!Card PCI v2" }, - { } -}; -MODULE_DEVICE_TABLE(pci, fcpci_ids); - -static struct pci_driver fcpci_driver = { - .name = "fcpci", - .probe = fritzpci_probe, - .remove = __devexit_p(fritz_remove_pci), - .id_table = fcpci_ids, -}; - -static int __init AVM_init(void) -{ - int err; - - pr_notice("AVM Fritz PCI driver Rev. %s\n", AVMFRITZ_REV); - err = pci_register_driver(&fcpci_driver); - return err; -} - -static void __exit AVM_cleanup(void) -{ - pci_unregister_driver(&fcpci_driver); -} - -module_init(AVM_init); -module_exit(AVM_cleanup); diff --git a/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c b/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c index faed794cf75a..e1dab30aed30 100644 --- a/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -3416,8 +3416,22 @@ deactivate_bchannel(struct bchannel *bch) u_long flags; spin_lock_irqsave(&hc->lock, flags); - mISDN_clear_bchannel(bch); + if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) { + dev_kfree_skb(bch->next_skb); + bch->next_skb = NULL; + } + if (bch->tx_skb) { + dev_kfree_skb(bch->tx_skb); + bch->tx_skb = NULL; + } + bch->tx_idx = 0; + if (bch->rx_skb) { + dev_kfree_skb(bch->rx_skb); + bch->rx_skb = NULL; + } hc->chan[bch->slot].coeff_count = 0; + test_and_clear_bit(FLG_ACTIVE, &bch->Flags); + test_and_clear_bit(FLG_TX_BUSY, &bch->Flags); hc->chan[bch->slot].rx_off = 0; hc->chan[bch->slot].conf = -1; mode_hfcmulti(hc, bch->slot, ISDN_P_NONE, -1, 0, -1, 0); @@ -5370,10 +5384,9 @@ hfcmulti_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ent->device == PCI_DEVICE_ID_CCD_HFC8S || ent->device == PCI_DEVICE_ID_CCD_HFCE1)) { printk(KERN_ERR - "Unknown HFC multiport controller (vendor:%04x device:%04x " - "subvendor:%04x subdevice:%04x)\n", pdev->vendor, - pdev->device, pdev->subsystem_vendor, - pdev->subsystem_device); + "Unknown HFC multiport controller (vendor:%x device:%x " + "subvendor:%x subdevice:%x)\n", ent->vendor, ent->device, + ent->subvendor, ent->subdevice); printk(KERN_ERR "Please contact the driver maintainer for support.\n"); return -ENODEV; diff --git a/trunk/drivers/isdn/hardware/mISDN/hfcpci.c b/trunk/drivers/isdn/hardware/mISDN/hfcpci.c index 70e6b0e01121..228ffbed1286 100644 --- a/trunk/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/trunk/drivers/isdn/hardware/mISDN/hfcpci.c @@ -1522,8 +1522,22 @@ deactivate_bchannel(struct bchannel *bch) u_long flags; spin_lock_irqsave(&hc->lock, flags); - mISDN_clear_bchannel(bch); + if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) { + dev_kfree_skb(bch->next_skb); + bch->next_skb = NULL; + } + if (bch->tx_skb) { + dev_kfree_skb(bch->tx_skb); + bch->tx_skb = NULL; + } + bch->tx_idx = 0; + if (bch->rx_skb) { + dev_kfree_skb(bch->rx_skb); + bch->rx_skb = NULL; + } mode_hfcpci(bch, bch->nr, ISDN_P_NONE); + test_and_clear_bit(FLG_ACTIVE, &bch->Flags); + test_and_clear_bit(FLG_TX_BUSY, &bch->Flags); spin_unlock_irqrestore(&hc->lock, flags); } diff --git a/trunk/drivers/isdn/hardware/mISDN/hfcsusb.c b/trunk/drivers/isdn/hardware/mISDN/hfcsusb.c index fc46a26cb14f..6b7704c41b94 100644 --- a/trunk/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/trunk/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -1809,7 +1809,21 @@ deactivate_bchannel(struct bchannel *bch) hw->name, __func__, bch->nr); spin_lock_irqsave(&hw->lock, flags); - mISDN_clear_bchannel(bch); + if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) { + dev_kfree_skb(bch->next_skb); + bch->next_skb = NULL; + } + if (bch->tx_skb) { + dev_kfree_skb(bch->tx_skb); + bch->tx_skb = NULL; + } + bch->tx_idx = 0; + if (bch->rx_skb) { + dev_kfree_skb(bch->rx_skb); + bch->rx_skb = NULL; + } + clear_bit(FLG_ACTIVE, &bch->Flags); + clear_bit(FLG_TX_BUSY, &bch->Flags); spin_unlock_irqrestore(&hw->lock, flags); hfcsusb_setup_bch(bch, ISDN_P_NONE); hfcsusb_stop_endpoint(hw, bch->nr); diff --git a/trunk/drivers/isdn/hardware/mISDN/iohelper.h b/trunk/drivers/isdn/hardware/mISDN/iohelper.h deleted file mode 100644 index c16a217301e8..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/iohelper.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * iohelper.h - * helper for define functions to access ISDN hardware - * supported are memory mapped IO - * indirect port IO (one port for address, one for data) - * - * Author Karsten Keil - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _IOHELPER_H -#define _IOHELPER_H - -typedef u8 (read_reg_t)(void *, u8); -typedef void (write_reg_t)(void *, u8, u8); -typedef void (fifo_func_t)(void *, u8, u8 *, int); - -struct _ioport { - u32 port; - u32 ale; -}; - -#define IOFUNC_IO(name, hws, ap) \ - static u8 Read##name##_IO(void *p, u8 off) {\ - struct hws *hw = p;\ - return inb(hw->ap.port + off);\ - } \ - static void Write##name##_IO(void *p, u8 off, u8 val) {\ - struct hws *hw = p;\ - outb(val, hw->ap.port + off);\ - } \ - static void ReadFiFo##name##_IO(void *p, u8 off, u8 *dp, int size) {\ - struct hws *hw = p;\ - insb(hw->ap.port + off, dp, size);\ - } \ - static void WriteFiFo##name##_IO(void *p, u8 off, u8 *dp, int size) {\ - struct hws *hw = p;\ - outsb(hw->ap.port + off, dp, size);\ - } - -#define IOFUNC_IND(name, hws, ap) \ - static u8 Read##name##_IND(void *p, u8 off) {\ - struct hws *hw = p;\ - outb(off, hw->ap.ale);\ - return inb(hw->ap.port);\ - } \ - static void Write##name##_IND(void *p, u8 off, u8 val) {\ - struct hws *hw = p;\ - outb(off, hw->ap.ale);\ - outb(val, hw->ap.port);\ - } \ - static void ReadFiFo##name##_IND(void *p, u8 off, u8 *dp, int size) {\ - struct hws *hw = p;\ - outb(off, hw->ap.ale);\ - insb(hw->ap.port, dp, size);\ - } \ - static void WriteFiFo##name##_IND(void *p, u8 off, u8 *dp, int size) {\ - struct hws *hw = p;\ - outb(off, hw->ap.ale);\ - outsb(hw->ap.port, dp, size);\ - } - -#define IOFUNC_MEMIO(name, hws, typ, adr) \ - static u8 Read##name##_MIO(void *p, u8 off) {\ - struct hws *hw = p;\ - return readb(((typ *)hw->adr) + off);\ - } \ - static void Write##name##_MIO(void *p, u8 off, u8 val) {\ - struct hws *hw = p;\ - writeb(val, ((typ *)hw->adr) + off);\ - } \ - static void ReadFiFo##name##_MIO(void *p, u8 off, u8 *dp, int size) {\ - struct hws *hw = p;\ - while (size--)\ - *dp++ = readb(((typ *)hw->adr) + off);\ - } \ - static void WriteFiFo##name##_MIO(void *p, u8 off, u8 *dp, int size) {\ - struct inf_hw *hw = p;\ - while (size--)\ - writeb(*dp++, ((typ *)hw->adr) + off);\ - } - -#define ASSIGN_FUNC(typ, name, dest) do {\ - dest.read_reg = &Read##name##_##typ;\ - dest.write_reg = &Write##name##_##typ;\ - dest.read_fifo = &ReadFiFo##name##_##typ;\ - dest.write_fifo = &WriteFiFo##name##_##typ;\ - } while (0) -#define ASSIGN_FUNC_IPAC(typ, target) do {\ - ASSIGN_FUNC(typ, ISAC, target.isac);\ - ASSIGN_FUNC(typ, IPAC, target);\ - } while (0) - -#endif \ No newline at end of file diff --git a/trunk/drivers/isdn/hardware/mISDN/ipac.h b/trunk/drivers/isdn/hardware/mISDN/ipac.h deleted file mode 100644 index f9601d55dbca..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/ipac.h +++ /dev/null @@ -1,405 +0,0 @@ -/* - * - * ipac.h Defines for the Infineon (former Siemens) ISDN - * chip series - * - * Author Karsten Keil - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "iohelper.h" - -struct isac_hw { - struct dchannel dch; - u32 type; - u32 off; /* offset to isac regs */ - char *name; - spinlock_t *hwlock; /* lock HW acccess */ - read_reg_t *read_reg; - write_reg_t *write_reg; - fifo_func_t *read_fifo; - fifo_func_t *write_fifo; - int (*monitor)(void *, u32, u8 *, int); - void (*release)(struct isac_hw *); - int (*init)(struct isac_hw *); - int (*ctrl)(struct isac_hw *, u32, u_long); - int (*open)(struct isac_hw *, struct channel_req *); - u8 *mon_tx; - u8 *mon_rx; - int mon_txp; - int mon_txc; - int mon_rxp; - struct arcofi_msg *arcofi_list; - struct timer_list arcofitimer; - wait_queue_head_t arcofi_wait; - u8 arcofi_bc; - u8 arcofi_state; - u8 mocr; - u8 adf2; - u8 state; -}; - -struct ipac_hw; - -struct hscx_hw { - struct bchannel bch; - struct ipac_hw *ip; - u8 fifo_size; - u8 off; /* offset to ICA or ICB */ - u8 slot; - char log[64]; -}; - -struct ipac_hw { - struct isac_hw isac; - struct hscx_hw hscx[2]; - char *name; - void *hw; - spinlock_t *hwlock; /* lock HW acccess */ - struct module *owner; - u32 type; - read_reg_t *read_reg; - write_reg_t *write_reg; - fifo_func_t *read_fifo; - fifo_func_t *write_fifo; - void (*release)(struct ipac_hw *); - int (*init)(struct ipac_hw *); - int (*ctrl)(struct ipac_hw *, u32, u_long); - u8 conf; -}; - -#define IPAC_TYPE_ISAC 0x0010 -#define IPAC_TYPE_IPAC 0x0020 -#define IPAC_TYPE_ISACX 0x0040 -#define IPAC_TYPE_IPACX 0x0080 -#define IPAC_TYPE_HSCX 0x0100 - -#define ISAC_USE_ARCOFI 0x1000 - -/* Monitor functions */ -#define MONITOR_RX_0 0x1000 -#define MONITOR_RX_1 0x1001 -#define MONITOR_TX_0 0x2000 -#define MONITOR_TX_1 0x2001 - -/* All registers original Siemens Spec */ -/* IPAC/ISAC registers */ -#define ISAC_MASK 0x20 -#define ISAC_ISTA 0x20 -#define ISAC_STAR 0x21 -#define ISAC_CMDR 0x21 -#define ISAC_EXIR 0x24 -#define ISAC_ADF2 0x39 -#define ISAC_SPCR 0x30 -#define ISAC_ADF1 0x38 -#define ISAC_CIR0 0x31 -#define ISAC_CIX0 0x31 -#define ISAC_CIR1 0x33 -#define ISAC_CIX1 0x33 -#define ISAC_STCR 0x37 -#define ISAC_MODE 0x22 -#define ISAC_RSTA 0x27 -#define ISAC_RBCL 0x25 -#define ISAC_RBCH 0x2A -#define ISAC_TIMR 0x23 -#define ISAC_SQXR 0x3b -#define ISAC_SQRR 0x3b -#define ISAC_MOSR 0x3a -#define ISAC_MOCR 0x3a -#define ISAC_MOR0 0x32 -#define ISAC_MOX0 0x32 -#define ISAC_MOR1 0x34 -#define ISAC_MOX1 0x34 - -#define ISAC_RBCH_XAC 0x80 - -#define IPAC_D_TIN2 0x01 - -/* IPAC/HSCX */ -#define IPAC_ISTAB 0x20 /* RD */ -#define IPAC_MASKB 0x20 /* WR */ -#define IPAC_STARB 0x21 /* RD */ -#define IPAC_CMDRB 0x21 /* WR */ -#define IPAC_MODEB 0x22 /* R/W */ -#define IPAC_EXIRB 0x24 /* RD */ -#define IPAC_RBCLB 0x25 /* RD */ -#define IPAC_RAH1 0x26 /* WR */ -#define IPAC_RAH2 0x27 /* WR */ -#define IPAC_RSTAB 0x27 /* RD */ -#define IPAC_RAL1 0x28 /* R/W */ -#define IPAC_RAL2 0x29 /* WR */ -#define IPAC_RHCRB 0x29 /* RD */ -#define IPAC_XBCL 0x2A /* WR */ -#define IPAC_CCR2 0x2C /* R/W */ -#define IPAC_RBCHB 0x2D /* RD */ -#define IPAC_XBCH 0x2D /* WR */ -#define HSCX_VSTR 0x2E /* RD */ -#define IPAC_RLCR 0x2E /* WR */ -#define IPAC_CCR1 0x2F /* R/W */ -#define IPAC_TSAX 0x30 /* WR */ -#define IPAC_TSAR 0x31 /* WR */ -#define IPAC_XCCR 0x32 /* WR */ -#define IPAC_RCCR 0x33 /* WR */ - -/* IPAC_ISTAB/IPAC_MASKB bits */ -#define IPAC_B_XPR 0x10 -#define IPAC_B_RPF 0x40 -#define IPAC_B_RME 0x80 -#define IPAC_B_ON 0x2F - -/* IPAC_EXIRB bits */ -#define IPAC_B_RFS 0x04 -#define IPAC_B_RFO 0x10 -#define IPAC_B_XDU 0x40 -#define IPAC_B_XMR 0x80 - -/* IPAC special registers */ -#define IPAC_CONF 0xC0 /* R/W */ -#define IPAC_ISTA 0xC1 /* RD */ -#define IPAC_MASK 0xC1 /* WR */ -#define IPAC_ID 0xC2 /* RD */ -#define IPAC_ACFG 0xC3 /* R/W */ -#define IPAC_AOE 0xC4 /* R/W */ -#define IPAC_ARX 0xC5 /* RD */ -#define IPAC_ATX 0xC5 /* WR */ -#define IPAC_PITA1 0xC6 /* R/W */ -#define IPAC_PITA2 0xC7 /* R/W */ -#define IPAC_POTA1 0xC8 /* R/W */ -#define IPAC_POTA2 0xC9 /* R/W */ -#define IPAC_PCFG 0xCA /* R/W */ -#define IPAC_SCFG 0xCB /* R/W */ -#define IPAC_TIMR2 0xCC /* R/W */ - -/* IPAC_ISTA/_MASK bits */ -#define IPAC__EXB 0x01 -#define IPAC__ICB 0x02 -#define IPAC__EXA 0x04 -#define IPAC__ICA 0x08 -#define IPAC__EXD 0x10 -#define IPAC__ICD 0x20 -#define IPAC__INT0 0x40 -#define IPAC__INT1 0x80 -#define IPAC__ON 0xC0 - -/* HSCX ISTA/MASK bits */ -#define HSCX__EXB 0x01 -#define HSCX__EXA 0x02 -#define HSCX__ICA 0x04 - -/* ISAC/ISACX/IPAC/IPACX L1 commands */ -#define ISAC_CMD_TIM 0x0 -#define ISAC_CMD_RS 0x1 -#define ISAC_CMD_SCZ 0x4 -#define ISAC_CMD_SSZ 0x2 -#define ISAC_CMD_AR8 0x8 -#define ISAC_CMD_AR10 0x9 -#define ISAC_CMD_ARL 0xA -#define ISAC_CMD_DUI 0xF - -/* ISAC/ISACX/IPAC/IPACX L1 indications */ -#define ISAC_IND_RS 0x1 -#define ISAC_IND_PU 0x7 -#define ISAC_IND_DR 0x0 -#define ISAC_IND_SD 0x2 -#define ISAC_IND_DIS 0x3 -#define ISAC_IND_EI 0x6 -#define ISAC_IND_RSY 0x4 -#define ISAC_IND_ARD 0x8 -#define ISAC_IND_TI 0xA -#define ISAC_IND_ATI 0xB -#define ISAC_IND_AI8 0xC -#define ISAC_IND_AI10 0xD -#define ISAC_IND_DID 0xF - -/* the new ISACX / IPACX */ -/* D-channel registers */ -#define ISACX_RFIFOD 0x00 /* RD */ -#define ISACX_XFIFOD 0x00 /* WR */ -#define ISACX_ISTAD 0x20 /* RD */ -#define ISACX_MASKD 0x20 /* WR */ -#define ISACX_STARD 0x21 /* RD */ -#define ISACX_CMDRD 0x21 /* WR */ -#define ISACX_MODED 0x22 /* R/W */ -#define ISACX_EXMD1 0x23 /* R/W */ -#define ISACX_TIMR1 0x24 /* R/W */ -#define ISACX_SAP1 0x25 /* WR */ -#define ISACX_SAP2 0x26 /* WR */ -#define ISACX_RBCLD 0x26 /* RD */ -#define ISACX_RBCHD 0x27 /* RD */ -#define ISACX_TEI1 0x27 /* WR */ -#define ISACX_TEI2 0x28 /* WR */ -#define ISACX_RSTAD 0x28 /* RD */ -#define ISACX_TMD 0x29 /* R/W */ -#define ISACX_CIR0 0x2E /* RD */ -#define ISACX_CIX0 0x2E /* WR */ -#define ISACX_CIR1 0x2F /* RD */ -#define ISACX_CIX1 0x2F /* WR */ - -/* Transceiver registers */ -#define ISACX_TR_CONF0 0x30 /* R/W */ -#define ISACX_TR_CONF1 0x31 /* R/W */ -#define ISACX_TR_CONF2 0x32 /* R/W */ -#define ISACX_TR_STA 0x33 /* RD */ -#define ISACX_TR_CMD 0x34 /* R/W */ -#define ISACX_SQRR1 0x35 /* RD */ -#define ISACX_SQXR1 0x35 /* WR */ -#define ISACX_SQRR2 0x36 /* RD */ -#define ISACX_SQXR2 0x36 /* WR */ -#define ISACX_SQRR3 0x37 /* RD */ -#define ISACX_SQXR3 0x37 /* WR */ -#define ISACX_ISTATR 0x38 /* RD */ -#define ISACX_MASKTR 0x39 /* R/W */ -#define ISACX_TR_MODE 0x3A /* R/W */ -#define ISACX_ACFG1 0x3C /* R/W */ -#define ISACX_ACFG2 0x3D /* R/W */ -#define ISACX_AOE 0x3E /* R/W */ -#define ISACX_ARX 0x3F /* RD */ -#define ISACX_ATX 0x3F /* WR */ - -/* IOM: Timeslot, DPS, CDA */ -#define ISACX_CDA10 0x40 /* R/W */ -#define ISACX_CDA11 0x41 /* R/W */ -#define ISACX_CDA20 0x42 /* R/W */ -#define ISACX_CDA21 0x43 /* R/W */ -#define ISACX_CDA_TSDP10 0x44 /* R/W */ -#define ISACX_CDA_TSDP11 0x45 /* R/W */ -#define ISACX_CDA_TSDP20 0x46 /* R/W */ -#define ISACX_CDA_TSDP21 0x47 /* R/W */ -#define ISACX_BCHA_TSDP_BC1 0x48 /* R/W */ -#define ISACX_BCHA_TSDP_BC2 0x49 /* R/W */ -#define ISACX_BCHB_TSDP_BC1 0x4A /* R/W */ -#define ISACX_BCHB_TSDP_BC2 0x4B /* R/W */ -#define ISACX_TR_TSDP_BC1 0x4C /* R/W */ -#define ISACX_TR_TSDP_BC2 0x4D /* R/W */ -#define ISACX_CDA1_CR 0x4E /* R/W */ -#define ISACX_CDA2_CR 0x4F /* R/W */ - -/* IOM: Contol, Sync transfer, Monitor */ -#define ISACX_TR_CR 0x50 /* R/W */ -#define ISACX_TRC_CR 0x50 /* R/W */ -#define ISACX_BCHA_CR 0x51 /* R/W */ -#define ISACX_BCHB_CR 0x52 /* R/W */ -#define ISACX_DCI_CR 0x53 /* R/W */ -#define ISACX_DCIC_CR 0x53 /* R/W */ -#define ISACX_MON_CR 0x54 /* R/W */ -#define ISACX_SDS1_CR 0x55 /* R/W */ -#define ISACX_SDS2_CR 0x56 /* R/W */ -#define ISACX_IOM_CR 0x57 /* R/W */ -#define ISACX_STI 0x58 /* RD */ -#define ISACX_ASTI 0x58 /* WR */ -#define ISACX_MSTI 0x59 /* R/W */ -#define ISACX_SDS_CONF 0x5A /* R/W */ -#define ISACX_MCDA 0x5B /* RD */ -#define ISACX_MOR 0x5C /* RD */ -#define ISACX_MOX 0x5C /* WR */ -#define ISACX_MOSR 0x5D /* RD */ -#define ISACX_MOCR 0x5E /* R/W */ -#define ISACX_MSTA 0x5F /* RD */ -#define ISACX_MCONF 0x5F /* WR */ - -/* Interrupt and general registers */ -#define ISACX_ISTA 0x60 /* RD */ -#define ISACX_MASK 0x60 /* WR */ -#define ISACX_AUXI 0x61 /* RD */ -#define ISACX_AUXM 0x61 /* WR */ -#define ISACX_MODE1 0x62 /* R/W */ -#define ISACX_MODE2 0x63 /* R/W */ -#define ISACX_ID 0x64 /* RD */ -#define ISACX_SRES 0x64 /* WR */ -#define ISACX_TIMR2 0x65 /* R/W */ - -/* Register Bits */ -/* ISACX/IPACX _ISTAD (R) and _MASKD (W) */ -#define ISACX_D_XDU 0x04 -#define ISACX_D_XMR 0x08 -#define ISACX_D_XPR 0x10 -#define ISACX_D_RFO 0x20 -#define ISACX_D_RPF 0x40 -#define ISACX_D_RME 0x80 - -/* ISACX/IPACX _ISTA (R) and _MASK (W) */ -#define ISACX__ICD 0x01 -#define ISACX__MOS 0x02 -#define ISACX__TRAN 0x04 -#define ISACX__AUX 0x08 -#define ISACX__CIC 0x10 -#define ISACX__ST 0x20 -#define IPACX__ICB 0x40 -#define IPACX__ICA 0x80 -#define IPACX__ON 0x2C - -/* ISACX/IPACX _CMDRD (W) */ -#define ISACX_CMDRD_XRES 0x01 -#define ISACX_CMDRD_XME 0x02 -#define ISACX_CMDRD_XTF 0x08 -#define ISACX_CMDRD_STI 0x10 -#define ISACX_CMDRD_RRES 0x40 -#define ISACX_CMDRD_RMC 0x80 - -/* ISACX/IPACX _RSTAD (R) */ -#define ISACX_RSTAD_TA 0x01 -#define ISACX_RSTAD_CR 0x02 -#define ISACX_RSTAD_SA0 0x04 -#define ISACX_RSTAD_SA1 0x08 -#define ISACX_RSTAD_RAB 0x10 -#define ISACX_RSTAD_CRC 0x20 -#define ISACX_RSTAD_RDO 0x40 -#define ISACX_RSTAD_VFR 0x80 - -/* ISACX/IPACX _CIR0 (R) */ -#define ISACX_CIR0_BAS 0x01 -#define ISACX_CIR0_SG 0x08 -#define ISACX_CIR0_CIC1 0x08 -#define ISACX_CIR0_CIC0 0x08 - -/* B-channel registers */ -#define IPACX_OFF_ICA 0x70 -#define IPACX_OFF_ICB 0x80 - -/* ICA: IPACX_OFF_ICA + Reg ICB: IPACX_OFF_ICB + Reg */ - -#define IPACX_ISTAB 0x00 /* RD */ -#define IPACX_MASKB 0x00 /* WR */ -#define IPACX_STARB 0x01 /* RD */ -#define IPACX_CMDRB 0x01 /* WR */ -#define IPACX_MODEB 0x02 /* R/W */ -#define IPACX_EXMB 0x03 /* R/W */ -#define IPACX_RAH1 0x05 /* WR */ -#define IPACX_RAH2 0x06 /* WR */ -#define IPACX_RBCLB 0x06 /* RD */ -#define IPACX_RBCHB 0x07 /* RD */ -#define IPACX_RAL1 0x07 /* WR */ -#define IPACX_RAL2 0x08 /* WR */ -#define IPACX_RSTAB 0x08 /* RD */ -#define IPACX_TMB 0x09 /* R/W */ -#define IPACX_RFIFOB 0x0A /* RD */ -#define IPACX_XFIFOB 0x0A /* WR */ - -/* IPACX_ISTAB / IPACX_MASKB bits */ -#define IPACX_B_XDU 0x04 -#define IPACX_B_XPR 0x10 -#define IPACX_B_RFO 0x20 -#define IPACX_B_RPF 0x40 -#define IPACX_B_RME 0x80 - -#define IPACX_B_ON 0x0B - -extern int mISDNisac_init(struct isac_hw *, void *); -extern irqreturn_t mISDNisac_irq(struct isac_hw *, u8); -extern u32 mISDNipac_init(struct ipac_hw *, void *); -extern irqreturn_t mISDNipac_irq(struct ipac_hw *, int); diff --git a/trunk/drivers/isdn/hardware/mISDN/isar.h b/trunk/drivers/isdn/hardware/mISDN/isar.h deleted file mode 100644 index 092351acd2ab..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/isar.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * - * isar.h ISAR (Siemens PSB 7110) specific defines - * - * Author Karsten Keil (keil@isdn4linux.de) - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "iohelper.h" - -struct isar_hw; - -struct isar_ch { - struct bchannel bch; - struct isar_hw *is; - struct timer_list ftimer; - u8 nr; - u8 dpath; - u8 mml; - u8 state; - u8 cmd; - u8 mod; - u8 newcmd; - u8 newmod; - u8 try_mod; - u8 conmsg[16]; -}; - -struct isar_hw { - struct isar_ch ch[2]; - void *hw; - spinlock_t *hwlock; /* lock HW acccess */ - char *name; - struct module *owner; - read_reg_t *read_reg; - write_reg_t *write_reg; - fifo_func_t *read_fifo; - fifo_func_t *write_fifo; - int (*ctrl)(void *, u32, u_long); - void (*release)(struct isar_hw *); - int (*init)(struct isar_hw *); - int (*open)(struct isar_hw *, struct channel_req *); - int (*firmware)(struct isar_hw *, const u8 *, int); - unsigned long Flags; - int version; - u8 bstat; - u8 iis; - u8 cmsb; - u8 clsb; - u8 buf[256]; - u8 log[256]; -}; - -#define ISAR_IRQMSK 0x04 -#define ISAR_IRQSTA 0x04 -#define ISAR_IRQBIT 0x75 -#define ISAR_CTRL_H 0x61 -#define ISAR_CTRL_L 0x60 -#define ISAR_IIS 0x58 -#define ISAR_IIA 0x58 -#define ISAR_HIS 0x50 -#define ISAR_HIA 0x50 -#define ISAR_MBOX 0x4c -#define ISAR_WADR 0x4a -#define ISAR_RADR 0x48 - -#define ISAR_HIS_VNR 0x14 -#define ISAR_HIS_DKEY 0x02 -#define ISAR_HIS_FIRM 0x1e -#define ISAR_HIS_STDSP 0x08 -#define ISAR_HIS_DIAG 0x05 -#define ISAR_HIS_P0CFG 0x3c -#define ISAR_HIS_P12CFG 0x24 -#define ISAR_HIS_SARTCFG 0x25 -#define ISAR_HIS_PUMPCFG 0x26 -#define ISAR_HIS_PUMPCTRL 0x2a -#define ISAR_HIS_IOM2CFG 0x27 -#define ISAR_HIS_IOM2REQ 0x07 -#define ISAR_HIS_IOM2CTRL 0x2b -#define ISAR_HIS_BSTREQ 0x0c -#define ISAR_HIS_PSTREQ 0x0e -#define ISAR_HIS_SDATA 0x20 -#define ISAR_HIS_DPS1 0x40 -#define ISAR_HIS_DPS2 0x80 -#define SET_DPS(x) ((x<<6) & 0xc0) - -#define ISAR_IIS_MSCMSD 0x3f -#define ISAR_IIS_VNR 0x15 -#define ISAR_IIS_DKEY 0x03 -#define ISAR_IIS_FIRM 0x1f -#define ISAR_IIS_STDSP 0x09 -#define ISAR_IIS_DIAG 0x25 -#define ISAR_IIS_GSTEV 0x00 -#define ISAR_IIS_BSTEV 0x28 -#define ISAR_IIS_BSTRSP 0x2c -#define ISAR_IIS_PSTRSP 0x2e -#define ISAR_IIS_PSTEV 0x2a -#define ISAR_IIS_IOM2RSP 0x27 -#define ISAR_IIS_RDATA 0x20 -#define ISAR_IIS_INVMSG 0x3f - -#define ISAR_CTRL_SWVER 0x10 -#define ISAR_CTRL_STST 0x40 - -#define ISAR_MSG_HWVER 0x20 - -#define ISAR_DP1_USE 1 -#define ISAR_DP2_USE 2 -#define ISAR_RATE_REQ 3 - -#define PMOD_DISABLE 0 -#define PMOD_FAX 1 -#define PMOD_DATAMODEM 2 -#define PMOD_HALFDUPLEX 3 -#define PMOD_V110 4 -#define PMOD_DTMF 5 -#define PMOD_DTMF_TRANS 6 -#define PMOD_BYPASS 7 - -#define PCTRL_ORIG 0x80 -#define PV32P2_V23R 0x40 -#define PV32P2_V22A 0x20 -#define PV32P2_V22B 0x10 -#define PV32P2_V22C 0x08 -#define PV32P2_V21 0x02 -#define PV32P2_BEL 0x01 - -/* LSB MSB in ISAR doc wrong !!! Arghhh */ -#define PV32P3_AMOD 0x80 -#define PV32P3_V32B 0x02 -#define PV32P3_V23B 0x01 -#define PV32P4_48 0x11 -#define PV32P5_48 0x05 -#define PV32P4_UT48 0x11 -#define PV32P5_UT48 0x0d -#define PV32P4_96 0x11 -#define PV32P5_96 0x03 -#define PV32P4_UT96 0x11 -#define PV32P5_UT96 0x0f -#define PV32P4_B96 0x91 -#define PV32P5_B96 0x0b -#define PV32P4_UTB96 0xd1 -#define PV32P5_UTB96 0x0f -#define PV32P4_120 0xb1 -#define PV32P5_120 0x09 -#define PV32P4_UT120 0xf1 -#define PV32P5_UT120 0x0f -#define PV32P4_144 0x99 -#define PV32P5_144 0x09 -#define PV32P4_UT144 0xf9 -#define PV32P5_UT144 0x0f -#define PV32P6_CTN 0x01 -#define PV32P6_ATN 0x02 - -#define PFAXP2_CTN 0x01 -#define PFAXP2_ATN 0x04 - -#define PSEV_10MS_TIMER 0x02 -#define PSEV_CON_ON 0x18 -#define PSEV_CON_OFF 0x19 -#define PSEV_V24_OFF 0x20 -#define PSEV_CTS_ON 0x21 -#define PSEV_CTS_OFF 0x22 -#define PSEV_DCD_ON 0x23 -#define PSEV_DCD_OFF 0x24 -#define PSEV_DSR_ON 0x25 -#define PSEV_DSR_OFF 0x26 -#define PSEV_REM_RET 0xcc -#define PSEV_REM_REN 0xcd -#define PSEV_GSTN_CLR 0xd4 - -#define PSEV_RSP_READY 0xbc -#define PSEV_LINE_TX_H 0xb3 -#define PSEV_LINE_TX_B 0xb2 -#define PSEV_LINE_RX_H 0xb1 -#define PSEV_LINE_RX_B 0xb0 -#define PSEV_RSP_CONN 0xb5 -#define PSEV_RSP_DISC 0xb7 -#define PSEV_RSP_FCERR 0xb9 -#define PSEV_RSP_SILDET 0xbe -#define PSEV_RSP_SILOFF 0xab -#define PSEV_FLAGS_DET 0xba - -#define PCTRL_CMD_TDTMF 0x5a - -#define PCTRL_CMD_FTH 0xa7 -#define PCTRL_CMD_FRH 0xa5 -#define PCTRL_CMD_FTM 0xa8 -#define PCTRL_CMD_FRM 0xa6 -#define PCTRL_CMD_SILON 0xac -#define PCTRL_CMD_CONT 0xa2 -#define PCTRL_CMD_ESC 0xa4 -#define PCTRL_CMD_SILOFF 0xab -#define PCTRL_CMD_HALT 0xa9 - -#define PCTRL_LOC_RET 0xcf -#define PCTRL_LOC_REN 0xce - -#define SMODE_DISABLE 0 -#define SMODE_V14 2 -#define SMODE_HDLC 3 -#define SMODE_BINARY 4 -#define SMODE_FSK_V14 5 - -#define SCTRL_HDMC_BOTH 0x00 -#define SCTRL_HDMC_DTX 0x80 -#define SCTRL_HDMC_DRX 0x40 -#define S_P1_OVSP 0x40 -#define S_P1_SNP 0x20 -#define S_P1_EOP 0x10 -#define S_P1_EDP 0x08 -#define S_P1_NSB 0x04 -#define S_P1_CHS_8 0x03 -#define S_P1_CHS_7 0x02 -#define S_P1_CHS_6 0x01 -#define S_P1_CHS_5 0x00 - -#define S_P2_BFT_DEF 0x10 - -#define IOM_CTRL_ENA 0x80 -#define IOM_CTRL_NOPCM 0x00 -#define IOM_CTRL_ALAW 0x02 -#define IOM_CTRL_ULAW 0x04 -#define IOM_CTRL_RCV 0x01 - -#define IOM_P1_TXD 0x10 - -#define HDLC_FED 0x40 -#define HDLC_FSD 0x20 -#define HDLC_FST 0x20 -#define HDLC_ERROR 0x1c -#define HDLC_ERR_FAD 0x10 -#define HDLC_ERR_RER 0x08 -#define HDLC_ERR_CER 0x04 -#define SART_NMD 0x01 - -#define BSTAT_RDM0 0x1 -#define BSTAT_RDM1 0x2 -#define BSTAT_RDM2 0x4 -#define BSTAT_RDM3 0x8 -#define BSTEV_TBO 0x1f -#define BSTEV_RBO 0x2f - -/* FAX State Machine */ -#define STFAX_NULL 0 -#define STFAX_READY 1 -#define STFAX_LINE 2 -#define STFAX_CONT 3 -#define STFAX_ACTIV 4 -#define STFAX_ESCAPE 5 -#define STFAX_SILDET 6 - -extern u32 mISDNisar_init(struct isar_hw *, void *); -extern void mISDNisar_irq(struct isar_hw *); diff --git a/trunk/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/trunk/drivers/isdn/hardware/mISDN/mISDNinfineon.c deleted file mode 100644 index 62441ba53b95..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/mISDNinfineon.c +++ /dev/null @@ -1,1178 +0,0 @@ -/* - * mISDNinfineon.c - * Support for cards based on following Infineon ISDN chipsets - * - ISAC + HSCX - * - IPAC and IPAC-X - * - ISAC-SX + HSCX - * - * Supported cards: - * - Dialogic Diva 2.0 - * - Dialogic Diva 2.0U - * - Dialogic Diva 2.01 - * - Dialogic Diva 2.02 - * - Sedlbauer Speedwin - * - HST Saphir3 - * - Develo (former ELSA) Microlink PCI (Quickstep 1000) - * - Develo (former ELSA) Quickstep 3000 - * - Berkom Scitel BRIX Quadro - * - Dr.Neuhaus (Sagem) Niccy - * - * - * - * Author Karsten Keil - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include "ipac.h" - -#define INFINEON_REV "1.0" - -static int inf_cnt; -static u32 debug; -static u32 irqloops = 4; - -enum inf_types { - INF_NONE, - INF_DIVA20, - INF_DIVA20U, - INF_DIVA201, - INF_DIVA202, - INF_SPEEDWIN, - INF_SAPHIR3, - INF_QS1000, - INF_QS3000, - INF_NICCY, - INF_SCT_1, - INF_SCT_2, - INF_SCT_3, - INF_SCT_4, - INF_GAZEL_R685, - INF_GAZEL_R753 -}; - -enum addr_mode { - AM_NONE = 0, - AM_IO, - AM_MEMIO, - AM_IND_IO, -}; - -struct inf_cinfo { - enum inf_types typ; - const char *full; - const char *name; - enum addr_mode cfg_mode; - enum addr_mode addr_mode; - u8 cfg_bar; - u8 addr_bar; - void *irqfunc; -}; - -struct _ioaddr { - enum addr_mode mode; - union { - void __iomem *p; - struct _ioport io; - } a; -}; - -struct _iohandle { - enum addr_mode mode; - resource_size_t size; - resource_size_t start; - void __iomem *p; -}; - -struct inf_hw { - struct list_head list; - struct pci_dev *pdev; - const struct inf_cinfo *ci; - char name[MISDN_MAX_IDLEN]; - u32 irq; - u32 irqcnt; - struct _iohandle cfg; - struct _iohandle addr; - struct _ioaddr isac; - struct _ioaddr hscx; - spinlock_t lock; /* HW access lock */ - struct ipac_hw ipac; - struct inf_hw *sc[3]; /* slave cards */ -}; - - -#define PCI_SUBVENDOR_HST_SAPHIR3 0x52 -#define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53 -#define PCI_SUB_ID_SEDLBAUER 0x01 - -static struct pci_device_id infineon_ids[] __devinitdata = { - { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA20}, - { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA20U}, - { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA201}, - { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA202, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA202}, - { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, - PCI_SUBVENDOR_SEDLBAUER_PCI, PCI_SUB_ID_SEDLBAUER, 0, 0, - INF_SPEEDWIN}, - { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, - PCI_SUBVENDOR_HST_SAPHIR3, PCI_SUB_ID_SEDLBAUER, 0, 0, INF_SAPHIR3}, - { PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_QS1000}, - { PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_QS3000}, - { PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_NICCY}, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO, 0, 0, - INF_SCT_1}, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R685, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R685}, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R753, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R753}, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R753}, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_OLITEC, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R753}, - { } -}; -MODULE_DEVICE_TABLE(pci, infineon_ids); - -/* PCI interface specific defines */ -/* Diva 2.0/2.0U */ -#define DIVA_HSCX_PORT 0x00 -#define DIVA_HSCX_ALE 0x04 -#define DIVA_ISAC_PORT 0x08 -#define DIVA_ISAC_ALE 0x0C -#define DIVA_PCI_CTRL 0x10 - -/* DIVA_PCI_CTRL bits */ -#define DIVA_IRQ_BIT 0x01 -#define DIVA_RESET_BIT 0x08 -#define DIVA_EEPROM_CLK 0x40 -#define DIVA_LED_A 0x10 -#define DIVA_LED_B 0x20 -#define DIVA_IRQ_CLR 0x80 - -/* Diva 2.01/2.02 */ -/* Siemens PITA */ -#define PITA_ICR_REG 0x00 -#define PITA_INT0_STATUS 0x02 - -#define PITA_MISC_REG 0x1c -#define PITA_PARA_SOFTRESET 0x01000000 -#define PITA_SER_SOFTRESET 0x02000000 -#define PITA_PARA_MPX_MODE 0x04000000 -#define PITA_INT0_ENABLE 0x00020000 - -/* TIGER 100 Registers */ -#define TIGER_RESET_ADDR 0x00 -#define TIGER_EXTERN_RESET 0x01 -#define TIGER_AUX_CTRL 0x02 -#define TIGER_AUX_DATA 0x03 -#define TIGER_AUX_IRQMASK 0x05 -#define TIGER_AUX_STATUS 0x07 - -/* Tiger AUX BITs */ -#define TIGER_IOMASK 0xdd /* 1 and 5 are inputs */ -#define TIGER_IRQ_BIT 0x02 - -#define TIGER_IPAC_ALE 0xC0 -#define TIGER_IPAC_PORT 0xC8 - -/* ELSA (now Develo) PCI cards */ -#define ELSA_IRQ_ADDR 0x4c -#define ELSA_IRQ_MASK 0x04 -#define QS1000_IRQ_OFF 0x01 -#define QS3000_IRQ_OFF 0x03 -#define QS1000_IRQ_ON 0x41 -#define QS3000_IRQ_ON 0x43 - -/* Dr Neuhaus/Sagem Niccy */ -#define NICCY_ISAC_PORT 0x00 -#define NICCY_HSCX_PORT 0x01 -#define NICCY_ISAC_ALE 0x02 -#define NICCY_HSCX_ALE 0x03 - -#define NICCY_IRQ_CTRL_REG 0x38 -#define NICCY_IRQ_ENABLE 0x001f00 -#define NICCY_IRQ_DISABLE 0xff0000 -#define NICCY_IRQ_BIT 0x800000 - - -/* Scitel PLX */ -#define SCT_PLX_IRQ_ADDR 0x4c -#define SCT_PLX_RESET_ADDR 0x50 -#define SCT_PLX_IRQ_ENABLE 0x41 -#define SCT_PLX_RESET_BIT 0x04 - -/* Gazel */ -#define GAZEL_IPAC_DATA_PORT 0x04 -/* Gazel PLX */ -#define GAZEL_CNTRL 0x50 -#define GAZEL_RESET 0x04 -#define GAZEL_RESET_9050 0x40000000 -#define GAZEL_INCSR 0x4C -#define GAZEL_ISAC_EN 0x08 -#define GAZEL_INT_ISAC 0x20 -#define GAZEL_HSCX_EN 0x01 -#define GAZEL_INT_HSCX 0x04 -#define GAZEL_PCI_EN 0x40 -#define GAZEL_IPAC_EN 0x03 - - -static LIST_HEAD(Cards); -static DEFINE_RWLOCK(card_lock); /* protect Cards */ - -static void -_set_debug(struct inf_hw *card) -{ - card->ipac.isac.dch.debug = debug; - card->ipac.hscx[0].bch.debug = debug; - card->ipac.hscx[1].bch.debug = debug; -} - -static int -set_debug(const char *val, struct kernel_param *kp) -{ - int ret; - struct inf_hw *card; - - ret = param_set_uint(val, kp); - if (!ret) { - read_lock(&card_lock); - list_for_each_entry(card, &Cards, list) - _set_debug(card); - read_unlock(&card_lock); - } - return ret; -} - -MODULE_AUTHOR("Karsten Keil"); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(INFINEON_REV); -module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "infineon debug mask"); -module_param(irqloops, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)"); - -/* Interface functions */ - -IOFUNC_IO(ISAC, inf_hw, isac.a.io) -IOFUNC_IO(IPAC, inf_hw, hscx.a.io) -IOFUNC_IND(ISAC, inf_hw, isac.a.io) -IOFUNC_IND(IPAC, inf_hw, hscx.a.io) -IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p) -IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p) - -static irqreturn_t -diva_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u8 val; - - spin_lock(&hw->lock); - val = inb((u32)hw->cfg.start + DIVA_PCI_CTRL); - if (!(val & DIVA_IRQ_BIT)) { /* for us or shared ? */ - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -diva20x_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u8 val; - - spin_lock(&hw->lock); - val = readb(hw->cfg.p); - if (!(val & PITA_INT0_STATUS)) { /* for us or shared ? */ - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - writeb(PITA_INT0_STATUS, hw->cfg.p); /* ACK PITA INT0 */ - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -tiger_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u8 val; - - spin_lock(&hw->lock); - val = inb((u32)hw->cfg.start + TIGER_AUX_STATUS); - if (val & TIGER_IRQ_BIT) { /* for us or shared ? */ - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -elsa_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u8 val; - - spin_lock(&hw->lock); - val = inb((u32)hw->cfg.start + ELSA_IRQ_ADDR); - if (!(val & ELSA_IRQ_MASK)) { - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -niccy_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u32 val; - - spin_lock(&hw->lock); - val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - if (!(val & NICCY_IRQ_BIT)) { /* for us or shared ? */ - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -gazel_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - irqreturn_t ret; - - spin_lock(&hw->lock); - ret = mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return ret; -} - -static irqreturn_t -ipac_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u8 val; - - spin_lock(&hw->lock); - val = hw->ipac.read_reg(hw, IPAC_ISTA); - if (!(val & 0x3f)) { - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static void -enable_hwirq(struct inf_hw *hw) -{ - u16 w; - u32 val; - - switch (hw->ci->typ) { - case INF_DIVA201: - case INF_DIVA202: - writel(PITA_INT0_ENABLE, hw->cfg.p); - break; - case INF_SPEEDWIN: - case INF_SAPHIR3: - outb(TIGER_IRQ_BIT, (u32)hw->cfg.start + TIGER_AUX_IRQMASK); - break; - case INF_QS1000: - outb(QS1000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR); - break; - case INF_QS3000: - outb(QS3000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR); - break; - case INF_NICCY: - val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - val |= NICCY_IRQ_ENABLE;; - outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - break; - case INF_SCT_1: - w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR); - w |= SCT_PLX_IRQ_ENABLE; - outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR); - break; - case INF_GAZEL_R685: - outb(GAZEL_ISAC_EN + GAZEL_HSCX_EN + GAZEL_PCI_EN, - (u32)hw->cfg.start + GAZEL_INCSR); - break; - case INF_GAZEL_R753: - outb(GAZEL_IPAC_EN + GAZEL_PCI_EN, - (u32)hw->cfg.start + GAZEL_INCSR); - break; - default: - break; - } -} - -static void -disable_hwirq(struct inf_hw *hw) -{ - u16 w; - u32 val; - - switch (hw->ci->typ) { - case INF_DIVA201: - case INF_DIVA202: - writel(0, hw->cfg.p); - break; - case INF_SPEEDWIN: - case INF_SAPHIR3: - outb(0, (u32)hw->cfg.start + TIGER_AUX_IRQMASK); - break; - case INF_QS1000: - outb(QS1000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR); - break; - case INF_QS3000: - outb(QS3000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR); - break; - case INF_NICCY: - val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - val &= NICCY_IRQ_DISABLE; - outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - break; - case INF_SCT_1: - w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR); - w &= (~SCT_PLX_IRQ_ENABLE); - outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR); - break; - case INF_GAZEL_R685: - case INF_GAZEL_R753: - outb(0, (u32)hw->cfg.start + GAZEL_INCSR); - break; - default: - break; - } -} - -static void -ipac_chip_reset(struct inf_hw *hw) -{ - hw->ipac.write_reg(hw, IPAC_POTA2, 0x20); - mdelay(5); - hw->ipac.write_reg(hw, IPAC_POTA2, 0x00); - mdelay(5); - hw->ipac.write_reg(hw, IPAC_CONF, hw->ipac.conf); - hw->ipac.write_reg(hw, IPAC_MASK, 0xc0); -} - -static void -reset_inf(struct inf_hw *hw) -{ - u16 w; - u32 val; - - if (debug & DEBUG_HW) - pr_notice("%s: resetting card\n", hw->name); - switch (hw->ci->typ) { - case INF_DIVA20: - case INF_DIVA20U: - outb(0, (u32)hw->cfg.start + DIVA_PCI_CTRL); - mdelay(10); - outb(DIVA_RESET_BIT, (u32)hw->cfg.start + DIVA_PCI_CTRL); - mdelay(10); - /* Workaround PCI9060 */ - outb(9, (u32)hw->cfg.start + 0x69); - outb(DIVA_RESET_BIT | DIVA_LED_A, - (u32)hw->cfg.start + DIVA_PCI_CTRL); - break; - case INF_DIVA201: - writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, - hw->cfg.p + PITA_MISC_REG); - mdelay(1); - writel(PITA_PARA_MPX_MODE, hw->cfg.p + PITA_MISC_REG); - mdelay(10); - break; - case INF_DIVA202: - writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, - hw->cfg.p + PITA_MISC_REG); - mdelay(1); - writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET, - hw->cfg.p + PITA_MISC_REG); - mdelay(10); - break; - case INF_SPEEDWIN: - case INF_SAPHIR3: - ipac_chip_reset(hw); - hw->ipac.write_reg(hw, IPAC_ACFG, 0xff); - hw->ipac.write_reg(hw, IPAC_AOE, 0x00); - hw->ipac.write_reg(hw, IPAC_PCFG, 0x12); - break; - case INF_QS1000: - case INF_QS3000: - ipac_chip_reset(hw); - hw->ipac.write_reg(hw, IPAC_ACFG, 0x00); - hw->ipac.write_reg(hw, IPAC_AOE, 0x3c); - hw->ipac.write_reg(hw, IPAC_ATX, 0xff); - break; - case INF_NICCY: - break; - case INF_SCT_1: - w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR); - w &= (~SCT_PLX_RESET_BIT); - outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR); - mdelay(10); - w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR); - w |= SCT_PLX_RESET_BIT; - outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR); - mdelay(10); - break; - case INF_GAZEL_R685: - val = inl((u32)hw->cfg.start + GAZEL_CNTRL); - val |= (GAZEL_RESET_9050 + GAZEL_RESET); - outl(val, (u32)hw->cfg.start + GAZEL_CNTRL); - val &= ~(GAZEL_RESET_9050 + GAZEL_RESET); - mdelay(4); - outl(val, (u32)hw->cfg.start + GAZEL_CNTRL); - mdelay(10); - hw->ipac.isac.adf2 = 0x87; - hw->ipac.hscx[0].slot = 0x1f; - hw->ipac.hscx[0].slot = 0x23; - break; - case INF_GAZEL_R753: - val = inl((u32)hw->cfg.start + GAZEL_CNTRL); - val |= (GAZEL_RESET_9050 + GAZEL_RESET); - outl(val, (u32)hw->cfg.start + GAZEL_CNTRL); - val &= ~(GAZEL_RESET_9050 + GAZEL_RESET); - mdelay(4); - outl(val, (u32)hw->cfg.start + GAZEL_CNTRL); - mdelay(10); - ipac_chip_reset(hw); - hw->ipac.write_reg(hw, IPAC_ACFG, 0xff); - hw->ipac.write_reg(hw, IPAC_AOE, 0x00); - hw->ipac.conf = 0x01; /* IOM off */ - break; - default: - return; - } - enable_hwirq(hw); -} - -static int -inf_ctrl(struct inf_hw *hw, u32 cmd, u_long arg) -{ - int ret = 0; - - switch (cmd) { - case HW_RESET_REQ: - reset_inf(hw); - break; - default: - pr_info("%s: %s unknown command %x %lx\n", - hw->name, __func__, cmd, arg); - ret = -EINVAL; - break; - } - return ret; -} - -static int __devinit -init_irq(struct inf_hw *hw) -{ - int ret, cnt = 3; - u_long flags; - - if (!hw->ci->irqfunc) - return -EINVAL; - ret = request_irq(hw->irq, hw->ci->irqfunc, IRQF_SHARED, hw->name, hw); - if (ret) { - pr_info("%s: couldn't get interrupt %d\n", hw->name, hw->irq); - return ret; - } - while (cnt--) { - spin_lock_irqsave(&hw->lock, flags); - reset_inf(hw); - ret = hw->ipac.init(&hw->ipac); - if (ret) { - spin_unlock_irqrestore(&hw->lock, flags); - pr_info("%s: ISAC init failed with %d\n", - hw->name, ret); - break; - } - spin_unlock_irqrestore(&hw->lock, flags); - msleep_interruptible(10); - if (debug & DEBUG_HW) - pr_notice("%s: IRQ %d count %d\n", hw->name, - hw->irq, hw->irqcnt); - if (!hw->irqcnt) { - pr_info("%s: IRQ(%d) got no requests during init %d\n", - hw->name, hw->irq, 3 - cnt); - } else - return 0; - } - free_irq(hw->irq, hw); - return -EIO; -} - -static void -release_io(struct inf_hw *hw) -{ - if (hw->cfg.mode) { - if (hw->cfg.p) { - release_mem_region(hw->cfg.start, hw->cfg.size); - iounmap(hw->cfg.p); - } else - release_region(hw->cfg.start, hw->cfg.size); - hw->cfg.mode = AM_NONE; - } - if (hw->addr.mode) { - if (hw->addr.p) { - release_mem_region(hw->addr.start, hw->addr.size); - iounmap(hw->addr.p); - } else - release_region(hw->addr.start, hw->addr.size); - hw->addr.mode = AM_NONE; - } -} - -static int __devinit -setup_io(struct inf_hw *hw) -{ - int err = 0; - - if (hw->ci->cfg_mode) { - hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar); - hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar); - if (hw->ci->cfg_mode == AM_MEMIO) { - if (!request_mem_region(hw->cfg.start, hw->cfg.size, - hw->name)) - err = -EBUSY; - } else { - if (!request_region(hw->cfg.start, hw->cfg.size, - hw->name)) - err = -EBUSY; - } - if (err) { - pr_info("mISDN: %s config port %lx (%lu bytes)" - "already in use\n", hw->name, - (ulong)hw->cfg.start, (ulong)hw->cfg.size); - return err; - } - if (hw->ci->cfg_mode == AM_MEMIO) - hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size); - hw->cfg.mode = hw->ci->cfg_mode; - if (debug & DEBUG_HW) - pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n", - hw->name, (ulong)hw->cfg.start, - (ulong)hw->cfg.size, hw->ci->cfg_mode); - - } - if (hw->ci->addr_mode) { - hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar); - hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar); - if (hw->ci->addr_mode == AM_MEMIO) { - if (!request_mem_region(hw->addr.start, hw->addr.size, - hw->name)) - err = -EBUSY; - } else { - if (!request_region(hw->addr.start, hw->addr.size, - hw->name)) - err = -EBUSY; - } - if (err) { - pr_info("mISDN: %s address port %lx (%lu bytes)" - "already in use\n", hw->name, - (ulong)hw->addr.start, (ulong)hw->addr.size); - return err; - } - if (hw->ci->addr_mode == AM_MEMIO) - hw->addr.p = ioremap(hw->addr.start, hw->addr.size); - hw->addr.mode = hw->ci->addr_mode; - if (debug & DEBUG_HW) - pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n", - hw->name, (ulong)hw->addr.start, - (ulong)hw->addr.size, hw->ci->addr_mode); - - } - - switch (hw->ci->typ) { - case INF_DIVA20: - case INF_DIVA20U: - hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX; - hw->isac.mode = hw->cfg.mode; - hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE; - hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT; - hw->hscx.mode = hw->cfg.mode; - hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE; - hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT; - break; - case INF_DIVA201: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.mode = hw->addr.mode; - hw->isac.a.p = hw->addr.p; - hw->hscx.mode = hw->addr.mode; - hw->hscx.a.p = hw->addr.p; - break; - case INF_DIVA202: - hw->ipac.type = IPAC_TYPE_IPACX; - hw->isac.mode = hw->addr.mode; - hw->isac.a.p = hw->addr.p; - hw->hscx.mode = hw->addr.mode; - hw->hscx.a.p = hw->addr.p; - break; - case INF_SPEEDWIN: - case INF_SAPHIR3: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.mode = hw->cfg.mode; - hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE; - hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT; - hw->hscx.mode = hw->cfg.mode; - hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE; - hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT; - outb(0xff, (ulong)hw->cfg.start); - mdelay(1); - outb(0x00, (ulong)hw->cfg.start); - mdelay(1); - outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL); - break; - case INF_QS1000: - case INF_QS3000: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.a.io.ale = (u32)hw->addr.start; - hw->isac.a.io.port = (u32)hw->addr.start + 1; - hw->isac.mode = hw->addr.mode; - hw->hscx.a.io.ale = (u32)hw->addr.start; - hw->hscx.a.io.port = (u32)hw->addr.start + 1; - hw->hscx.mode = hw->addr.mode; - break; - case INF_NICCY: - hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX; - hw->isac.mode = hw->addr.mode; - hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE; - hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT; - hw->hscx.mode = hw->addr.mode; - hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE; - hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT; - break; - case INF_SCT_1: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.a.io.ale = (u32)hw->addr.start; - hw->isac.a.io.port = hw->isac.a.io.ale + 4; - hw->isac.mode = hw->addr.mode; - hw->hscx.a.io.ale = hw->isac.a.io.ale; - hw->hscx.a.io.port = hw->isac.a.io.port; - hw->hscx.mode = hw->addr.mode; - break; - case INF_SCT_2: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.a.io.ale = (u32)hw->addr.start + 0x08; - hw->isac.a.io.port = hw->isac.a.io.ale + 4; - hw->isac.mode = hw->addr.mode; - hw->hscx.a.io.ale = hw->isac.a.io.ale; - hw->hscx.a.io.port = hw->isac.a.io.port; - hw->hscx.mode = hw->addr.mode; - break; - case INF_SCT_3: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.a.io.ale = (u32)hw->addr.start + 0x10; - hw->isac.a.io.port = hw->isac.a.io.ale + 4; - hw->isac.mode = hw->addr.mode; - hw->hscx.a.io.ale = hw->isac.a.io.ale; - hw->hscx.a.io.port = hw->isac.a.io.port; - hw->hscx.mode = hw->addr.mode; - break; - case INF_SCT_4: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.a.io.ale = (u32)hw->addr.start + 0x20; - hw->isac.a.io.port = hw->isac.a.io.ale + 4; - hw->isac.mode = hw->addr.mode; - hw->hscx.a.io.ale = hw->isac.a.io.ale; - hw->hscx.a.io.port = hw->isac.a.io.port; - hw->hscx.mode = hw->addr.mode; - break; - case INF_GAZEL_R685: - hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX; - hw->ipac.isac.off = 0x80; - hw->isac.mode = hw->addr.mode; - hw->isac.a.io.port = (u32)hw->addr.start; - hw->hscx.mode = hw->addr.mode; - hw->hscx.a.io.port = hw->isac.a.io.port; - break; - case INF_GAZEL_R753: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.mode = hw->addr.mode; - hw->isac.a.io.ale = (u32)hw->addr.start; - hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT; - hw->hscx.mode = hw->addr.mode; - hw->hscx.a.io.ale = hw->isac.a.io.ale; - hw->hscx.a.io.port = hw->isac.a.io.port; - break; - default: - return -EINVAL; - } - switch (hw->isac.mode) { - case AM_MEMIO: - ASSIGN_FUNC_IPAC(MIO, hw->ipac); - break; - case AM_IND_IO: - ASSIGN_FUNC_IPAC(IND, hw->ipac); - break; - case AM_IO: - ASSIGN_FUNC_IPAC(IO, hw->ipac); - break; - default: - return -EINVAL; - } - return 0; -} - -static void -release_card(struct inf_hw *card) { - ulong flags; - int i; - - spin_lock_irqsave(&card->lock, flags); - disable_hwirq(card); - spin_unlock_irqrestore(&card->lock, flags); - card->ipac.isac.release(&card->ipac.isac); - free_irq(card->irq, card); - mISDN_unregister_device(&card->ipac.isac.dch.dev); - release_io(card); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - switch (card->ci->typ) { - case INF_SCT_2: - case INF_SCT_3: - case INF_SCT_4: - break; - case INF_SCT_1: - for (i = 0; i < 3; i++) { - if (card->sc[i]) - release_card(card->sc[i]); - card->sc[i] = NULL; - } - default: - pci_disable_device(card->pdev); - pci_set_drvdata(card->pdev, NULL); - break; - } - kfree(card); - inf_cnt--; -} - -static int __devinit -setup_instance(struct inf_hw *card) -{ - int err; - ulong flags; - - snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name, - inf_cnt + 1); - write_lock_irqsave(&card_lock, flags); - list_add_tail(&card->list, &Cards); - write_unlock_irqrestore(&card_lock, flags); - - _set_debug(card); - card->ipac.isac.name = card->name; - card->ipac.name = card->name; - card->ipac.owner = THIS_MODULE; - spin_lock_init(&card->lock); - card->ipac.isac.hwlock = &card->lock; - card->ipac.hwlock = &card->lock; - card->ipac.ctrl = (void *)&inf_ctrl; - - err = setup_io(card); - if (err) - goto error_setup; - - card->ipac.isac.dch.dev.Bprotocols = - mISDNipac_init(&card->ipac, card); - - if (card->ipac.isac.dch.dev.Bprotocols == 0) - goto error_setup;; - - err = mISDN_register_device(&card->ipac.isac.dch.dev, - &card->pdev->dev, card->name); - if (err) - goto error; - - err = init_irq(card); - if (!err) { - inf_cnt++; - pr_notice("Infineon %d cards installed\n", inf_cnt); - return 0; - } - mISDN_unregister_device(&card->ipac.isac.dch.dev); -error: - card->ipac.release(&card->ipac); -error_setup: - release_io(card); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - return err; -} - -static const struct inf_cinfo inf_card_info[] = { - { - INF_DIVA20, - "Dialogic Diva 2.0", - "diva20", - AM_IND_IO, AM_NONE, 2, 0, - &diva_irq - }, - { - INF_DIVA20U, - "Dialogic Diva 2.0U", - "diva20U", - AM_IND_IO, AM_NONE, 2, 0, - &diva_irq - }, - { - INF_DIVA201, - "Dialogic Diva 2.01", - "diva201", - AM_MEMIO, AM_MEMIO, 0, 1, - &diva20x_irq - }, - { - INF_DIVA202, - "Dialogic Diva 2.02", - "diva202", - AM_MEMIO, AM_MEMIO, 0, 1, - &diva20x_irq - }, - { - INF_SPEEDWIN, - "Sedlbauer SpeedWin PCI", - "speedwin", - AM_IND_IO, AM_NONE, 0, 0, - &tiger_irq - }, - { - INF_SAPHIR3, - "HST Saphir 3", - "saphir", - AM_IND_IO, AM_NONE, 0, 0, - &tiger_irq - }, - { - INF_QS1000, - "Develo Microlink PCI", - "qs1000", - AM_IO, AM_IND_IO, 1, 3, - &elsa_irq - }, - { - INF_QS3000, - "Develo QuickStep 3000", - "qs3000", - AM_IO, AM_IND_IO, 1, 3, - &elsa_irq - }, - { - INF_NICCY, - "Sagem NICCY", - "niccy", - AM_IO, AM_IND_IO, 0, 1, - &niccy_irq - }, - { - INF_SCT_1, - "SciTel Quadro", - "p1_scitel", - AM_IO, AM_IND_IO, 1, 5, - &ipac_irq - }, - { - INF_SCT_2, - "SciTel Quadro", - "p2_scitel", - AM_NONE, AM_IND_IO, 0, 4, - &ipac_irq - }, - { - INF_SCT_3, - "SciTel Quadro", - "p3_scitel", - AM_NONE, AM_IND_IO, 0, 3, - &ipac_irq - }, - { - INF_SCT_4, - "SciTel Quadro", - "p4_scitel", - AM_NONE, AM_IND_IO, 0, 2, - &ipac_irq - }, - { - INF_GAZEL_R685, - "Gazel R685", - "gazel685", - AM_IO, AM_IO, 1, 2, - &gazel_irq - }, - { - INF_GAZEL_R753, - "Gazel R753", - "gazel753", - AM_IO, AM_IND_IO, 1, 2, - &ipac_irq - }, - { - INF_NONE, - } -}; - -static const struct inf_cinfo * __devinit -get_card_info(enum inf_types typ) -{ - const struct inf_cinfo *ci = inf_card_info; - - while (ci->typ != INF_NONE) { - if (ci->typ == typ) - return ci; - ci++; - } - return NULL; -} - -static int __devinit -inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int err = -ENOMEM; - struct inf_hw *card; - - card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL); - if (!card) { - pr_info("No memory for Infineon ISDN card\n"); - return err; - } - card->pdev = pdev; - err = pci_enable_device(pdev); - if (err) { - kfree(card); - return err; - } - card->ci = get_card_info(ent->driver_data); - if (!card->ci) { - pr_info("mISDN: do not have informations about adapter at %s\n", - pci_name(pdev)); - kfree(card); - return -EINVAL; - } else - pr_notice("mISDN: found adapter %s at %s\n", - card->ci->full, pci_name(pdev)); - - card->irq = pdev->irq; - pci_set_drvdata(pdev, card); - err = setup_instance(card); - if (err) { - pci_disable_device(card->pdev); - kfree(card); - pci_set_drvdata(pdev, NULL); - } else if (ent->driver_data == INF_SCT_1) { - int i; - struct inf_hw *sc; - - for (i = 1; i < 4; i++) { - sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL); - if (!sc) { - release_card(card); - return -ENOMEM; - } - sc->irq = card->irq; - sc->pdev = card->pdev; - sc->ci = card->ci + i; - err = setup_instance(sc); - if (err) { - kfree(sc); - release_card(card); - } else - card->sc[i - 1] = sc; - } - } - return err; -} - -static void __devexit -inf_remove(struct pci_dev *pdev) -{ - struct inf_hw *card = pci_get_drvdata(pdev); - - if (card) - release_card(card); - else - pr_debug("%s: drvdata allready removed\n", __func__); -} - -static struct pci_driver infineon_driver = { - .name = "ISDN Infineon pci", - .probe = inf_probe, - .remove = __devexit_p(inf_remove), - .id_table = infineon_ids, -}; - -static int __init -infineon_init(void) -{ - int err; - - pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV); - err = pci_register_driver(&infineon_driver); - return err; -} - -static void __exit -infineon_cleanup(void) -{ - pci_unregister_driver(&infineon_driver); -} - -module_init(infineon_init); -module_exit(infineon_cleanup); diff --git a/trunk/drivers/isdn/hardware/mISDN/mISDNipac.c b/trunk/drivers/isdn/hardware/mISDN/mISDNipac.c deleted file mode 100644 index 613ba0435372..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/mISDNipac.c +++ /dev/null @@ -1,1655 +0,0 @@ -/* - * isac.c ISAC specific routines - * - * Author Karsten Keil - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include "ipac.h" - - -#define DBUSY_TIMER_VALUE 80 -#define ARCOFI_USE 1 - -#define ISAC_REV "2.0" - -MODULE_AUTHOR("Karsten Keil"); -MODULE_VERSION(ISAC_REV); -MODULE_LICENSE("GPL v2"); - -#define ReadISAC(is, o) (is->read_reg(is->dch.hw, o + is->off)) -#define WriteISAC(is, o, v) (is->write_reg(is->dch.hw, o + is->off, v)) -#define ReadHSCX(h, o) (h->ip->read_reg(h->ip->hw, h->off + o)) -#define WriteHSCX(h, o, v) (h->ip->write_reg(h->ip->hw, h->off + o, v)) -#define ReadIPAC(ip, o) (ip->read_reg(ip->hw, o)) -#define WriteIPAC(ip, o, v) (ip->write_reg(ip->hw, o, v)) - -static inline void -ph_command(struct isac_hw *isac, u8 command) -{ - pr_debug("%s: ph_command %x\n", isac->name, command); - if (isac->type & IPAC_TYPE_ISACX) - WriteISAC(isac, ISACX_CIX0, (command << 4) | 0xE); - else - WriteISAC(isac, ISAC_CIX0, (command << 2) | 3); -} - -static void -isac_ph_state_change(struct isac_hw *isac) -{ - switch (isac->state) { - case (ISAC_IND_RS): - case (ISAC_IND_EI): - ph_command(isac, ISAC_CMD_DUI); - } - schedule_event(&isac->dch, FLG_PHCHANGE); -} - -static void -isac_ph_state_bh(struct dchannel *dch) -{ - struct isac_hw *isac = container_of(dch, struct isac_hw, dch); - - switch (isac->state) { - case ISAC_IND_RS: - case ISAC_IND_EI: - dch->state = 0; - l1_event(dch->l1, HW_RESET_IND); - break; - case ISAC_IND_DID: - dch->state = 3; - l1_event(dch->l1, HW_DEACT_CNF); - break; - case ISAC_IND_DR: - dch->state = 3; - l1_event(dch->l1, HW_DEACT_IND); - break; - case ISAC_IND_PU: - dch->state = 4; - l1_event(dch->l1, HW_POWERUP_IND); - break; - case ISAC_IND_RSY: - if (dch->state <= 5) { - dch->state = 5; - l1_event(dch->l1, ANYSIGNAL); - } else { - dch->state = 8; - l1_event(dch->l1, LOSTFRAMING); - } - break; - case ISAC_IND_ARD: - dch->state = 6; - l1_event(dch->l1, INFO2); - break; - case ISAC_IND_AI8: - dch->state = 7; - l1_event(dch->l1, INFO4_P8); - break; - case ISAC_IND_AI10: - dch->state = 7; - l1_event(dch->l1, INFO4_P10); - break; - } - pr_debug("%s: TE newstate %x\n", isac->name, dch->state); -} - -void -isac_empty_fifo(struct isac_hw *isac, int count) -{ - u8 *ptr; - - pr_debug("%s: %s %d\n", isac->name, __func__, count); - - if (!isac->dch.rx_skb) { - isac->dch.rx_skb = mI_alloc_skb(isac->dch.maxlen, GFP_ATOMIC); - if (!isac->dch.rx_skb) { - pr_info("%s: D receive out of memory\n", isac->name); - WriteISAC(isac, ISAC_CMDR, 0x80); - return; - } - } - if ((isac->dch.rx_skb->len + count) >= isac->dch.maxlen) { - pr_debug("%s: %s overrun %d\n", isac->name, __func__, - isac->dch.rx_skb->len + count); - WriteISAC(isac, ISAC_CMDR, 0x80); - return; - } - ptr = skb_put(isac->dch.rx_skb, count); - isac->read_fifo(isac->dch.hw, isac->off, ptr, count); - WriteISAC(isac, ISAC_CMDR, 0x80); - if (isac->dch.debug & DEBUG_HW_DFIFO) { - char pfx[MISDN_MAX_IDLEN + 16]; - - snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-recv %s %d ", - isac->name, count); - print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count); - } -} - -static void -isac_fill_fifo(struct isac_hw *isac) -{ - int count, more; - u8 *ptr; - - if (!isac->dch.tx_skb) - return; - count = isac->dch.tx_skb->len - isac->dch.tx_idx; - if (count <= 0) - return; - - more = 0; - if (count > 32) { - more = !0; - count = 32; - } - pr_debug("%s: %s %d\n", isac->name, __func__, count); - ptr = isac->dch.tx_skb->data + isac->dch.tx_idx; - isac->dch.tx_idx += count; - isac->write_fifo(isac->dch.hw, isac->off, ptr, count); - WriteISAC(isac, ISAC_CMDR, more ? 0x8 : 0xa); - if (test_and_set_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) { - pr_debug("%s: %s dbusytimer running\n", isac->name, __func__); - del_timer(&isac->dch.timer); - } - init_timer(&isac->dch.timer); - isac->dch.timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); - add_timer(&isac->dch.timer); - if (isac->dch.debug & DEBUG_HW_DFIFO) { - char pfx[MISDN_MAX_IDLEN + 16]; - - snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-send %s %d ", - isac->name, count); - print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count); - } -} - -static void -isac_rme_irq(struct isac_hw *isac) -{ - u8 val, count; - - val = ReadISAC(isac, ISAC_RSTA); - if ((val & 0x70) != 0x20) { - if (val & 0x40) { - pr_debug("%s: ISAC RDO\n", isac->name); -#ifdef ERROR_STATISTIC - isac->dch.err_rx++; -#endif - } - if (!(val & 0x20)) { - pr_debug("%s: ISAC CRC error\n", isac->name); -#ifdef ERROR_STATISTIC - isac->dch.err_crc++; -#endif - } - WriteISAC(isac, ISAC_CMDR, 0x80); - if (isac->dch.rx_skb) - dev_kfree_skb(isac->dch.rx_skb); - isac->dch.rx_skb = NULL; - } else { - count = ReadISAC(isac, ISAC_RBCL) & 0x1f; - if (count == 0) - count = 32; - isac_empty_fifo(isac, count); - recv_Dchannel(&isac->dch); - } -} - -static void -isac_xpr_irq(struct isac_hw *isac) -{ - if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) - del_timer(&isac->dch.timer); - if (isac->dch.tx_skb && isac->dch.tx_idx < isac->dch.tx_skb->len) { - isac_fill_fifo(isac); - } else { - if (isac->dch.tx_skb) - dev_kfree_skb(isac->dch.tx_skb); - if (get_next_dframe(&isac->dch)) - isac_fill_fifo(isac); - } -} - -static void -isac_retransmit(struct isac_hw *isac) -{ - if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) - del_timer(&isac->dch.timer); - if (test_bit(FLG_TX_BUSY, &isac->dch.Flags)) { - /* Restart frame */ - isac->dch.tx_idx = 0; - isac_fill_fifo(isac); - } else if (isac->dch.tx_skb) { /* should not happen */ - pr_info("%s: tx_skb exist but not busy\n", isac->name); - test_and_set_bit(FLG_TX_BUSY, &isac->dch.Flags); - isac->dch.tx_idx = 0; - isac_fill_fifo(isac); - } else { - pr_info("%s: ISAC XDU no TX_BUSY\n", isac->name); - if (get_next_dframe(&isac->dch)) - isac_fill_fifo(isac); - } -} - -static void -isac_mos_irq(struct isac_hw *isac) -{ - u8 val; - int ret; - - val = ReadISAC(isac, ISAC_MOSR); - pr_debug("%s: ISAC MOSR %02x\n", isac->name, val); -#if ARCOFI_USE - if (val & 0x08) { - if (!isac->mon_rx) { - isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC); - if (!isac->mon_rx) { - pr_info("%s: ISAC MON RX out of memory!\n", - isac->name); - isac->mocr &= 0xf0; - isac->mocr |= 0x0a; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - goto afterMONR0; - } else - isac->mon_rxp = 0; - } - if (isac->mon_rxp >= MAX_MON_FRAME) { - isac->mocr &= 0xf0; - isac->mocr |= 0x0a; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - isac->mon_rxp = 0; - pr_debug("%s: ISAC MON RX overflow!\n", isac->name); - goto afterMONR0; - } - isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR0); - pr_debug("%s: ISAC MOR0 %02x\n", isac->name, - isac->mon_rx[isac->mon_rxp - 1]); - if (isac->mon_rxp == 1) { - isac->mocr |= 0x04; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - } - } -afterMONR0: - if (val & 0x80) { - if (!isac->mon_rx) { - isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC); - if (!isac->mon_rx) { - pr_info("%s: ISAC MON RX out of memory!\n", - isac->name); - isac->mocr &= 0x0f; - isac->mocr |= 0xa0; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - goto afterMONR1; - } else - isac->mon_rxp = 0; - } - if (isac->mon_rxp >= MAX_MON_FRAME) { - isac->mocr &= 0x0f; - isac->mocr |= 0xa0; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - isac->mon_rxp = 0; - pr_debug("%s: ISAC MON RX overflow!\n", isac->name); - goto afterMONR1; - } - isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR1); - pr_debug("%s: ISAC MOR1 %02x\n", isac->name, - isac->mon_rx[isac->mon_rxp - 1]); - isac->mocr |= 0x40; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - } -afterMONR1: - if (val & 0x04) { - isac->mocr &= 0xf0; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - isac->mocr |= 0x0a; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - if (isac->monitor) { - ret = isac->monitor(isac->dch.hw, MONITOR_RX_0, - isac->mon_rx, isac->mon_rxp); - if (ret) - kfree(isac->mon_rx); - } else { - pr_info("%s: MONITOR 0 received %d but no user\n", - isac->name, isac->mon_rxp); - kfree(isac->mon_rx); - } - isac->mon_rx = NULL; - isac->mon_rxp = 0; - } - if (val & 0x40) { - isac->mocr &= 0x0f; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - isac->mocr |= 0xa0; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - if (isac->monitor) { - ret = isac->monitor(isac->dch.hw, MONITOR_RX_1, - isac->mon_rx, isac->mon_rxp); - if (ret) - kfree(isac->mon_rx); - } else { - pr_info("%s: MONITOR 1 received %d but no user\n", - isac->name, isac->mon_rxp); - kfree(isac->mon_rx); - } - isac->mon_rx = NULL; - isac->mon_rxp = 0; - } - if (val & 0x02) { - if ((!isac->mon_tx) || (isac->mon_txc && - (isac->mon_txp >= isac->mon_txc) && !(val & 0x08))) { - isac->mocr &= 0xf0; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - isac->mocr |= 0x0a; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) { - if (isac->monitor) - ret = isac->monitor(isac->dch.hw, - MONITOR_TX_0, NULL, 0); - } - kfree(isac->mon_tx); - isac->mon_tx = NULL; - isac->mon_txc = 0; - isac->mon_txp = 0; - goto AfterMOX0; - } - if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) { - if (isac->monitor) - ret = isac->monitor(isac->dch.hw, - MONITOR_TX_0, NULL, 0); - kfree(isac->mon_tx); - isac->mon_tx = NULL; - isac->mon_txc = 0; - isac->mon_txp = 0; - goto AfterMOX0; - } - WriteISAC(isac, ISAC_MOX0, isac->mon_tx[isac->mon_txp++]); - pr_debug("%s: ISAC %02x -> MOX0\n", isac->name, - isac->mon_tx[isac->mon_txp - 1]); - } -AfterMOX0: - if (val & 0x20) { - if ((!isac->mon_tx) || (isac->mon_txc && - (isac->mon_txp >= isac->mon_txc) && !(val & 0x80))) { - isac->mocr &= 0x0f; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - isac->mocr |= 0xa0; - WriteISAC(isac, ISAC_MOCR, isac->mocr); - if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) { - if (isac->monitor) - ret = isac->monitor(isac->dch.hw, - MONITOR_TX_1, NULL, 0); - } - kfree(isac->mon_tx); - isac->mon_tx = NULL; - isac->mon_txc = 0; - isac->mon_txp = 0; - goto AfterMOX1; - } - if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) { - if (isac->monitor) - ret = isac->monitor(isac->dch.hw, - MONITOR_TX_1, NULL, 0); - kfree(isac->mon_tx); - isac->mon_tx = NULL; - isac->mon_txc = 0; - isac->mon_txp = 0; - goto AfterMOX1; - } - WriteISAC(isac, ISAC_MOX1, isac->mon_tx[isac->mon_txp++]); - pr_debug("%s: ISAC %02x -> MOX1\n", isac->name, - isac->mon_tx[isac->mon_txp - 1]); - } -AfterMOX1: - val = 0; /* dummy to avoid warning */ -#endif -} - -static void -isac_cisq_irq(struct isac_hw *isac) { - u8 val; - - val = ReadISAC(isac, ISAC_CIR0); - pr_debug("%s: ISAC CIR0 %02X\n", isac->name, val); - if (val & 2) { - pr_debug("%s: ph_state change %x->%x\n", isac->name, - isac->state, (val >> 2) & 0xf); - isac->state = (val >> 2) & 0xf; - isac_ph_state_change(isac); - } - if (val & 1) { - val = ReadISAC(isac, ISAC_CIR1); - pr_debug("%s: ISAC CIR1 %02X\n", isac->name, val); - } -} - -static void -isacsx_cic_irq(struct isac_hw *isac) -{ - u8 val; - - val = ReadISAC(isac, ISACX_CIR0); - pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val); - if (val & ISACX_CIR0_CIC0) { - pr_debug("%s: ph_state change %x->%x\n", isac->name, - isac->state, val >> 4); - isac->state = val >> 4; - isac_ph_state_change(isac); - } -} - -static void -isacsx_rme_irq(struct isac_hw *isac) -{ - int count; - u8 val; - - val = ReadISAC(isac, ISACX_RSTAD); - if ((val & (ISACX_RSTAD_VFR | - ISACX_RSTAD_RDO | - ISACX_RSTAD_CRC | - ISACX_RSTAD_RAB)) - != (ISACX_RSTAD_VFR | ISACX_RSTAD_CRC)) { - pr_debug("%s: RSTAD %#x, dropped\n", isac->name, val); -#ifdef ERROR_STATISTIC - if (val & ISACX_RSTAD_CRC) - isac->dch.err_rx++; - else - isac->dch.err_crc++; -#endif - WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC); - if (isac->dch.rx_skb) - dev_kfree_skb(isac->dch.rx_skb); - isac->dch.rx_skb = NULL; - } else { - count = ReadISAC(isac, ISACX_RBCLD) & 0x1f; - if (count == 0) - count = 32; - isac_empty_fifo(isac, count); - if (isac->dch.rx_skb) { - skb_trim(isac->dch.rx_skb, isac->dch.rx_skb->len - 1); - pr_debug("%s: dchannel received %d\n", isac->name, - isac->dch.rx_skb->len); - recv_Dchannel(&isac->dch); - } - } -} - -irqreturn_t -mISDNisac_irq(struct isac_hw *isac, u8 val) -{ - if (unlikely(!val)) - return IRQ_NONE; - pr_debug("%s: ISAC interrupt %02x\n", isac->name, val); - if (isac->type & IPAC_TYPE_ISACX) { - if (val & ISACX__CIC) - isacsx_cic_irq(isac); - if (val & ISACX__ICD) { - val = ReadISAC(isac, ISACX_ISTAD); - pr_debug("%s: ISTAD %02x\n", isac->name, val); - if (val & ISACX_D_XDU) { - pr_debug("%s: ISAC XDU\n", isac->name); -#ifdef ERROR_STATISTIC - isac->dch.err_tx++; -#endif - isac_retransmit(isac); - } - if (val & ISACX_D_XMR) { - pr_debug("%s: ISAC XMR\n", isac->name); -#ifdef ERROR_STATISTIC - isac->dch.err_tx++; -#endif - isac_retransmit(isac); - } - if (val & ISACX_D_XPR) - isac_xpr_irq(isac); - if (val & ISACX_D_RFO) { - pr_debug("%s: ISAC RFO\n", isac->name); - WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC); - } - if (val & ISACX_D_RME) - isacsx_rme_irq(isac); - if (val & ISACX_D_RPF) - isac_empty_fifo(isac, 0x20); - } - } else { - if (val & 0x80) /* RME */ - isac_rme_irq(isac); - if (val & 0x40) /* RPF */ - isac_empty_fifo(isac, 32); - if (val & 0x10) /* XPR */ - isac_xpr_irq(isac); - if (val & 0x04) /* CISQ */ - isac_cisq_irq(isac); - if (val & 0x20) /* RSC - never */ - pr_debug("%s: ISAC RSC interrupt\n", isac->name); - if (val & 0x02) /* SIN - never */ - pr_debug("%s: ISAC SIN interrupt\n", isac->name); - if (val & 0x01) { /* EXI */ - val = ReadISAC(isac, ISAC_EXIR); - pr_debug("%s: ISAC EXIR %02x\n", isac->name, val); - if (val & 0x80) /* XMR */ - pr_debug("%s: ISAC XMR\n", isac->name); - if (val & 0x40) { /* XDU */ - pr_debug("%s: ISAC XDU\n", isac->name); -#ifdef ERROR_STATISTIC - isac->dch.err_tx++; -#endif - isac_retransmit(isac); - } - if (val & 0x04) /* MOS */ - isac_mos_irq(isac); - } - } - return IRQ_HANDLED; -} -EXPORT_SYMBOL(mISDNisac_irq); - -static int -isac_l1hw(struct mISDNchannel *ch, struct sk_buff *skb) -{ - struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); - struct dchannel *dch = container_of(dev, struct dchannel, dev); - struct isac_hw *isac = container_of(dch, struct isac_hw, dch); - int ret = -EINVAL; - struct mISDNhead *hh = mISDN_HEAD_P(skb); - u32 id; - u_long flags; - - switch (hh->prim) { - case PH_DATA_REQ: - spin_lock_irqsave(isac->hwlock, flags); - ret = dchannel_senddata(dch, skb); - if (ret > 0) { /* direct TX */ - id = hh->id; /* skb can be freed */ - isac_fill_fifo(isac); - ret = 0; - spin_unlock_irqrestore(isac->hwlock, flags); - queue_ch_frame(ch, PH_DATA_CNF, id, NULL); - } else - spin_unlock_irqrestore(isac->hwlock, flags); - return ret; - case PH_ACTIVATE_REQ: - ret = l1_event(dch->l1, hh->prim); - break; - case PH_DEACTIVATE_REQ: - test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); - ret = l1_event(dch->l1, hh->prim); - break; - } - - if (!ret) - dev_kfree_skb(skb); - return ret; -} - -static int -isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para) -{ - u8 tl = 0; - u_long flags; - - switch (cmd) { - case HW_TESTLOOP: - spin_lock_irqsave(isac->hwlock, flags); - if (!(isac->type & IPAC_TYPE_ISACX)) { - /* TODO: implement for IPAC_TYPE_ISACX */ - if (para & 1) /* B1 */ - tl |= 0x0c; - else if (para & 2) /* B2 */ - tl |= 0x3; - /* we only support IOM2 mode */ - WriteISAC(isac, ISAC_SPCR, tl); - if (tl) - WriteISAC(isac, ISAC_ADF1, 0x8); - else - WriteISAC(isac, ISAC_ADF1, 0x0); - } - spin_unlock_irqrestore(isac->hwlock, flags); - break; - default: - pr_debug("%s: %s unknown command %x %lx\n", isac->name, - __func__, cmd, para); - return -1; - } - return 0; -} - -static int -isac_l1cmd(struct dchannel *dch, u32 cmd) -{ - struct isac_hw *isac = container_of(dch, struct isac_hw, dch); - u_long flags; - - pr_debug("%s: cmd(%x) state(%02x)\n", isac->name, cmd, isac->state); - switch (cmd) { - case INFO3_P8: - spin_lock_irqsave(isac->hwlock, flags); - ph_command(isac, ISAC_CMD_AR8); - spin_unlock_irqrestore(isac->hwlock, flags); - break; - case INFO3_P10: - spin_lock_irqsave(isac->hwlock, flags); - ph_command(isac, ISAC_CMD_AR10); - spin_unlock_irqrestore(isac->hwlock, flags); - break; - case HW_RESET_REQ: - spin_lock_irqsave(isac->hwlock, flags); - if ((isac->state == ISAC_IND_EI) || - (isac->state == ISAC_IND_DR) || - (isac->state == ISAC_IND_RS)) - ph_command(isac, ISAC_CMD_TIM); - else - ph_command(isac, ISAC_CMD_RS); - spin_unlock_irqrestore(isac->hwlock, flags); - break; - case HW_DEACT_REQ: - skb_queue_purge(&dch->squeue); - if (dch->tx_skb) { - dev_kfree_skb(dch->tx_skb); - dch->tx_skb = NULL; - } - dch->tx_idx = 0; - if (dch->rx_skb) { - dev_kfree_skb(dch->rx_skb); - dch->rx_skb = NULL; - } - test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); - if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) - del_timer(&dch->timer); - break; - case HW_POWERUP_REQ: - spin_lock_irqsave(isac->hwlock, flags); - ph_command(isac, ISAC_CMD_TIM); - spin_unlock_irqrestore(isac->hwlock, flags); - break; - case PH_ACTIVATE_IND: - test_and_set_bit(FLG_ACTIVE, &dch->Flags); - _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL, - GFP_ATOMIC); - break; - case PH_DEACTIVATE_IND: - test_and_clear_bit(FLG_ACTIVE, &dch->Flags); - _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL, - GFP_ATOMIC); - break; - default: - pr_debug("%s: %s unknown command %x\n", isac->name, - __func__, cmd); - return -1; - } - return 0; -} - -static void -isac_release(struct isac_hw *isac) -{ - if (isac->type & IPAC_TYPE_ISACX) - WriteISAC(isac, ISACX_MASK, 0xff); - else - WriteISAC(isac, ISAC_MASK, 0xff); - if (isac->dch.timer.function != NULL) { - del_timer(&isac->dch.timer); - isac->dch.timer.function = NULL; - } - kfree(isac->mon_rx); - isac->mon_rx = NULL; - kfree(isac->mon_tx); - isac->mon_tx = NULL; - if (isac->dch.l1) - l1_event(isac->dch.l1, CLOSE_CHANNEL); - mISDN_freedchannel(&isac->dch); -} - -static void -dbusy_timer_handler(struct isac_hw *isac) -{ - int rbch, star; - u_long flags; - - if (test_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) { - spin_lock_irqsave(isac->hwlock, flags); - rbch = ReadISAC(isac, ISAC_RBCH); - star = ReadISAC(isac, ISAC_STAR); - pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n", - isac->name, rbch, star); - if (rbch & ISAC_RBCH_XAC) /* D-Channel Busy */ - test_and_set_bit(FLG_L1_BUSY, &isac->dch.Flags); - else { - /* discard frame; reset transceiver */ - test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags); - if (isac->dch.tx_idx) - isac->dch.tx_idx = 0; - else - pr_info("%s: ISAC D-Channel Busy no tx_idx\n", - isac->name); - /* Transmitter reset */ - WriteISAC(isac, ISAC_CMDR, 0x01); - } - spin_unlock_irqrestore(isac->hwlock, flags); - } -} - -static int -open_dchannel(struct isac_hw *isac, struct channel_req *rq) -{ - pr_debug("%s: %s dev(%d) open from %p\n", isac->name, __func__, - isac->dch.dev.id, __builtin_return_address(1)); - if (rq->protocol != ISDN_P_TE_S0) - return -EINVAL; - if (rq->adr.channel == 1) - /* E-Channel not supported */ - return -EINVAL; - rq->ch = &isac->dch.dev.D; - rq->ch->protocol = rq->protocol; - if (isac->dch.state == 7) - _queue_data(rq->ch, PH_ACTIVATE_IND, MISDN_ID_ANY, - 0, NULL, GFP_KERNEL); - return 0; -} - -static const char *ISACVer[] = -{"2086/2186 V1.1", "2085 B1", "2085 B2", - "2085 V2.3"}; - -static int -isac_init(struct isac_hw *isac) -{ - u8 val; - int err = 0; - - if (!isac->dch.l1) { - err = create_l1(&isac->dch, isac_l1cmd); - if (err) - return err; - } - isac->mon_tx = NULL; - isac->mon_rx = NULL; - isac->dch.timer.function = (void *) dbusy_timer_handler; - isac->dch.timer.data = (long)isac; - init_timer(&isac->dch.timer); - isac->mocr = 0xaa; - if (isac->type & IPAC_TYPE_ISACX) { - /* Disable all IRQ */ - WriteISAC(isac, ISACX_MASK, 0xff); - val = ReadISAC(isac, ISACX_STARD); - pr_debug("%s: ISACX STARD %x\n", isac->name, val); - val = ReadISAC(isac, ISACX_ISTAD); - pr_debug("%s: ISACX ISTAD %x\n", isac->name, val); - val = ReadISAC(isac, ISACX_ISTA); - pr_debug("%s: ISACX ISTA %x\n", isac->name, val); - /* clear LDD */ - WriteISAC(isac, ISACX_TR_CONF0, 0x00); - /* enable transmitter */ - WriteISAC(isac, ISACX_TR_CONF2, 0x00); - /* transparent mode 0, RAC, stop/go */ - WriteISAC(isac, ISACX_MODED, 0xc9); - /* all HDLC IRQ unmasked */ - val = ReadISAC(isac, ISACX_ID); - if (isac->dch.debug & DEBUG_HW) - pr_notice("%s: ISACX Design ID %x\n", - isac->name, val & 0x3f); - val = ReadISAC(isac, ISACX_CIR0); - pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val); - isac->state = val >> 4; - isac_ph_state_change(isac); - ph_command(isac, ISAC_CMD_RS); - WriteISAC(isac, ISACX_MASK, IPACX__ON); - WriteISAC(isac, ISACX_MASKD, 0x00); - } else { /* old isac */ - WriteISAC(isac, ISAC_MASK, 0xff); - val = ReadISAC(isac, ISAC_STAR); - pr_debug("%s: ISAC STAR %x\n", isac->name, val); - val = ReadISAC(isac, ISAC_MODE); - pr_debug("%s: ISAC MODE %x\n", isac->name, val); - val = ReadISAC(isac, ISAC_ADF2); - pr_debug("%s: ISAC ADF2 %x\n", isac->name, val); - val = ReadISAC(isac, ISAC_ISTA); - pr_debug("%s: ISAC ISTA %x\n", isac->name, val); - if (val & 0x01) { - val = ReadISAC(isac, ISAC_EXIR); - pr_debug("%s: ISAC EXIR %x\n", isac->name, val); - } - val = ReadISAC(isac, ISAC_RBCH); - if (isac->dch.debug & DEBUG_HW) - pr_notice("%s: ISAC version (%x): %s\n", isac->name, - val, ISACVer[(val >> 5) & 3]); - isac->type |= ((val >> 5) & 3); - if (!isac->adf2) - isac->adf2 = 0x80; - if (!(isac->adf2 & 0x80)) { /* only IOM 2 Mode */ - pr_info("%s: only support IOM2 mode but adf2=%02x\n", - isac->name, isac->adf2); - isac_release(isac); - return -EINVAL; - } - WriteISAC(isac, ISAC_ADF2, isac->adf2); - WriteISAC(isac, ISAC_SQXR, 0x2f); - WriteISAC(isac, ISAC_SPCR, 0x00); - WriteISAC(isac, ISAC_STCR, 0x70); - WriteISAC(isac, ISAC_MODE, 0xc9); - WriteISAC(isac, ISAC_TIMR, 0x00); - WriteISAC(isac, ISAC_ADF1, 0x00); - val = ReadISAC(isac, ISAC_CIR0); - pr_debug("%s: ISAC CIR0 %x\n", isac->name, val); - isac->state = (val >> 2) & 0xf; - isac_ph_state_change(isac); - ph_command(isac, ISAC_CMD_RS); - WriteISAC(isac, ISAC_MASK, 0); - } - return err; -} - -int -mISDNisac_init(struct isac_hw *isac, void *hw) -{ - mISDN_initdchannel(&isac->dch, MAX_DFRAME_LEN_L1, isac_ph_state_bh); - isac->dch.hw = hw; - isac->dch.dev.D.send = isac_l1hw; - isac->init = isac_init; - isac->release = isac_release; - isac->ctrl = isac_ctrl; - isac->open = open_dchannel; - isac->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0); - isac->dch.dev.nrbchan = 2; - return 0; -} -EXPORT_SYMBOL(mISDNisac_init); - -static void -waitforCEC(struct hscx_hw *hx) -{ - u8 starb, to = 50; - - while (to) { - starb = ReadHSCX(hx, IPAC_STARB); - if (!(starb & 0x04)) - break; - udelay(1); - to--; - } - if (to < 50) - pr_debug("%s: B%1d CEC %d us\n", hx->ip->name, hx->bch.nr, - 50 - to); - if (!to) - pr_info("%s: B%1d CEC timeout\n", hx->ip->name, hx->bch.nr); -} - - -static void -waitforXFW(struct hscx_hw *hx) -{ - u8 starb, to = 50; - - while (to) { - starb = ReadHSCX(hx, IPAC_STARB); - if ((starb & 0x44) == 0x40) - break; - udelay(1); - to--; - } - if (to < 50) - pr_debug("%s: B%1d XFW %d us\n", hx->ip->name, hx->bch.nr, - 50 - to); - if (!to) - pr_info("%s: B%1d XFW timeout\n", hx->ip->name, hx->bch.nr); -} - -static void -hscx_cmdr(struct hscx_hw *hx, u8 cmd) -{ - if (hx->ip->type & IPAC_TYPE_IPACX) - WriteHSCX(hx, IPACX_CMDRB, cmd); - else { - waitforCEC(hx); - WriteHSCX(hx, IPAC_CMDRB, cmd); - } -} - -static void -hscx_empty_fifo(struct hscx_hw *hscx, u8 count) -{ - u8 *p; - - pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count); - if (!hscx->bch.rx_skb) { - hscx->bch.rx_skb = mI_alloc_skb(hscx->bch.maxlen, GFP_ATOMIC); - if (!hscx->bch.rx_skb) { - pr_info("%s: B receive out of memory\n", - hscx->ip->name); - hscx_cmdr(hscx, 0x80); /* RMC */ - return; - } - } - if ((hscx->bch.rx_skb->len + count) > hscx->bch.maxlen) { - pr_debug("%s: overrun %d\n", hscx->ip->name, - hscx->bch.rx_skb->len + count); - skb_trim(hscx->bch.rx_skb, 0); - hscx_cmdr(hscx, 0x80); /* RMC */ - return; - } - p = skb_put(hscx->bch.rx_skb, count); - - if (hscx->ip->type & IPAC_TYPE_IPACX) - hscx->ip->read_fifo(hscx->ip->hw, - hscx->off + IPACX_RFIFOB, p, count); - else - hscx->ip->read_fifo(hscx->ip->hw, - hscx->off, p, count); - - hscx_cmdr(hscx, 0x80); /* RMC */ - - if (hscx->bch.debug & DEBUG_HW_BFIFO) { - snprintf(hscx->log, 64, "B%1d-recv %s %d ", - hscx->bch.nr, hscx->ip->name, count); - print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count); - } -} - -static void -hscx_fill_fifo(struct hscx_hw *hscx) -{ - int count, more; - u8 *p; - - if (!hscx->bch.tx_skb) - return; - count = hscx->bch.tx_skb->len - hscx->bch.tx_idx; - if (count <= 0) - return; - p = hscx->bch.tx_skb->data + hscx->bch.tx_idx; - - more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0; - if (count > hscx->fifo_size) { - count = hscx->fifo_size; - more = 1; - } - pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr, count, - hscx->bch.tx_idx, hscx->bch.tx_skb->len); - hscx->bch.tx_idx += count; - - if (hscx->ip->type & IPAC_TYPE_IPACX) - hscx->ip->write_fifo(hscx->ip->hw, - hscx->off + IPACX_XFIFOB, p, count); - else { - waitforXFW(hscx); - hscx->ip->write_fifo(hscx->ip->hw, - hscx->off, p, count); - } - hscx_cmdr(hscx, more ? 0x08 : 0x0a); - - if (hscx->bch.debug & DEBUG_HW_BFIFO) { - snprintf(hscx->log, 64, "B%1d-send %s %d ", - hscx->bch.nr, hscx->ip->name, count); - print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count); - } -} - -static void -hscx_xpr(struct hscx_hw *hx) -{ - if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) - hscx_fill_fifo(hx); - else { - if (hx->bch.tx_skb) { - /* send confirm, on trans, free on hdlc. */ - if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) - confirm_Bsend(&hx->bch); - dev_kfree_skb(hx->bch.tx_skb); - } - if (get_next_bframe(&hx->bch)) - hscx_fill_fifo(hx); - } -} - -static void -ipac_rme(struct hscx_hw *hx) -{ - int count; - u8 rstab; - - if (hx->ip->type & IPAC_TYPE_IPACX) - rstab = ReadHSCX(hx, IPACX_RSTAB); - else - rstab = ReadHSCX(hx, IPAC_RSTAB); - pr_debug("%s: B%1d RSTAB %02x\n", hx->ip->name, hx->bch.nr, rstab); - if ((rstab & 0xf0) != 0xa0) { - /* !(VFR && !RDO && CRC && !RAB) */ - if (!(rstab & 0x80)) { - if (hx->bch.debug & DEBUG_HW_BCHANNEL) - pr_notice("%s: B%1d invalid frame\n", - hx->ip->name, hx->bch.nr); - } - if (rstab & 0x40) { - if (hx->bch.debug & DEBUG_HW_BCHANNEL) - pr_notice("%s: B%1d RDO proto=%x\n", - hx->ip->name, hx->bch.nr, - hx->bch.state); - } - if (!(rstab & 0x20)) { - if (hx->bch.debug & DEBUG_HW_BCHANNEL) - pr_notice("%s: B%1d CRC error\n", - hx->ip->name, hx->bch.nr); - } - hscx_cmdr(hx, 0x80); /* Do RMC */ - return; - } - if (hx->ip->type & IPAC_TYPE_IPACX) - count = ReadHSCX(hx, IPACX_RBCLB); - else - count = ReadHSCX(hx, IPAC_RBCLB); - count &= (hx->fifo_size - 1); - if (count == 0) - count = hx->fifo_size; - hscx_empty_fifo(hx, count); - if (!hx->bch.rx_skb) - return; - if (hx->bch.rx_skb->len < 2) { - pr_debug("%s: B%1d frame to short %d\n", - hx->ip->name, hx->bch.nr, hx->bch.rx_skb->len); - skb_trim(hx->bch.rx_skb, 0); - } else { - skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1); - recv_Bchannel(&hx->bch, 0); - } -} - -static void -ipac_irq(struct hscx_hw *hx, u8 ista) -{ - u8 istab, m, exirb = 0; - - if (hx->ip->type & IPAC_TYPE_IPACX) - istab = ReadHSCX(hx, IPACX_ISTAB); - else if (hx->ip->type & IPAC_TYPE_IPAC) { - istab = ReadHSCX(hx, IPAC_ISTAB); - m = (hx->bch.nr & 1) ? IPAC__EXA : IPAC__EXB; - if (m & ista) { - exirb = ReadHSCX(hx, IPAC_EXIRB); - pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name, - hx->bch.nr, exirb); - } - } else if (hx->bch.nr & 2) { /* HSCX B */ - if (ista & (HSCX__EXA | HSCX__ICA)) - ipac_irq(&hx->ip->hscx[0], ista); - if (ista & HSCX__EXB) { - exirb = ReadHSCX(hx, IPAC_EXIRB); - pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name, - hx->bch.nr, exirb); - } - istab = ista & 0xF8; - } else { /* HSCX A */ - istab = ReadHSCX(hx, IPAC_ISTAB); - if (ista & HSCX__EXA) { - exirb = ReadHSCX(hx, IPAC_EXIRB); - pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name, - hx->bch.nr, exirb); - } - istab = istab & 0xF8; - } - if (exirb & IPAC_B_XDU) - istab |= IPACX_B_XDU; - if (exirb & IPAC_B_RFO) - istab |= IPACX_B_RFO; - pr_debug("%s: B%1d ISTAB %02x\n", hx->ip->name, hx->bch.nr, istab); - - if (!test_bit(FLG_ACTIVE, &hx->bch.Flags)) - return; - - if (istab & IPACX_B_RME) - ipac_rme(hx); - - if (istab & IPACX_B_RPF) { - hscx_empty_fifo(hx, hx->fifo_size); - if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) { - /* receive transparent audio data */ - if (hx->bch.rx_skb) - recv_Bchannel(&hx->bch, 0); - } - } - - if (istab & IPACX_B_RFO) { - pr_debug("%s: B%1d RFO error\n", hx->ip->name, hx->bch.nr); - hscx_cmdr(hx, 0x40); /* RRES */ - } - - if (istab & IPACX_B_XPR) - hscx_xpr(hx); - - if (istab & IPACX_B_XDU) { - if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) { - hscx_fill_fifo(hx); - return; - } - pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name, - hx->bch.nr, hx->bch.tx_idx); - hx->bch.tx_idx = 0; - hscx_cmdr(hx, 0x01); /* XRES */ - } -} - -irqreturn_t -mISDNipac_irq(struct ipac_hw *ipac, int maxloop) -{ - int cnt = maxloop + 1; - u8 ista, istad; - struct isac_hw *isac = &ipac->isac; - - if (ipac->type & IPAC_TYPE_IPACX) { - ista = ReadIPAC(ipac, ISACX_ISTA); - while (ista && cnt--) { - pr_debug("%s: ISTA %02x\n", ipac->name, ista); - if (ista & IPACX__ICA) - ipac_irq(&ipac->hscx[0], ista); - if (ista & IPACX__ICB) - ipac_irq(&ipac->hscx[1], ista); - if (ista & (ISACX__ICD | ISACX__CIC)) - mISDNisac_irq(&ipac->isac, ista); - ista = ReadIPAC(ipac, ISACX_ISTA); - } - } else if (ipac->type & IPAC_TYPE_IPAC) { - ista = ReadIPAC(ipac, IPAC_ISTA); - while (ista && cnt--) { - pr_debug("%s: ISTA %02x\n", ipac->name, ista); - if (ista & (IPAC__ICD | IPAC__EXD)) { - istad = ReadISAC(isac, ISAC_ISTA); - pr_debug("%s: ISTAD %02x\n", ipac->name, istad); - if (istad & IPAC_D_TIN2) - pr_debug("%s TIN2 irq\n", ipac->name); - if (ista & IPAC__EXD) - istad |= 1; /* ISAC EXI */ - mISDNisac_irq(isac, istad); - } - if (ista & (IPAC__ICA | IPAC__EXA)) - ipac_irq(&ipac->hscx[0], ista); - if (ista & (IPAC__ICB | IPAC__EXB)) - ipac_irq(&ipac->hscx[1], ista); - ista = ReadIPAC(ipac, IPAC_ISTA); - } - } else if (ipac->type & IPAC_TYPE_HSCX) { - while (cnt) { - ista = ReadIPAC(ipac, IPAC_ISTAB + ipac->hscx[1].off); - pr_debug("%s: B2 ISTA %02x\n", ipac->name, ista); - if (ista) - ipac_irq(&ipac->hscx[1], ista); - istad = ReadISAC(isac, ISAC_ISTA); - pr_debug("%s: ISTAD %02x\n", ipac->name, istad); - if (istad) - mISDNisac_irq(isac, istad); - if (0 == (ista | istad)) - break; - cnt--; - } - } - if (cnt > maxloop) /* only for ISAC/HSCX without PCI IRQ test */ - return IRQ_NONE; - if (cnt < maxloop) - pr_debug("%s: %d irqloops cpu%d\n", ipac->name, - maxloop - cnt, smp_processor_id()); - if (maxloop && !cnt) - pr_notice("%s: %d IRQ LOOP cpu%d\n", ipac->name, - maxloop, smp_processor_id()); - return IRQ_HANDLED; -} -EXPORT_SYMBOL(mISDNipac_irq); - -static int -hscx_mode(struct hscx_hw *hscx, u32 bprotocol) -{ - pr_debug("%s: HSCX %c protocol %x-->%x ch %d\n", hscx->ip->name, - '@' + hscx->bch.nr, hscx->bch.state, bprotocol, hscx->bch.nr); - if (hscx->ip->type & IPAC_TYPE_IPACX) { - if (hscx->bch.nr & 1) { /* B1 and ICA */ - WriteIPAC(hscx->ip, ISACX_BCHA_TSDP_BC1, 0x80); - WriteIPAC(hscx->ip, ISACX_BCHA_CR, 0x88); - } else { /* B2 and ICB */ - WriteIPAC(hscx->ip, ISACX_BCHB_TSDP_BC1, 0x81); - WriteIPAC(hscx->ip, ISACX_BCHB_CR, 0x88); - } - switch (bprotocol) { - case ISDN_P_NONE: /* init */ - WriteHSCX(hscx, IPACX_MODEB, 0xC0); /* rec off */ - WriteHSCX(hscx, IPACX_EXMB, 0x30); /* std adj. */ - WriteHSCX(hscx, IPACX_MASKB, 0xFF); /* ints off */ - hscx_cmdr(hscx, 0x41); - test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags); - test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags); - break; - case ISDN_P_B_RAW: - WriteHSCX(hscx, IPACX_MODEB, 0x88); /* ex trans */ - WriteHSCX(hscx, IPACX_EXMB, 0x00); /* trans */ - hscx_cmdr(hscx, 0x41); - WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON); - test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags); - break; - case ISDN_P_B_HDLC: - WriteHSCX(hscx, IPACX_MODEB, 0xC0); /* trans */ - WriteHSCX(hscx, IPACX_EXMB, 0x00); /* hdlc,crc */ - hscx_cmdr(hscx, 0x41); - WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON); - test_and_set_bit(FLG_HDLC, &hscx->bch.Flags); - break; - default: - pr_info("%s: protocol not known %x\n", hscx->ip->name, - bprotocol); - return -ENOPROTOOPT; - } - } else if (hscx->ip->type & IPAC_TYPE_IPAC) { /* IPAC */ - WriteHSCX(hscx, IPAC_CCR1, 0x82); - WriteHSCX(hscx, IPAC_CCR2, 0x30); - WriteHSCX(hscx, IPAC_XCCR, 0x07); - WriteHSCX(hscx, IPAC_RCCR, 0x07); - WriteHSCX(hscx, IPAC_TSAX, hscx->slot); - WriteHSCX(hscx, IPAC_TSAR, hscx->slot); - switch (bprotocol) { - case ISDN_P_NONE: - WriteHSCX(hscx, IPAC_TSAX, 0x1F); - WriteHSCX(hscx, IPAC_TSAR, 0x1F); - WriteHSCX(hscx, IPAC_MODEB, 0x84); - WriteHSCX(hscx, IPAC_CCR1, 0x82); - WriteHSCX(hscx, IPAC_MASKB, 0xFF); /* ints off */ - test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags); - test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags); - break; - case ISDN_P_B_RAW: - WriteHSCX(hscx, IPAC_MODEB, 0xe4); /* ex trans */ - WriteHSCX(hscx, IPAC_CCR1, 0x82); - hscx_cmdr(hscx, 0x41); - WriteHSCX(hscx, IPAC_MASKB, 0); - test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags); - break; - case ISDN_P_B_HDLC: - WriteHSCX(hscx, IPAC_MODEB, 0x8c); - WriteHSCX(hscx, IPAC_CCR1, 0x8a); - hscx_cmdr(hscx, 0x41); - WriteHSCX(hscx, IPAC_MASKB, 0); - test_and_set_bit(FLG_HDLC, &hscx->bch.Flags); - break; - default: - pr_info("%s: protocol not known %x\n", hscx->ip->name, - bprotocol); - return -ENOPROTOOPT; - } - } else if (hscx->ip->type & IPAC_TYPE_HSCX) { /* HSCX */ - WriteHSCX(hscx, IPAC_CCR1, 0x85); - WriteHSCX(hscx, IPAC_CCR2, 0x30); - WriteHSCX(hscx, IPAC_XCCR, 0x07); - WriteHSCX(hscx, IPAC_RCCR, 0x07); - WriteHSCX(hscx, IPAC_TSAX, hscx->slot); - WriteHSCX(hscx, IPAC_TSAR, hscx->slot); - switch (bprotocol) { - case ISDN_P_NONE: - WriteHSCX(hscx, IPAC_TSAX, 0x1F); - WriteHSCX(hscx, IPAC_TSAR, 0x1F); - WriteHSCX(hscx, IPAC_MODEB, 0x84); - WriteHSCX(hscx, IPAC_CCR1, 0x85); - WriteHSCX(hscx, IPAC_MASKB, 0xFF); /* ints off */ - test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags); - test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags); - break; - case ISDN_P_B_RAW: - WriteHSCX(hscx, IPAC_MODEB, 0xe4); /* ex trans */ - WriteHSCX(hscx, IPAC_CCR1, 0x85); - hscx_cmdr(hscx, 0x41); - WriteHSCX(hscx, IPAC_MASKB, 0); - test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags); - break; - case ISDN_P_B_HDLC: - WriteHSCX(hscx, IPAC_MODEB, 0x8c); - WriteHSCX(hscx, IPAC_CCR1, 0x8d); - hscx_cmdr(hscx, 0x41); - WriteHSCX(hscx, IPAC_MASKB, 0); - test_and_set_bit(FLG_HDLC, &hscx->bch.Flags); - break; - default: - pr_info("%s: protocol not known %x\n", hscx->ip->name, - bprotocol); - return -ENOPROTOOPT; - } - } else - return -EINVAL; - hscx->bch.state = bprotocol; - return 0; -} - -static int -hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb) -{ - struct bchannel *bch = container_of(ch, struct bchannel, ch); - struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch); - int ret = -EINVAL; - struct mISDNhead *hh = mISDN_HEAD_P(skb); - u32 id; - u_long flags; - - switch (hh->prim) { - case PH_DATA_REQ: - spin_lock_irqsave(hx->ip->hwlock, flags); - ret = bchannel_senddata(bch, skb); - if (ret > 0) { /* direct TX */ - id = hh->id; /* skb can be freed */ - ret = 0; - hscx_fill_fifo(hx); - spin_unlock_irqrestore(hx->ip->hwlock, flags); - if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) - queue_ch_frame(ch, PH_DATA_CNF, id, NULL); - } else - spin_unlock_irqrestore(hx->ip->hwlock, flags); - return ret; - case PH_ACTIVATE_REQ: - spin_lock_irqsave(hx->ip->hwlock, flags); - if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) - ret = hscx_mode(hx, ch->protocol); - else - ret = 0; - spin_unlock_irqrestore(hx->ip->hwlock, flags); - if (!ret) - _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, - NULL, GFP_KERNEL); - break; - case PH_DEACTIVATE_REQ: - spin_lock_irqsave(hx->ip->hwlock, flags); - mISDN_clear_bchannel(bch); - hscx_mode(hx, ISDN_P_NONE); - spin_unlock_irqrestore(hx->ip->hwlock, flags); - _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, - NULL, GFP_KERNEL); - ret = 0; - break; - default: - pr_info("%s: %s unknown prim(%x,%x)\n", - hx->ip->name, __func__, hh->prim, hh->id); - ret = -EINVAL; - } - if (!ret) - dev_kfree_skb(skb); - return ret; -} - -static int -channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) -{ - int ret = 0; - - switch (cq->op) { - case MISDN_CTRL_GETOP: - cq->op = 0; - break; - /* Nothing implemented yet */ - case MISDN_CTRL_FILL_EMPTY: - default: - pr_info("%s: unknown Op %x\n", __func__, cq->op); - ret = -EINVAL; - break; - } - return ret; -} - -static int -hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) -{ - struct bchannel *bch = container_of(ch, struct bchannel, ch); - struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch); - int ret = -EINVAL; - u_long flags; - - pr_debug("%s: %s cmd:%x %p\n", hx->ip->name, __func__, cmd, arg); - switch (cmd) { - case CLOSE_CHANNEL: - test_and_clear_bit(FLG_OPEN, &bch->Flags); - if (test_bit(FLG_ACTIVE, &bch->Flags)) { - spin_lock_irqsave(hx->ip->hwlock, flags); - mISDN_freebchannel(bch); - hscx_mode(hx, ISDN_P_NONE); - spin_unlock_irqrestore(hx->ip->hwlock, flags); - } else { - skb_queue_purge(&bch->rqueue); - bch->rcount = 0; - } - ch->protocol = ISDN_P_NONE; - ch->peer = NULL; - module_put(hx->ip->owner); - ret = 0; - break; - case CONTROL_CHANNEL: - ret = channel_bctrl(bch, arg); - break; - default: - pr_info("%s: %s unknown prim(%x)\n", - hx->ip->name, __func__, cmd); - } - return ret; -} - -static void -free_ipac(struct ipac_hw *ipac) -{ - isac_release(&ipac->isac); -} - -static const char *HSCXVer[] = -{"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7", - "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"}; - - - -static void -hscx_init(struct hscx_hw *hx) -{ - u8 val; - - WriteHSCX(hx, IPAC_RAH2, 0xFF); - WriteHSCX(hx, IPAC_XBCH, 0x00); - WriteHSCX(hx, IPAC_RLCR, 0x00); - - if (hx->ip->type & IPAC_TYPE_HSCX) { - WriteHSCX(hx, IPAC_CCR1, 0x85); - val = ReadHSCX(hx, HSCX_VSTR); - pr_debug("%s: HSCX VSTR %02x\n", hx->ip->name, val); - if (hx->bch.debug & DEBUG_HW) - pr_notice("%s: HSCX version %s\n", hx->ip->name, - HSCXVer[val & 0x0f]); - } else - WriteHSCX(hx, IPAC_CCR1, 0x82); - WriteHSCX(hx, IPAC_CCR2, 0x30); - WriteHSCX(hx, IPAC_XCCR, 0x07); - WriteHSCX(hx, IPAC_RCCR, 0x07); -} - -static int -ipac_init(struct ipac_hw *ipac) -{ - u8 val; - - if (ipac->type & IPAC_TYPE_HSCX) { - hscx_init(&ipac->hscx[0]); - hscx_init(&ipac->hscx[1]); - val = ReadIPAC(ipac, IPAC_ID); - } else if (ipac->type & IPAC_TYPE_IPAC) { - hscx_init(&ipac->hscx[0]); - hscx_init(&ipac->hscx[1]); - WriteIPAC(ipac, IPAC_MASK, IPAC__ON); - val = ReadIPAC(ipac, IPAC_CONF); - /* conf is default 0, but can be overwritten by card setup */ - pr_debug("%s: IPAC CONF %02x/%02x\n", ipac->name, - val, ipac->conf); - WriteIPAC(ipac, IPAC_CONF, ipac->conf); - val = ReadIPAC(ipac, IPAC_ID); - if (ipac->hscx[0].bch.debug & DEBUG_HW) - pr_notice("%s: IPAC Design ID %02x\n", ipac->name, val); - } - /* nothing special for IPACX to do here */ - return isac_init(&ipac->isac); -} - -static int -open_bchannel(struct ipac_hw *ipac, struct channel_req *rq) -{ - struct bchannel *bch; - - if (rq->adr.channel > 2) - return -EINVAL; - if (rq->protocol == ISDN_P_NONE) - return -EINVAL; - bch = &ipac->hscx[rq->adr.channel - 1].bch; - if (test_and_set_bit(FLG_OPEN, &bch->Flags)) - return -EBUSY; /* b-channel can be only open once */ - test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); - bch->ch.protocol = rq->protocol; - rq->ch = &bch->ch; - return 0; -} - -static int -channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq) -{ - int ret = 0; - - switch (cq->op) { - case MISDN_CTRL_GETOP: - cq->op = MISDN_CTRL_LOOP; - break; - case MISDN_CTRL_LOOP: - /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */ - if (cq->channel < 0 || cq->channel > 3) { - ret = -EINVAL; - break; - } - ret = ipac->ctrl(ipac, HW_TESTLOOP, cq->channel); - break; - default: - pr_info("%s: unknown CTRL OP %x\n", ipac->name, cq->op); - ret = -EINVAL; - break; - } - return ret; -} - -static int -ipac_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg) -{ - struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); - struct dchannel *dch = container_of(dev, struct dchannel, dev); - struct isac_hw *isac = container_of(dch, struct isac_hw, dch); - struct ipac_hw *ipac = container_of(isac, struct ipac_hw, isac); - struct channel_req *rq; - int err = 0; - - pr_debug("%s: DCTRL: %x %p\n", ipac->name, cmd, arg); - switch (cmd) { - case OPEN_CHANNEL: - rq = arg; - if (rq->protocol == ISDN_P_TE_S0) - err = open_dchannel(isac, rq); - else - err = open_bchannel(ipac, rq); - if (err) - break; - if (!try_module_get(ipac->owner)) - pr_info("%s: cannot get module\n", ipac->name); - break; - case CLOSE_CHANNEL: - pr_debug("%s: dev(%d) close from %p\n", ipac->name, - dch->dev.id, __builtin_return_address(0)); - module_put(ipac->owner); - break; - case CONTROL_CHANNEL: - err = channel_ctrl(ipac, arg); - break; - default: - pr_debug("%s: unknown DCTRL command %x\n", ipac->name, cmd); - return -EINVAL; - } - return err; -} - -u32 -mISDNipac_init(struct ipac_hw *ipac, void *hw) -{ - u32 ret; - u8 i; - - ipac->hw = hw; - if (ipac->isac.dch.debug & DEBUG_HW) - pr_notice("%s: ipac type %x\n", ipac->name, ipac->type); - if (ipac->type & IPAC_TYPE_HSCX) { - ipac->isac.type = IPAC_TYPE_ISAC; - ipac->hscx[0].off = 0; - ipac->hscx[1].off = 0x40; - ipac->hscx[0].fifo_size = 32; - ipac->hscx[1].fifo_size = 32; - } else if (ipac->type & IPAC_TYPE_IPAC) { - ipac->isac.type = IPAC_TYPE_IPAC | IPAC_TYPE_ISAC; - ipac->hscx[0].off = 0; - ipac->hscx[1].off = 0x40; - ipac->hscx[0].fifo_size = 64; - ipac->hscx[1].fifo_size = 64; - } else if (ipac->type & IPAC_TYPE_IPACX) { - ipac->isac.type = IPAC_TYPE_IPACX | IPAC_TYPE_ISACX; - ipac->hscx[0].off = IPACX_OFF_ICA; - ipac->hscx[1].off = IPACX_OFF_ICB; - ipac->hscx[0].fifo_size = 64; - ipac->hscx[1].fifo_size = 64; - } else - return 0; - - mISDNisac_init(&ipac->isac, hw); - - ipac->isac.dch.dev.D.ctrl = ipac_dctrl; - - for (i = 0; i < 2; i++) { - ipac->hscx[i].bch.nr = i + 1; - set_channelmap(i + 1, ipac->isac.dch.dev.channelmap); - list_add(&ipac->hscx[i].bch.ch.list, - &ipac->isac.dch.dev.bchannels); - mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM); - ipac->hscx[i].bch.ch.nr = i + 1; - ipac->hscx[i].bch.ch.send = &hscx_l2l1; - ipac->hscx[i].bch.ch.ctrl = hscx_bctrl; - ipac->hscx[i].bch.hw = hw; - ipac->hscx[i].ip = ipac; - /* default values for IOM time slots - * can be overwriten by card */ - ipac->hscx[i].slot = (i == 0) ? 0x2f : 0x03; - } - - ipac->init = ipac_init; - ipac->release = free_ipac; - - ret = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | - (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); - return ret; -} -EXPORT_SYMBOL(mISDNipac_init); - -static int __init -isac_mod_init(void) -{ - pr_notice("mISDNipac module version %s\n", ISAC_REV); - return 0; -} - -static void __exit -isac_mod_cleanup(void) -{ - pr_notice("mISDNipac module unloaded\n"); -} -module_init(isac_mod_init); -module_exit(isac_mod_cleanup); diff --git a/trunk/drivers/isdn/hardware/mISDN/mISDNisar.c b/trunk/drivers/isdn/hardware/mISDN/mISDNisar.c deleted file mode 100644 index de352a17673a..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/mISDNisar.c +++ /dev/null @@ -1,1726 +0,0 @@ -/* - * mISDNisar.c ISAR (Siemens PSB 7110) specific functions - * - * Author Karsten Keil (keil@isdn4linux.de) - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* define this to enable static debug messages, if you kernel supports - * dynamic debugging, you should use debugfs for this - */ -/* #define DEBUG */ - -#include -#include -#include -#include "isar.h" - -#define ISAR_REV "2.1" - -MODULE_AUTHOR("Karsten Keil"); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(ISAR_REV); - -#define DEBUG_HW_FIRMWARE_FIFO 0x10000 - -static const u8 faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146"; -static const u8 faxmodulation[] = {3, 24, 48, 72, 73, 74, 96, 97, 98, 121, - 122, 145, 146}; -#define FAXMODCNT 13 - -static void isar_setup(struct isar_hw *); - -static inline int -waitforHIA(struct isar_hw *isar, int timeout) -{ - int t = timeout; - u8 val = isar->read_reg(isar->hw, ISAR_HIA); - - while ((val & 1) && t) { - udelay(1); - t--; - val = isar->read_reg(isar->hw, ISAR_HIA); - } - pr_debug("%s: HIA after %dus\n", isar->name, timeout - t); - return timeout; -} - -/* - * send msg to ISAR mailbox - * if msg is NULL use isar->buf - */ -static int -send_mbox(struct isar_hw *isar, u8 his, u8 creg, u8 len, u8 *msg) -{ - if (!waitforHIA(isar, 1000)) - return 0; - pr_debug("send_mbox(%02x,%02x,%d)\n", his, creg, len); - isar->write_reg(isar->hw, ISAR_CTRL_H, creg); - isar->write_reg(isar->hw, ISAR_CTRL_L, len); - isar->write_reg(isar->hw, ISAR_WADR, 0); - if (!msg) - msg = isar->buf; - if (msg && len) { - isar->write_fifo(isar->hw, ISAR_MBOX, msg, len); - if (isar->ch[0].bch.debug & DEBUG_HW_BFIFO) { - int l = 0; - - while (l < (int)len) { - hex_dump_to_buffer(msg + l, len - l, 32, 1, - isar->log, 256, 1); - pr_debug("%s: %s %02x: %s\n", isar->name, - __func__, l, isar->log); - l += 32; - } - } - } - isar->write_reg(isar->hw, ISAR_HIS, his); - waitforHIA(isar, 1000); - return 1; -} - -/* - * receive message from ISAR mailbox - * if msg is NULL use isar->buf - */ -static void -rcv_mbox(struct isar_hw *isar, u8 *msg) -{ - if (!msg) - msg = isar->buf; - isar->write_reg(isar->hw, ISAR_RADR, 0); - if (msg && isar->clsb) { - isar->read_fifo(isar->hw, ISAR_MBOX, msg, isar->clsb); - if (isar->ch[0].bch.debug & DEBUG_HW_BFIFO) { - int l = 0; - - while (l < (int)isar->clsb) { - hex_dump_to_buffer(msg + l, isar->clsb - l, 32, - 1, isar->log, 256, 1); - pr_debug("%s: %s %02x: %s\n", isar->name, - __func__, l, isar->log); - l += 32; - } - } - } - isar->write_reg(isar->hw, ISAR_IIA, 0); -} - -static inline void -get_irq_infos(struct isar_hw *isar) -{ - isar->iis = isar->read_reg(isar->hw, ISAR_IIS); - isar->cmsb = isar->read_reg(isar->hw, ISAR_CTRL_H); - isar->clsb = isar->read_reg(isar->hw, ISAR_CTRL_L); - pr_debug("%s: rcv_mbox(%02x,%02x,%d)\n", isar->name, - isar->iis, isar->cmsb, isar->clsb); -} - -/* - * poll answer message from ISAR mailbox - * should be used only with ISAR IRQs disabled before DSP was started - * - */ -static int -poll_mbox(struct isar_hw *isar, int maxdelay) -{ - int t = maxdelay; - u8 irq; - - irq = isar->read_reg(isar->hw, ISAR_IRQBIT); - while (t && !(irq & ISAR_IRQSTA)) { - udelay(1); - t--; - } - if (t) { - get_irq_infos(isar); - rcv_mbox(isar, NULL); - } - pr_debug("%s: pulled %d bytes after %d us\n", - isar->name, isar->clsb, maxdelay - t); - return t; -} - -static int -ISARVersion(struct isar_hw *isar) -{ - int ver; - - /* disable ISAR IRQ */ - isar->write_reg(isar->hw, ISAR_IRQBIT, 0); - isar->buf[0] = ISAR_MSG_HWVER; - isar->buf[1] = 0; - isar->buf[2] = 1; - if (!send_mbox(isar, ISAR_HIS_VNR, 0, 3, NULL)) - return -1; - if (!poll_mbox(isar, 1000)) - return -2; - if (isar->iis == ISAR_IIS_VNR) { - if (isar->clsb == 1) { - ver = isar->buf[0] & 0xf; - return ver; - } - return -3; - } - return -4; -} - -static int -load_firmware(struct isar_hw *isar, const u8 *buf, int size) -{ - u32 saved_debug = isar->ch[0].bch.debug; - int ret, cnt; - u8 nom, noc; - u16 left, val, *sp = (u16 *)buf; - u8 *mp; - u_long flags; - - struct { - u16 sadr; - u16 len; - u16 d_key; - } blk_head; - - if (1 != isar->version) { - pr_err("%s: ISAR wrong version %d firmware download aborted\n", - isar->name, isar->version); - return -EINVAL; - } - if (!(saved_debug & DEBUG_HW_FIRMWARE_FIFO)) - isar->ch[0].bch.debug &= ~DEBUG_HW_BFIFO; - pr_debug("%s: load firmware %d words (%d bytes)\n", - isar->name, size/2, size); - cnt = 0; - size /= 2; - /* disable ISAR IRQ */ - spin_lock_irqsave(isar->hwlock, flags); - isar->write_reg(isar->hw, ISAR_IRQBIT, 0); - spin_unlock_irqrestore(isar->hwlock, flags); - while (cnt < size) { - blk_head.sadr = le16_to_cpu(*sp++); - blk_head.len = le16_to_cpu(*sp++); - blk_head.d_key = le16_to_cpu(*sp++); - cnt += 3; - pr_debug("ISAR firmware block (%#x,%d,%#x)\n", - blk_head.sadr, blk_head.len, blk_head.d_key & 0xff); - left = blk_head.len; - if (cnt + left > size) { - pr_info("%s: firmware error have %d need %d words\n", - isar->name, size, cnt + left); - ret = -EINVAL; - goto reterrflg; - } - spin_lock_irqsave(isar->hwlock, flags); - if (!send_mbox(isar, ISAR_HIS_DKEY, blk_head.d_key & 0xff, - 0, NULL)) { - pr_info("ISAR send_mbox dkey failed\n"); - ret = -ETIME; - goto reterror; - } - if (!poll_mbox(isar, 1000)) { - pr_warning("ISAR poll_mbox dkey failed\n"); - ret = -ETIME; - goto reterror; - } - spin_unlock_irqrestore(isar->hwlock, flags); - if ((isar->iis != ISAR_IIS_DKEY) || isar->cmsb || isar->clsb) { - pr_info("ISAR wrong dkey response (%x,%x,%x)\n", - isar->iis, isar->cmsb, isar->clsb); - ret = 1; - goto reterrflg; - } - while (left > 0) { - if (left > 126) - noc = 126; - else - noc = left; - nom = (2 * noc) + 3; - mp = isar->buf; - /* the ISAR is big endian */ - *mp++ = blk_head.sadr >> 8; - *mp++ = blk_head.sadr & 0xFF; - left -= noc; - cnt += noc; - *mp++ = noc; - pr_debug("%s: load %3d words at %04x\n", isar->name, - noc, blk_head.sadr); - blk_head.sadr += noc; - while (noc) { - val = le16_to_cpu(*sp++); - *mp++ = val >> 8; - *mp++ = val & 0xFF;; - noc--; - } - spin_lock_irqsave(isar->hwlock, flags); - if (!send_mbox(isar, ISAR_HIS_FIRM, 0, nom, NULL)) { - pr_info("ISAR send_mbox prog failed\n"); - ret = -ETIME; - goto reterror; - } - if (!poll_mbox(isar, 1000)) { - pr_info("ISAR poll_mbox prog failed\n"); - ret = -ETIME; - goto reterror; - } - spin_unlock_irqrestore(isar->hwlock, flags); - if ((isar->iis != ISAR_IIS_FIRM) || - isar->cmsb || isar->clsb) { - pr_info("ISAR wrong prog response (%x,%x,%x)\n", - isar->iis, isar->cmsb, isar->clsb); - ret = -EIO; - goto reterrflg; - } - } - pr_debug("%s: ISAR firmware block %d words loaded\n", - isar->name, blk_head.len); - } - isar->ch[0].bch.debug = saved_debug; - /* 10ms delay */ - cnt = 10; - while (cnt--) - mdelay(1); - isar->buf[0] = 0xff; - isar->buf[1] = 0xfe; - isar->bstat = 0; - spin_lock_irqsave(isar->hwlock, flags); - if (!send_mbox(isar, ISAR_HIS_STDSP, 0, 2, NULL)) { - pr_info("ISAR send_mbox start dsp failed\n"); - ret = -ETIME; - goto reterror; - } - if (!poll_mbox(isar, 1000)) { - pr_info("ISAR poll_mbox start dsp failed\n"); - ret = -ETIME; - goto reterror; - } - if ((isar->iis != ISAR_IIS_STDSP) || isar->cmsb || isar->clsb) { - pr_info("ISAR wrong start dsp response (%x,%x,%x)\n", - isar->iis, isar->cmsb, isar->clsb); - ret = -EIO; - goto reterror; - } else - pr_debug("%s: ISAR start dsp success\n", isar->name); - - /* NORMAL mode entered */ - /* Enable IRQs of ISAR */ - isar->write_reg(isar->hw, ISAR_IRQBIT, ISAR_IRQSTA); - spin_unlock_irqrestore(isar->hwlock, flags); - cnt = 1000; /* max 1s */ - while ((!isar->bstat) && cnt) { - mdelay(1); - cnt--; - } - if (!cnt) { - pr_info("ISAR no general status event received\n"); - ret = -ETIME; - goto reterrflg; - } else - pr_debug("%s: ISAR general status event %x\n", - isar->name, isar->bstat); - /* 10ms delay */ - cnt = 10; - while (cnt--) - mdelay(1); - isar->iis = 0; - spin_lock_irqsave(isar->hwlock, flags); - if (!send_mbox(isar, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) { - pr_info("ISAR send_mbox self tst failed\n"); - ret = -ETIME; - goto reterror; - } - spin_unlock_irqrestore(isar->hwlock, flags); - cnt = 10000; /* max 100 ms */ - while ((isar->iis != ISAR_IIS_DIAG) && cnt) { - udelay(10); - cnt--; - } - mdelay(1); - if (!cnt) { - pr_info("ISAR no self tst response\n"); - ret = -ETIME; - goto reterrflg; - } - if ((isar->cmsb == ISAR_CTRL_STST) && (isar->clsb == 1) - && (isar->buf[0] == 0)) - pr_debug("%s: ISAR selftest OK\n", isar->name); - else { - pr_info("ISAR selftest not OK %x/%x/%x\n", - isar->cmsb, isar->clsb, isar->buf[0]); - ret = -EIO; - goto reterrflg; - } - spin_lock_irqsave(isar->hwlock, flags); - isar->iis = 0; - if (!send_mbox(isar, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) { - pr_info("ISAR RQST SVN failed\n"); - ret = -ETIME; - goto reterror; - } - spin_unlock_irqrestore(isar->hwlock, flags); - cnt = 30000; /* max 300 ms */ - while ((isar->iis != ISAR_IIS_DIAG) && cnt) { - udelay(10); - cnt--; - } - mdelay(1); - if (!cnt) { - pr_info("ISAR no SVN response\n"); - ret = -ETIME; - goto reterrflg; - } else { - if ((isar->cmsb == ISAR_CTRL_SWVER) && (isar->clsb == 1)) { - pr_notice("%s: ISAR software version %#x\n", - isar->name, isar->buf[0]); - } else { - pr_info("%s: ISAR wrong swver response (%x,%x)" - " cnt(%d)\n", isar->name, isar->cmsb, - isar->clsb, cnt); - ret = -EIO; - goto reterrflg; - } - } - spin_lock_irqsave(isar->hwlock, flags); - isar_setup(isar); - spin_unlock_irqrestore(isar->hwlock, flags); - ret = 0; -reterrflg: - spin_lock_irqsave(isar->hwlock, flags); -reterror: - isar->ch[0].bch.debug = saved_debug; - if (ret) - /* disable ISAR IRQ */ - isar->write_reg(isar->hw, ISAR_IRQBIT, 0); - spin_unlock_irqrestore(isar->hwlock, flags); - return ret; -} - -static inline void -deliver_status(struct isar_ch *ch, int status) -{ - pr_debug("%s: HL->LL FAXIND %x\n", ch->is->name, status); - _queue_data(&ch->bch.ch, PH_CONTROL_IND, status, 0, NULL, GFP_ATOMIC); -} - -static inline void -isar_rcv_frame(struct isar_ch *ch) -{ - u8 *ptr; - - if (!ch->is->clsb) { - pr_debug("%s; ISAR zero len frame\n", ch->is->name); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - return; - } - switch (ch->bch.state) { - case ISDN_P_NONE: - pr_debug("%s: ISAR protocol 0 spurious IIS_RDATA %x/%x/%x\n", - ch->is->name, ch->is->iis, ch->is->cmsb, ch->is->clsb); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - break; - case ISDN_P_B_RAW: - case ISDN_P_B_L2DTMF: - case ISDN_P_B_MODEM_ASYNC: - if (!ch->bch.rx_skb) { - ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen, - GFP_ATOMIC); - if (unlikely(!ch->bch.rx_skb)) { - pr_info("%s: B receive out of memory\n", - ch->is->name); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - break; - } - } - rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb)); - recv_Bchannel(&ch->bch, 0); - break; - case ISDN_P_B_HDLC: - if (!ch->bch.rx_skb) { - ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen, - GFP_ATOMIC); - if (unlikely(!ch->bch.rx_skb)) { - pr_info("%s: B receive out of memory\n", - ch->is->name); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - break; - } - } - if ((ch->bch.rx_skb->len + ch->is->clsb) > - (ch->bch.maxlen + 2)) { - pr_debug("%s: incoming packet too large\n", - ch->is->name); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - skb_trim(ch->bch.rx_skb, 0); - break; - } - if (ch->is->cmsb & HDLC_ERROR) { - pr_debug("%s: ISAR frame error %x len %d\n", - ch->is->name, ch->is->cmsb, ch->is->clsb); -#ifdef ERROR_STATISTIC - if (ch->is->cmsb & HDLC_ERR_RER) - ch->bch.err_inv++; - if (ch->is->cmsb & HDLC_ERR_CER) - ch->bch.err_crc++; -#endif - skb_trim(ch->bch.rx_skb, 0); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - break; - } - if (ch->is->cmsb & HDLC_FSD) - skb_trim(ch->bch.rx_skb, 0); - ptr = skb_put(ch->bch.rx_skb, ch->is->clsb); - rcv_mbox(ch->is, ptr); - if (ch->is->cmsb & HDLC_FED) { - if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */ - pr_debug("%s: ISAR frame to short %d\n", - ch->is->name, ch->bch.rx_skb->len); - skb_trim(ch->bch.rx_skb, 0); - break; - } - skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); - recv_Bchannel(&ch->bch, 0); - } - break; - case ISDN_P_B_T30_FAX: - if (ch->state != STFAX_ACTIV) { - pr_debug("%s: isar_rcv_frame: not ACTIV\n", - ch->is->name); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - if (ch->bch.rx_skb) - skb_trim(ch->bch.rx_skb, 0); - break; - } - if (!ch->bch.rx_skb) { - ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen, - GFP_ATOMIC); - if (unlikely(!ch->bch.rx_skb)) { - pr_info("%s: B receive out of memory\n", - __func__); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - break; - } - } - if (ch->cmd == PCTRL_CMD_FRM) { - rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb)); - pr_debug("%s: isar_rcv_frame: %d\n", - ch->is->name, ch->bch.rx_skb->len); - if (ch->is->cmsb & SART_NMD) { /* ABORT */ - pr_debug("%s: isar_rcv_frame: no more data\n", - ch->is->name); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - send_mbox(ch->is, SET_DPS(ch->dpath) | - ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, - 0, NULL); - ch->state = STFAX_ESCAPE; - /* set_skb_flag(skb, DF_NOMOREDATA); */ - } - recv_Bchannel(&ch->bch, 0); - if (ch->is->cmsb & SART_NMD) - deliver_status(ch, HW_MOD_NOCARR); - break; - } - if (ch->cmd != PCTRL_CMD_FRH) { - pr_debug("%s: isar_rcv_frame: unknown fax mode %x\n", - ch->is->name, ch->cmd); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - if (ch->bch.rx_skb) - skb_trim(ch->bch.rx_skb, 0); - break; - } - /* PCTRL_CMD_FRH */ - if ((ch->bch.rx_skb->len + ch->is->clsb) > - (ch->bch.maxlen + 2)) { - pr_info("%s: %s incoming packet too large\n", - ch->is->name, __func__); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - skb_trim(ch->bch.rx_skb, 0); - break; - } else if (ch->is->cmsb & HDLC_ERROR) { - pr_info("%s: ISAR frame error %x len %d\n", - ch->is->name, ch->is->cmsb, ch->is->clsb); - skb_trim(ch->bch.rx_skb, 0); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - break; - } - if (ch->is->cmsb & HDLC_FSD) - skb_trim(ch->bch.rx_skb, 0); - ptr = skb_put(ch->bch.rx_skb, ch->is->clsb); - rcv_mbox(ch->is, ptr); - if (ch->is->cmsb & HDLC_FED) { - if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */ - pr_info("%s: ISAR frame to short %d\n", - ch->is->name, ch->bch.rx_skb->len); - skb_trim(ch->bch.rx_skb, 0); - break; - } - skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); - recv_Bchannel(&ch->bch, 0); - } - if (ch->is->cmsb & SART_NMD) { /* ABORT */ - pr_debug("%s: isar_rcv_frame: no more data\n", - ch->is->name); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - if (ch->bch.rx_skb) - skb_trim(ch->bch.rx_skb, 0); - send_mbox(ch->is, SET_DPS(ch->dpath) | - ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); - ch->state = STFAX_ESCAPE; - deliver_status(ch, HW_MOD_NOCARR); - } - break; - default: - pr_info("isar_rcv_frame protocol (%x)error\n", ch->bch.state); - ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); - break; - } -} - -static void -isar_fill_fifo(struct isar_ch *ch) -{ - int count; - u8 msb; - u8 *ptr; - - pr_debug("%s: ch%d tx_skb %p tx_idx %d\n", - ch->is->name, ch->bch.nr, ch->bch.tx_skb, ch->bch.tx_idx); - if (!ch->bch.tx_skb) - return; - count = ch->bch.tx_skb->len - ch->bch.tx_idx; - if (count <= 0) - return; - if (!(ch->is->bstat & - (ch->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) - return; - if (count > ch->mml) { - msb = 0; - count = ch->mml; - } else { - msb = HDLC_FED; - } - ptr = ch->bch.tx_skb->data + ch->bch.tx_idx; - if (!ch->bch.tx_idx) { - pr_debug("%s: frame start\n", ch->is->name); - if ((ch->bch.state == ISDN_P_B_T30_FAX) && - (ch->cmd == PCTRL_CMD_FTH)) { - if (count > 1) { - if ((ptr[0] == 0xff) && (ptr[1] == 0x13)) { - /* last frame */ - test_and_set_bit(FLG_LASTDATA, - &ch->bch.Flags); - pr_debug("%s: set LASTDATA\n", - ch->is->name); - if (msb == HDLC_FED) - test_and_set_bit(FLG_DLEETX, - &ch->bch.Flags); - } - } - } - msb |= HDLC_FST; - } - ch->bch.tx_idx += count; - switch (ch->bch.state) { - case ISDN_P_NONE: - pr_info("%s: wrong protocol 0\n", __func__); - break; - case ISDN_P_B_RAW: - case ISDN_P_B_L2DTMF: - case ISDN_P_B_MODEM_ASYNC: - send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, - 0, count, ptr); - break; - case ISDN_P_B_HDLC: - send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, - msb, count, ptr); - break; - case ISDN_P_B_T30_FAX: - if (ch->state != STFAX_ACTIV) - pr_debug("%s: not ACTIV\n", ch->is->name); - else if (ch->cmd == PCTRL_CMD_FTH) - send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, - msb, count, ptr); - else if (ch->cmd == PCTRL_CMD_FTM) - send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, - 0, count, ptr); - else - pr_debug("%s: not FTH/FTM\n", ch->is->name); - break; - default: - pr_info("%s: protocol(%x) error\n", - __func__, ch->bch.state); - break; - } -} - -static inline struct isar_ch * -sel_bch_isar(struct isar_hw *isar, u8 dpath) -{ - struct isar_ch *base = &isar->ch[0]; - - if ((!dpath) || (dpath > 2)) - return NULL; - if (base->dpath == dpath) - return base; - base++; - if (base->dpath == dpath) - return base; - return NULL; -} - -static void -send_next(struct isar_ch *ch) -{ - pr_debug("%s: %s ch%d tx_skb %p tx_idx %d\n", - ch->is->name, __func__, ch->bch.nr, - ch->bch.tx_skb, ch->bch.tx_idx); - if (ch->bch.state == ISDN_P_B_T30_FAX) { - if (ch->cmd == PCTRL_CMD_FTH) { - if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) { - pr_debug("set NMD_DATA\n"); - test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); - } - } else if (ch->cmd == PCTRL_CMD_FTM) { - if (test_bit(FLG_DLEETX, &ch->bch.Flags)) { - test_and_set_bit(FLG_LASTDATA, &ch->bch.Flags); - test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); - } - } - } - if (ch->bch.tx_skb) { - /* send confirm, on trans, free on hdlc. */ - if (test_bit(FLG_TRANSPARENT, &ch->bch.Flags)) - confirm_Bsend(&ch->bch); - dev_kfree_skb(ch->bch.tx_skb); - } - if (get_next_bframe(&ch->bch)) - isar_fill_fifo(ch); - else { - if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) { - if (test_and_clear_bit(FLG_LASTDATA, - &ch->bch.Flags)) { - if (test_and_clear_bit(FLG_NMD_DATA, - &ch->bch.Flags)) { - u8 zd = 0; - send_mbox(ch->is, SET_DPS(ch->dpath) | - ISAR_HIS_SDATA, 0x01, 1, &zd); - } - test_and_set_bit(FLG_LL_OK, &ch->bch.Flags); - } else { - deliver_status(ch, HW_MOD_CONNECT); - } - } - } -} - -static void -check_send(struct isar_hw *isar, u8 rdm) -{ - struct isar_ch *ch; - - pr_debug("%s: rdm %x\n", isar->name, rdm); - if (rdm & BSTAT_RDM1) { - ch = sel_bch_isar(isar, 1); - if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) { - if (ch->bch.tx_skb && (ch->bch.tx_skb->len > - ch->bch.tx_idx)) - isar_fill_fifo(ch); - else - send_next(ch); - } - } - if (rdm & BSTAT_RDM2) { - ch = sel_bch_isar(isar, 2); - if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) { - if (ch->bch.tx_skb && (ch->bch.tx_skb->len > - ch->bch.tx_idx)) - isar_fill_fifo(ch); - else - send_next(ch); - } - } -} - -const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4", - "300", "600", "1200", "2400", "4800", "7200", - "9600nt", "9600t", "12000", "14400", "WRONG"}; -const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21", - "Bell103", "V23", "Bell202", "V17", "V29", "V27ter"}; - -static void -isar_pump_status_rsp(struct isar_ch *ch) { - u8 ril = ch->is->buf[0]; - u8 rim; - - if (!test_and_clear_bit(ISAR_RATE_REQ, &ch->is->Flags)) - return; - if (ril > 14) { - pr_info("%s: wrong pstrsp ril=%d\n", ch->is->name, ril); - ril = 15; - } - switch (ch->is->buf[1]) { - case 0: - rim = 0; - break; - case 0x20: - rim = 2; - break; - case 0x40: - rim = 3; - break; - case 0x41: - rim = 4; - break; - case 0x51: - rim = 5; - break; - case 0x61: - rim = 6; - break; - case 0x71: - rim = 7; - break; - case 0x82: - rim = 8; - break; - case 0x92: - rim = 9; - break; - case 0xa2: - rim = 10; - break; - default: - rim = 1; - break; - } - sprintf(ch->conmsg, "%s %s", dmril[ril], dmrim[rim]); - pr_debug("%s: pump strsp %s\n", ch->is->name, ch->conmsg); -} - -static void -isar_pump_statev_modem(struct isar_ch *ch, u8 devt) { - u8 dps = SET_DPS(ch->dpath); - - switch (devt) { - case PSEV_10MS_TIMER: - pr_debug("%s: pump stev TIMER\n", ch->is->name); - break; - case PSEV_CON_ON: - pr_debug("%s: pump stev CONNECT\n", ch->is->name); - deliver_status(ch, HW_MOD_CONNECT); - break; - case PSEV_CON_OFF: - pr_debug("%s: pump stev NO CONNECT\n", ch->is->name); - send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); - deliver_status(ch, HW_MOD_NOCARR); - break; - case PSEV_V24_OFF: - pr_debug("%s: pump stev V24 OFF\n", ch->is->name); - break; - case PSEV_CTS_ON: - pr_debug("%s: pump stev CTS ON\n", ch->is->name); - break; - case PSEV_CTS_OFF: - pr_debug("%s pump stev CTS OFF\n", ch->is->name); - break; - case PSEV_DCD_ON: - pr_debug("%s: pump stev CARRIER ON\n", ch->is->name); - test_and_set_bit(ISAR_RATE_REQ, &ch->is->Flags); - send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); - break; - case PSEV_DCD_OFF: - pr_debug("%s: pump stev CARRIER OFF\n", ch->is->name); - break; - case PSEV_DSR_ON: - pr_debug("%s: pump stev DSR ON\n", ch->is->name); - break; - case PSEV_DSR_OFF: - pr_debug("%s: pump stev DSR_OFF\n", ch->is->name); - break; - case PSEV_REM_RET: - pr_debug("%s: pump stev REMOTE RETRAIN\n", ch->is->name); - break; - case PSEV_REM_REN: - pr_debug("%s: pump stev REMOTE RENEGOTIATE\n", ch->is->name); - break; - case PSEV_GSTN_CLR: - pr_debug("%s: pump stev GSTN CLEAR\n", ch->is->name); - break; - default: - pr_info("u%s: nknown pump stev %x\n", ch->is->name, devt); - break; - } -} - -static void -isar_pump_statev_fax(struct isar_ch *ch, u8 devt) { - u8 dps = SET_DPS(ch->dpath); - u8 p1; - - switch (devt) { - case PSEV_10MS_TIMER: - pr_debug("%s: pump stev TIMER\n", ch->is->name); - break; - case PSEV_RSP_READY: - pr_debug("%s: pump stev RSP_READY\n", ch->is->name); - ch->state = STFAX_READY; - deliver_status(ch, HW_MOD_READY); -#ifdef AUTOCON - if (test_bit(BC_FLG_ORIG, &ch->bch.Flags)) - isar_pump_cmd(bch, HW_MOD_FRH, 3); - else - isar_pump_cmd(bch, HW_MOD_FTH, 3); -#endif - break; - case PSEV_LINE_TX_H: - if (ch->state == STFAX_LINE) { - pr_debug("%s: pump stev LINE_TX_H\n", ch->is->name); - ch->state = STFAX_CONT; - send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, - PCTRL_CMD_CONT, 0, NULL); - } else { - pr_debug("%s: pump stev LINE_TX_H wrong st %x\n", - ch->is->name, ch->state); - } - break; - case PSEV_LINE_RX_H: - if (ch->state == STFAX_LINE) { - pr_debug("%s: pump stev LINE_RX_H\n", ch->is->name); - ch->state = STFAX_CONT; - send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, - PCTRL_CMD_CONT, 0, NULL); - } else { - pr_debug("%s: pump stev LINE_RX_H wrong st %x\n", - ch->is->name, ch->state); - } - break; - case PSEV_LINE_TX_B: - if (ch->state == STFAX_LINE) { - pr_debug("%s: pump stev LINE_TX_B\n", ch->is->name); - ch->state = STFAX_CONT; - send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, - PCTRL_CMD_CONT, 0, NULL); - } else { - pr_debug("%s: pump stev LINE_TX_B wrong st %x\n", - ch->is->name, ch->state); - } - break; - case PSEV_LINE_RX_B: - if (ch->state == STFAX_LINE) { - pr_debug("%s: pump stev LINE_RX_B\n", ch->is->name); - ch->state = STFAX_CONT; - send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, - PCTRL_CMD_CONT, 0, NULL); - } else { - pr_debug("%s: pump stev LINE_RX_B wrong st %x\n", - ch->is->name, ch->state); - } - break; - case PSEV_RSP_CONN: - if (ch->state == STFAX_CONT) { - pr_debug("%s: pump stev RSP_CONN\n", ch->is->name); - ch->state = STFAX_ACTIV; - test_and_set_bit(ISAR_RATE_REQ, &ch->is->Flags); - send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); - if (ch->cmd == PCTRL_CMD_FTH) { - int delay = (ch->mod == 3) ? 1000 : 200; - /* 1s (200 ms) Flags before data */ - if (test_and_set_bit(FLG_FTI_RUN, - &ch->bch.Flags)) - del_timer(&ch->ftimer); - ch->ftimer.expires = - jiffies + ((delay * HZ)/1000); - test_and_set_bit(FLG_LL_CONN, - &ch->bch.Flags); - add_timer(&ch->ftimer); - } else { - deliver_status(ch, HW_MOD_CONNECT); - } - } else { - pr_debug("%s: pump stev RSP_CONN wrong st %x\n", - ch->is->name, ch->state); - } - break; - case PSEV_FLAGS_DET: - pr_debug("%s: pump stev FLAGS_DET\n", ch->is->name); - break; - case PSEV_RSP_DISC: - pr_debug("%s: pump stev RSP_DISC state(%d)\n", - ch->is->name, ch->state); - if (ch->state == STFAX_ESCAPE) { - p1 = 5; - switch (ch->newcmd) { - case 0: - ch->state = STFAX_READY; - break; - case PCTRL_CMD_FTM: - p1 = 2; - case PCTRL_CMD_FTH: - send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, - PCTRL_CMD_SILON, 1, &p1); - ch->state = STFAX_SILDET; - break; - case PCTRL_CMD_FRH: - case PCTRL_CMD_FRM: - ch->mod = ch->newmod; - p1 = ch->newmod; - ch->newmod = 0; - ch->cmd = ch->newcmd; - ch->newcmd = 0; - send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, - ch->cmd, 1, &p1); - ch->state = STFAX_LINE; - ch->try_mod = 3; - break; - default: - pr_debug("%s: RSP_DISC unknown newcmd %x\n", - ch->is->name, ch->newcmd); - break; - } - } else if (ch->state == STFAX_ACTIV) { - if (test_and_clear_bit(FLG_LL_OK, &ch->bch.Flags)) - deliver_status(ch, HW_MOD_OK); - else if (ch->cmd == PCTRL_CMD_FRM) - deliver_status(ch, HW_MOD_NOCARR); - else - deliver_status(ch, HW_MOD_FCERROR); - ch->state = STFAX_READY; - } else if (ch->state != STFAX_SILDET) { - /* ignore in STFAX_SILDET */ - ch->state = STFAX_READY; - deliver_status(ch, HW_MOD_FCERROR); - } - break; - case PSEV_RSP_SILDET: - pr_debug("%s: pump stev RSP_SILDET\n", ch->is->name); - if (ch->state == STFAX_SILDET) { - ch->mod = ch->newmod; - p1 = ch->newmod; - ch->newmod = 0; - ch->cmd = ch->newcmd; - ch->newcmd = 0; - send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, - ch->cmd, 1, &p1); - ch->state = STFAX_LINE; - ch->try_mod = 3; - } - break; - case PSEV_RSP_SILOFF: - pr_debug("%s: pump stev RSP_SILOFF\n", ch->is->name); - break; - case PSEV_RSP_FCERR: - if (ch->state == STFAX_LINE) { - pr_debug("%s: pump stev RSP_FCERR try %d\n", - ch->is->name, ch->try_mod); - if (ch->try_mod--) { - send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, - ch->cmd, 1, &ch->mod); - break; - } - } - pr_debug("%s: pump stev RSP_FCERR\n", ch->is->name); - ch->state = STFAX_ESCAPE; - send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, - 0, NULL); - deliver_status(ch, HW_MOD_FCERROR); - break; - default: - break; - } -} - -void -mISDNisar_irq(struct isar_hw *isar) -{ - struct isar_ch *ch; - - get_irq_infos(isar); - switch (isar->iis & ISAR_IIS_MSCMSD) { - case ISAR_IIS_RDATA: - ch = sel_bch_isar(isar, isar->iis >> 6); - if (ch) - isar_rcv_frame(ch); - else { - pr_debug("%s: ISAR spurious IIS_RDATA %x/%x/%x\n", - isar->name, isar->iis, isar->cmsb, - isar->clsb); - isar->write_reg(isar->hw, ISAR_IIA, 0); - } - break; - case ISAR_IIS_GSTEV: - isar->write_reg(isar->hw, ISAR_IIA, 0); - isar->bstat |= isar->cmsb; - check_send(isar, isar->cmsb); - break; - case ISAR_IIS_BSTEV: -#ifdef ERROR_STATISTIC - ch = sel_bch_isar(isar, isar->iis >> 6); - if (ch) { - if (isar->cmsb == BSTEV_TBO) - ch->bch.err_tx++; - if (isar->cmsb == BSTEV_RBO) - ch->bch.err_rdo++; - } -#endif - pr_debug("%s: Buffer STEV dpath%d msb(%x)\n", - isar->name, isar->iis>>6, isar->cmsb); - isar->write_reg(isar->hw, ISAR_IIA, 0); - break; - case ISAR_IIS_PSTEV: - ch = sel_bch_isar(isar, isar->iis >> 6); - if (ch) { - rcv_mbox(isar, NULL); - if (ch->bch.state == ISDN_P_B_MODEM_ASYNC) - isar_pump_statev_modem(ch, isar->cmsb); - else if (ch->bch.state == ISDN_P_B_T30_FAX) - isar_pump_statev_fax(ch, isar->cmsb); - else if (ch->bch.state == ISDN_P_B_RAW) { - int tt; - tt = isar->cmsb | 0x30; - if (tt == 0x3e) - tt = '*'; - else if (tt == 0x3f) - tt = '#'; - else if (tt > '9') - tt += 7; - tt |= DTMF_TONE_VAL; - _queue_data(&ch->bch.ch, PH_CONTROL_IND, - MISDN_ID_ANY, sizeof(tt), &tt, - GFP_ATOMIC); - } else - pr_debug("%s: ISAR IIS_PSTEV pm %d sta %x\n", - isar->name, ch->bch.state, - isar->cmsb); - } else { - pr_debug("%s: ISAR spurious IIS_PSTEV %x/%x/%x\n", - isar->name, isar->iis, isar->cmsb, - isar->clsb); - isar->write_reg(isar->hw, ISAR_IIA, 0); - } - break; - case ISAR_IIS_PSTRSP: - ch = sel_bch_isar(isar, isar->iis >> 6); - if (ch) { - rcv_mbox(isar, NULL); - isar_pump_status_rsp(ch); - } else { - pr_debug("%s: ISAR spurious IIS_PSTRSP %x/%x/%x\n", - isar->name, isar->iis, isar->cmsb, - isar->clsb); - isar->write_reg(isar->hw, ISAR_IIA, 0); - } - break; - case ISAR_IIS_DIAG: - case ISAR_IIS_BSTRSP: - case ISAR_IIS_IOM2RSP: - rcv_mbox(isar, NULL); - break; - case ISAR_IIS_INVMSG: - rcv_mbox(isar, NULL); - pr_debug("%s: invalid msg his:%x\n", isar->name, isar->cmsb); - break; - default: - rcv_mbox(isar, NULL); - pr_debug("%s: unhandled msg iis(%x) ctrl(%x/%x)\n", - isar->name, isar->iis, isar->cmsb, isar->clsb); - break; - } -} -EXPORT_SYMBOL(mISDNisar_irq); - -static void -ftimer_handler(unsigned long data) -{ - struct isar_ch *ch = (struct isar_ch *)data; - - pr_debug("%s: ftimer flags %lx\n", ch->is->name, ch->bch.Flags); - test_and_clear_bit(FLG_FTI_RUN, &ch->bch.Flags); - if (test_and_clear_bit(FLG_LL_CONN, &ch->bch.Flags)) - deliver_status(ch, HW_MOD_CONNECT); -} - -static void -setup_pump(struct isar_ch *ch) { - u8 dps = SET_DPS(ch->dpath); - u8 ctrl, param[6]; - - switch (ch->bch.state) { - case ISDN_P_NONE: - case ISDN_P_B_RAW: - case ISDN_P_B_HDLC: - send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL); - break; - case ISDN_P_B_L2DTMF: - if (test_bit(FLG_DTMFSEND, &ch->bch.Flags)) { - param[0] = 5; /* TOA 5 db */ - send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, - PMOD_DTMF_TRANS, 1, param); - } else { - param[0] = 40; /* REL -46 dbm */ - send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, - PMOD_DTMF, 1, param); - } - case ISDN_P_B_MODEM_ASYNC: - ctrl = PMOD_DATAMODEM; - if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) { - ctrl |= PCTRL_ORIG; - param[5] = PV32P6_CTN; - } else { - param[5] = PV32P6_ATN; - } - param[0] = 6; /* 6 db */ - param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B | - PV32P2_V22C | PV32P2_V21 | PV32P2_BEL; - param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B; - param[3] = PV32P4_UT144; - param[4] = PV32P5_UT144; - send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param); - break; - case ISDN_P_B_T30_FAX: - ctrl = PMOD_FAX; - if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) { - ctrl |= PCTRL_ORIG; - param[1] = PFAXP2_CTN; - } else { - param[1] = PFAXP2_ATN; - } - param[0] = 6; /* 6 db */ - send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param); - ch->state = STFAX_NULL; - ch->newcmd = 0; - ch->newmod = 0; - test_and_set_bit(FLG_FTI_RUN, &ch->bch.Flags); - break; - } - udelay(1000); - send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); - udelay(1000); -} - -static void -setup_sart(struct isar_ch *ch) { - u8 dps = SET_DPS(ch->dpath); - u8 ctrl, param[2] = {0, 0}; - - switch (ch->bch.state) { - case ISDN_P_NONE: - send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, - 0, NULL); - break; - case ISDN_P_B_RAW: - case ISDN_P_B_L2DTMF: - send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, - 2, param); - break; - case ISDN_P_B_HDLC: - case ISDN_P_B_T30_FAX: - send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, - 1, param); - break; - case ISDN_P_B_MODEM_ASYNC: - ctrl = SMODE_V14 | SCTRL_HDMC_BOTH; - param[0] = S_P1_CHS_8; - param[1] = S_P2_BFT_DEF; - send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, ctrl, 2, param); - break; - } - udelay(1000); - send_mbox(ch->is, dps | ISAR_HIS_BSTREQ, 0, 0, NULL); - udelay(1000); -} - -static void -setup_iom2(struct isar_ch *ch) { - u8 dps = SET_DPS(ch->dpath); - u8 cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD, 0, 0, 0, 0}; - - if (ch->bch.nr == 2) { - msg[1] = 1; - msg[3] = 1; - } - switch (ch->bch.state) { - case ISDN_P_NONE: - cmsb = 0; - /* dummy slot */ - msg[1] = ch->dpath + 2; - msg[3] = ch->dpath + 2; - break; - case ISDN_P_B_RAW: - case ISDN_P_B_HDLC: - break; - case ISDN_P_B_MODEM_ASYNC: - case ISDN_P_B_T30_FAX: - cmsb |= IOM_CTRL_RCV; - case ISDN_P_B_L2DTMF: - if (test_bit(FLG_DTMFSEND, &ch->bch.Flags)) - cmsb |= IOM_CTRL_RCV; - cmsb |= IOM_CTRL_ALAW; - break; - } - send_mbox(ch->is, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg); - udelay(1000); - send_mbox(ch->is, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL); - udelay(1000); -} - -static int -modeisar(struct isar_ch *ch, u32 bprotocol) -{ - /* Here we are selecting the best datapath for requested protocol */ - if (ch->bch.state == ISDN_P_NONE) { /* New Setup */ - switch (bprotocol) { - case ISDN_P_NONE: /* init */ - if (!ch->dpath) - /* no init for dpath 0 */ - return 0; - test_and_clear_bit(FLG_HDLC, &ch->bch.Flags); - test_and_clear_bit(FLG_TRANSPARENT, &ch->bch.Flags); - break; - case ISDN_P_B_RAW: - case ISDN_P_B_HDLC: - /* best is datapath 2 */ - if (!test_and_set_bit(ISAR_DP2_USE, &ch->is->Flags)) - ch->dpath = 2; - else if (!test_and_set_bit(ISAR_DP1_USE, - &ch->is->Flags)) - ch->dpath = 1; - else { - pr_info("modeisar both pathes in use\n"); - return -EBUSY; - } - if (bprotocol == ISDN_P_B_HDLC) - test_and_set_bit(FLG_HDLC, &ch->bch.Flags); - else - test_and_set_bit(FLG_TRANSPARENT, - &ch->bch.Flags); - break; - case ISDN_P_B_MODEM_ASYNC: - case ISDN_P_B_T30_FAX: - case ISDN_P_B_L2DTMF: - /* only datapath 1 */ - if (!test_and_set_bit(ISAR_DP1_USE, &ch->is->Flags)) - ch->dpath = 1; - else { - pr_info("%s: ISAR modeisar analog functions" - "only with DP1\n", ch->is->name); - return -EBUSY; - } - break; - default: - pr_info("%s: protocol not known %x\n", ch->is->name, - bprotocol); - return -ENOPROTOOPT; - } - } - pr_debug("%s: ISAR ch%d dp%d protocol %x->%x\n", ch->is->name, - ch->bch.nr, ch->dpath, ch->bch.state, bprotocol); - ch->bch.state = bprotocol; - setup_pump(ch); - setup_iom2(ch); - setup_sart(ch); - if (ch->bch.state == ISDN_P_NONE) { - /* Clear resources */ - if (ch->dpath == 1) - test_and_clear_bit(ISAR_DP1_USE, &ch->is->Flags); - else if (ch->dpath == 2) - test_and_clear_bit(ISAR_DP2_USE, &ch->is->Flags); - ch->dpath = 0; - ch->is->ctrl(ch->is->hw, HW_DEACT_IND, ch->bch.nr); - } else - ch->is->ctrl(ch->is->hw, HW_ACTIVATE_IND, ch->bch.nr); - return 0; -} - -static void -isar_pump_cmd(struct isar_ch *ch, u32 cmd, u8 para) -{ - u8 dps = SET_DPS(ch->dpath); - u8 ctrl = 0, nom = 0, p1 = 0; - - pr_debug("%s: isar_pump_cmd %x/%x state(%x)\n", - ch->is->name, cmd, para, ch->bch.state); - switch (cmd) { - case HW_MOD_FTM: - if (ch->state == STFAX_READY) { - p1 = para; - ctrl = PCTRL_CMD_FTM; - nom = 1; - ch->state = STFAX_LINE; - ch->cmd = ctrl; - ch->mod = para; - ch->newmod = 0; - ch->newcmd = 0; - ch->try_mod = 3; - } else if ((ch->state == STFAX_ACTIV) && - (ch->cmd == PCTRL_CMD_FTM) && (ch->mod == para)) - deliver_status(ch, HW_MOD_CONNECT); - else { - ch->newmod = para; - ch->newcmd = PCTRL_CMD_FTM; - nom = 0; - ctrl = PCTRL_CMD_ESC; - ch->state = STFAX_ESCAPE; - } - break; - case HW_MOD_FTH: - if (ch->state == STFAX_READY) { - p1 = para; - ctrl = PCTRL_CMD_FTH; - nom = 1; - ch->state = STFAX_LINE; - ch->cmd = ctrl; - ch->mod = para; - ch->newmod = 0; - ch->newcmd = 0; - ch->try_mod = 3; - } else if ((ch->state == STFAX_ACTIV) && - (ch->cmd == PCTRL_CMD_FTH) && (ch->mod == para)) - deliver_status(ch, HW_MOD_CONNECT); - else { - ch->newmod = para; - ch->newcmd = PCTRL_CMD_FTH; - nom = 0; - ctrl = PCTRL_CMD_ESC; - ch->state = STFAX_ESCAPE; - } - break; - case HW_MOD_FRM: - if (ch->state == STFAX_READY) { - p1 = para; - ctrl = PCTRL_CMD_FRM; - nom = 1; - ch->state = STFAX_LINE; - ch->cmd = ctrl; - ch->mod = para; - ch->newmod = 0; - ch->newcmd = 0; - ch->try_mod = 3; - } else if ((ch->state == STFAX_ACTIV) && - (ch->cmd == PCTRL_CMD_FRM) && (ch->mod == para)) - deliver_status(ch, HW_MOD_CONNECT); - else { - ch->newmod = para; - ch->newcmd = PCTRL_CMD_FRM; - nom = 0; - ctrl = PCTRL_CMD_ESC; - ch->state = STFAX_ESCAPE; - } - break; - case HW_MOD_FRH: - if (ch->state == STFAX_READY) { - p1 = para; - ctrl = PCTRL_CMD_FRH; - nom = 1; - ch->state = STFAX_LINE; - ch->cmd = ctrl; - ch->mod = para; - ch->newmod = 0; - ch->newcmd = 0; - ch->try_mod = 3; - } else if ((ch->state == STFAX_ACTIV) && - (ch->cmd == PCTRL_CMD_FRH) && (ch->mod == para)) - deliver_status(ch, HW_MOD_CONNECT); - else { - ch->newmod = para; - ch->newcmd = PCTRL_CMD_FRH; - nom = 0; - ctrl = PCTRL_CMD_ESC; - ch->state = STFAX_ESCAPE; - } - break; - case PCTRL_CMD_TDTMF: - p1 = para; - nom = 1; - ctrl = PCTRL_CMD_TDTMF; - break; - } - if (ctrl) - send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1); -} - -static void -isar_setup(struct isar_hw *isar) -{ - u8 msg; - int i; - - /* Dpath 1, 2 */ - msg = 61; - for (i = 0; i < 2; i++) { - /* Buffer Config */ - send_mbox(isar, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) | - ISAR_HIS_P12CFG, 4, 1, &msg); - isar->ch[i].mml = msg; - isar->ch[i].bch.state = 0; - isar->ch[i].dpath = i + 1; - modeisar(&isar->ch[i], ISDN_P_NONE); - } -} - -static int -isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb) -{ - struct bchannel *bch = container_of(ch, struct bchannel, ch); - struct isar_ch *ich = container_of(bch, struct isar_ch, bch); - int ret = -EINVAL; - struct mISDNhead *hh = mISDN_HEAD_P(skb); - u32 id, *val; - u_long flags; - - switch (hh->prim) { - case PH_DATA_REQ: - spin_lock_irqsave(ich->is->hwlock, flags); - ret = bchannel_senddata(bch, skb); - if (ret > 0) { /* direct TX */ - id = hh->id; /* skb can be freed */ - ret = 0; - isar_fill_fifo(ich); - spin_unlock_irqrestore(ich->is->hwlock, flags); - if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) - queue_ch_frame(ch, PH_DATA_CNF, id, NULL); - } else - spin_unlock_irqrestore(ich->is->hwlock, flags); - return ret; - case PH_ACTIVATE_REQ: - spin_lock_irqsave(ich->is->hwlock, flags); - if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) - ret = modeisar(ich, ch->protocol); - else - ret = 0; - spin_unlock_irqrestore(ich->is->hwlock, flags); - if (!ret) - _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, - NULL, GFP_KERNEL); - break; - case PH_DEACTIVATE_REQ: - spin_lock_irqsave(ich->is->hwlock, flags); - mISDN_clear_bchannel(bch); - modeisar(ich, ISDN_P_NONE); - spin_unlock_irqrestore(ich->is->hwlock, flags); - _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, - NULL, GFP_KERNEL); - ret = 0; - break; - case PH_CONTROL_REQ: - val = (u32 *)skb->data; - pr_debug("%s: PH_CONTROL | REQUEST %x/%x\n", ich->is->name, - hh->id, *val); - if ((hh->id == 0) && ((*val & ~DTMF_TONE_MASK) == - DTMF_TONE_VAL)) { - if (bch->state == ISDN_P_B_L2DTMF) { - char tt = *val & DTMF_TONE_MASK; - - if (tt == '*') - tt = 0x1e; - else if (tt == '#') - tt = 0x1f; - else if (tt > '9') - tt -= 7; - tt &= 0x1f; - spin_lock_irqsave(ich->is->hwlock, flags); - isar_pump_cmd(ich, PCTRL_CMD_TDTMF, tt); - spin_unlock_irqrestore(ich->is->hwlock, flags); - } else { - pr_info("%s: DTMF send wrong protocol %x\n", - __func__, bch->state); - return -EINVAL; - } - } else if ((hh->id == HW_MOD_FRM) || (hh->id == HW_MOD_FRH) || - (hh->id == HW_MOD_FTM) || (hh->id == HW_MOD_FTH)) { - for (id = 0; id < FAXMODCNT; id++) - if (faxmodulation[id] == *val) - break; - if ((FAXMODCNT > id) && - test_bit(FLG_INITIALIZED, &bch->Flags)) { - pr_debug("%s: isar: new mod\n", ich->is->name); - isar_pump_cmd(ich, hh->id, *val); - ret = 0; - } else { - pr_info("%s: wrong modulation\n", - ich->is->name); - ret = -EINVAL; - } - } else if (hh->id == HW_MOD_LASTDATA) - test_and_set_bit(FLG_DLEETX, &bch->Flags); - else { - pr_info("%s: unknown PH_CONTROL_REQ %x\n", - ich->is->name, hh->id); - ret = -EINVAL; - } - default: - pr_info("%s: %s unknown prim(%x,%x)\n", - ich->is->name, __func__, hh->prim, hh->id); - ret = -EINVAL; - } - if (!ret) - dev_kfree_skb(skb); - return ret; -} - -static int -channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) -{ - int ret = 0; - - switch (cq->op) { - case MISDN_CTRL_GETOP: - cq->op = 0; - break; - /* Nothing implemented yet */ - case MISDN_CTRL_FILL_EMPTY: - default: - pr_info("%s: unknown Op %x\n", __func__, cq->op); - ret = -EINVAL; - break; - } - return ret; -} - -static int -isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) -{ - struct bchannel *bch = container_of(ch, struct bchannel, ch); - struct isar_ch *ich = container_of(bch, struct isar_ch, bch); - int ret = -EINVAL; - u_long flags; - - pr_debug("%s: %s cmd:%x %p\n", ich->is->name, __func__, cmd, arg); - switch (cmd) { - case CLOSE_CHANNEL: - test_and_clear_bit(FLG_OPEN, &bch->Flags); - if (test_bit(FLG_ACTIVE, &bch->Flags)) { - spin_lock_irqsave(ich->is->hwlock, flags); - mISDN_freebchannel(bch); - modeisar(ich, ISDN_P_NONE); - spin_unlock_irqrestore(ich->is->hwlock, flags); - } else { - skb_queue_purge(&bch->rqueue); - bch->rcount = 0; - } - ch->protocol = ISDN_P_NONE; - ch->peer = NULL; - module_put(ich->is->owner); - ret = 0; - break; - case CONTROL_CHANNEL: - ret = channel_bctrl(bch, arg); - break; - default: - pr_info("%s: %s unknown prim(%x)\n", - ich->is->name, __func__, cmd); - } - return ret; -} - -static void -free_isar(struct isar_hw *isar) -{ - modeisar(&isar->ch[0], ISDN_P_NONE); - modeisar(&isar->ch[1], ISDN_P_NONE); - del_timer(&isar->ch[0].ftimer); - del_timer(&isar->ch[1].ftimer); - test_and_clear_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags); - test_and_clear_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags); -} - -static int -init_isar(struct isar_hw *isar) -{ - int cnt = 3; - - while (cnt--) { - isar->version = ISARVersion(isar); - if (isar->ch[0].bch.debug & DEBUG_HW) - pr_notice("%s: Testing version %d (%d time)\n", - isar->name, isar->version, 3 - cnt); - if (isar->version == 1) - break; - isar->ctrl(isar->hw, HW_RESET_REQ, 0); - } - if (isar->version != 1) - return -EINVAL; - isar->ch[0].ftimer.function = &ftimer_handler; - isar->ch[0].ftimer.data = (long)&isar->ch[0]; - init_timer(&isar->ch[0].ftimer); - test_and_set_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags); - isar->ch[1].ftimer.function = &ftimer_handler; - isar->ch[1].ftimer.data = (long)&isar->ch[1]; - init_timer(&isar->ch[1].ftimer); - test_and_set_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags); - return 0; -} - -static int -isar_open(struct isar_hw *isar, struct channel_req *rq) -{ - struct bchannel *bch; - - if (rq->adr.channel > 2) - return -EINVAL; - if (rq->protocol == ISDN_P_NONE) - return -EINVAL; - bch = &isar->ch[rq->adr.channel - 1].bch; - if (test_and_set_bit(FLG_OPEN, &bch->Flags)) - return -EBUSY; /* b-channel can be only open once */ - test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); - bch->ch.protocol = rq->protocol; - rq->ch = &bch->ch; - return 0; -} - -u32 -mISDNisar_init(struct isar_hw *isar, void *hw) -{ - u32 ret, i; - - isar->hw = hw; - for (i = 0; i < 2; i++) { - isar->ch[i].bch.nr = i + 1; - mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM); - isar->ch[i].bch.ch.nr = i + 1; - isar->ch[i].bch.ch.send = &isar_l2l1; - isar->ch[i].bch.ch.ctrl = isar_bctrl; - isar->ch[i].bch.hw = hw; - isar->ch[i].is = isar; - } - - isar->init = &init_isar; - isar->release = &free_isar; - isar->firmware = &load_firmware; - isar->open = &isar_open; - - ret = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | - (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)) | - (1 << (ISDN_P_B_L2DTMF & ISDN_P_B_MASK)) | - (1 << (ISDN_P_B_MODEM_ASYNC & ISDN_P_B_MASK)) | - (1 << (ISDN_P_B_T30_FAX & ISDN_P_B_MASK)); - - return ret; -} -EXPORT_SYMBOL(mISDNisar_init); - -static int isar_mod_init(void) -{ - pr_notice("mISDN: ISAR driver Rev. %s\n", ISAR_REV); - return 0; -} - -static void isar_mod_cleanup(void) -{ - pr_notice("mISDN: ISAR module unloaded\n"); -} -module_init(isar_mod_init); -module_exit(isar_mod_cleanup); diff --git a/trunk/drivers/isdn/hardware/mISDN/netjet.c b/trunk/drivers/isdn/hardware/mISDN/netjet.c deleted file mode 100644 index 6c1b164937a9..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/netjet.c +++ /dev/null @@ -1,1156 +0,0 @@ -/* - * NETJet mISDN driver - * - * Author Karsten Keil - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include "ipac.h" -#include "iohelper.h" -#include "netjet.h" -#include - -#define NETJET_REV "2.0" - -enum nj_types { - NETJET_S_TJ300, - NETJET_S_TJ320, - ENTERNOW__TJ320, -}; - -struct tiger_dma { - size_t size; - u32 *start; - int idx; - u32 dmastart; - u32 dmairq; - u32 dmaend; - u32 dmacur; -}; - -struct tiger_hw; - -struct tiger_ch { - struct bchannel bch; - struct tiger_hw *nj; - int idx; - int free; - int lastrx; - u16 rxstate; - u16 txstate; - struct isdnhdlc_vars hsend; - struct isdnhdlc_vars hrecv; - u8 *hsbuf; - u8 *hrbuf; -}; - -#define TX_INIT 0x0001 -#define TX_IDLE 0x0002 -#define TX_RUN 0x0004 -#define TX_UNDERRUN 0x0100 -#define RX_OVERRUN 0x0100 - -#define LOG_SIZE 64 - -struct tiger_hw { - struct list_head list; - struct pci_dev *pdev; - char name[MISDN_MAX_IDLEN]; - enum nj_types typ; - int irq; - u32 irqcnt; - u32 base; - size_t base_s; - dma_addr_t dma; - void *dma_p; - spinlock_t lock; /* lock HW */ - struct isac_hw isac; - struct tiger_dma send; - struct tiger_dma recv; - struct tiger_ch bc[2]; - u8 ctrlreg; - u8 dmactrl; - u8 auxd; - u8 last_is0; - u8 irqmask0; - char log[LOG_SIZE]; -}; - -static LIST_HEAD(Cards); -static DEFINE_RWLOCK(card_lock); /* protect Cards */ -static u32 debug; -static int nj_cnt; - -static void -_set_debug(struct tiger_hw *card) -{ - card->isac.dch.debug = debug; - card->bc[0].bch.debug = debug; - card->bc[1].bch.debug = debug; -} - -static int -set_debug(const char *val, struct kernel_param *kp) -{ - int ret; - struct tiger_hw *card; - - ret = param_set_uint(val, kp); - if (!ret) { - read_lock(&card_lock); - list_for_each_entry(card, &Cards, list) - _set_debug(card); - read_unlock(&card_lock); - } - return ret; -} - -MODULE_AUTHOR("Karsten Keil"); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(NETJET_REV); -module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Netjet debug mask"); - -static void -nj_disable_hwirq(struct tiger_hw *card) -{ - outb(0, card->base + NJ_IRQMASK0); - outb(0, card->base + NJ_IRQMASK1); -} - - -static u8 -ReadISAC_nj(void *p, u8 offset) -{ - struct tiger_hw *card = p; - u8 ret; - - card->auxd &= 0xfc; - card->auxd |= (offset >> 4) & 3; - outb(card->auxd, card->base + NJ_AUXDATA); - ret = inb(card->base + NJ_ISAC_OFF + ((offset & 0x0f) << 2)); - return ret; -} - -static void -WriteISAC_nj(void *p, u8 offset, u8 value) -{ - struct tiger_hw *card = p; - - card->auxd &= 0xfc; - card->auxd |= (offset >> 4) & 3; - outb(card->auxd, card->base + NJ_AUXDATA); - outb(value, card->base + NJ_ISAC_OFF + ((offset & 0x0f) << 2)); -} - -static void -ReadFiFoISAC_nj(void *p, u8 offset, u8 *data, int size) -{ - struct tiger_hw *card = p; - - card->auxd &= 0xfc; - outb(card->auxd, card->base + NJ_AUXDATA); - insb(card->base + NJ_ISAC_OFF, data, size); -} - -static void -WriteFiFoISAC_nj(void *p, u8 offset, u8 *data, int size) -{ - struct tiger_hw *card = p; - - card->auxd &= 0xfc; - outb(card->auxd, card->base + NJ_AUXDATA); - outsb(card->base + NJ_ISAC_OFF, data, size); -} - -static void -fill_mem(struct tiger_ch *bc, u32 idx, u32 cnt, u32 fill) -{ - struct tiger_hw *card = bc->bch.hw; - u32 mask = 0xff, val; - - pr_debug("%s: B%1d fill %02x len %d idx %d/%d\n", card->name, - bc->bch.nr, fill, cnt, idx, card->send.idx); - if (bc->bch.nr & 2) { - fill <<= 8; - mask <<= 8; - } - mask ^= 0xffffffff; - while (cnt--) { - val = card->send.start[idx]; - val &= mask; - val |= fill; - card->send.start[idx++] = val; - if (idx >= card->send.size) - idx = 0; - } -} - -static int -mode_tiger(struct tiger_ch *bc, u32 protocol) -{ - struct tiger_hw *card = bc->bch.hw; - - pr_debug("%s: B%1d protocol %x-->%x\n", card->name, - bc->bch.nr, bc->bch.state, protocol); - switch (protocol) { - case ISDN_P_NONE: - if (bc->bch.state == ISDN_P_NONE) - break; - fill_mem(bc, 0, card->send.size, 0xff); - bc->bch.state = protocol; - /* only stop dma and interrupts if both channels NULL */ - if ((card->bc[0].bch.state == ISDN_P_NONE) && - (card->bc[1].bch.state == ISDN_P_NONE)) { - card->dmactrl = 0; - outb(card->dmactrl, card->base + NJ_DMACTRL); - outb(0, card->base + NJ_IRQMASK0); - } - test_and_clear_bit(FLG_HDLC, &bc->bch.Flags); - test_and_clear_bit(FLG_TRANSPARENT, &bc->bch.Flags); - bc->txstate = 0; - bc->rxstate = 0; - bc->lastrx = -1; - break; - case ISDN_P_B_RAW: - test_and_set_bit(FLG_TRANSPARENT, &bc->bch.Flags); - bc->bch.state = protocol; - bc->idx = 0; - bc->free = card->send.size/2; - bc->rxstate = 0; - bc->txstate = TX_INIT | TX_IDLE; - bc->lastrx = -1; - if (!card->dmactrl) { - card->dmactrl = 1; - outb(card->dmactrl, card->base + NJ_DMACTRL); - outb(0x0f, card->base + NJ_IRQMASK0); - } - break; - case ISDN_P_B_HDLC: - test_and_set_bit(FLG_HDLC, &bc->bch.Flags); - bc->bch.state = protocol; - bc->idx = 0; - bc->free = card->send.size/2; - bc->rxstate = 0; - bc->txstate = TX_INIT | TX_IDLE; - isdnhdlc_rcv_init(&bc->hrecv, 0); - isdnhdlc_out_init(&bc->hsend, 0); - bc->lastrx = -1; - if (!card->dmactrl) { - card->dmactrl = 1; - outb(card->dmactrl, card->base + NJ_DMACTRL); - outb(0x0f, card->base + NJ_IRQMASK0); - } - break; - default: - pr_info("%s: %s protocol %x not handled\n", card->name, - __func__, protocol); - return -ENOPROTOOPT; - } - card->send.dmacur = inl(card->base + NJ_DMA_READ_ADR); - card->recv.dmacur = inl(card->base + NJ_DMA_WRITE_ADR); - card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2; - card->recv.idx = (card->recv.dmacur - card->recv.dmastart) >> 2; - pr_debug("%s: %s ctrl %x irq %02x/%02x idx %d/%d\n", - card->name, __func__, - inb(card->base + NJ_DMACTRL), - inb(card->base + NJ_IRQMASK0), - inb(card->base + NJ_IRQSTAT0), - card->send.idx, - card->recv.idx); - return 0; -} - -static void -nj_reset(struct tiger_hw *card) -{ - outb(0xff, card->base + NJ_CTRL); /* Reset On */ - mdelay(1); - - /* now edge triggered for TJ320 GE 13/07/00 */ - /* see comment in IRQ function */ - if (card->typ == NETJET_S_TJ320) /* TJ320 */ - card->ctrlreg = 0x40; /* Reset Off and status read clear */ - else - card->ctrlreg = 0x00; /* Reset Off and status read clear */ - outb(card->ctrlreg, card->base + NJ_CTRL); - mdelay(10); - - /* configure AUX pins (all output except ISAC IRQ pin) */ - card->auxd = 0; - card->dmactrl = 0; - outb(~NJ_ISACIRQ, card->base + NJ_AUXCTRL); - outb(NJ_ISACIRQ, card->base + NJ_IRQMASK1); - outb(card->auxd, card->base + NJ_AUXDATA); -} - -static int -inittiger(struct tiger_hw *card) -{ - int i; - - card->dma_p = pci_alloc_consistent(card->pdev, NJ_DMA_SIZE, - &card->dma); - if (!card->dma_p) { - pr_info("%s: No DMA memory\n", card->name); - return -ENOMEM; - } - if ((u64)card->dma > 0xffffffff) { - pr_info("%s: DMA outside 32 bit\n", card->name); - return -ENOMEM; - } - for (i = 0; i < 2; i++) { - card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_KERNEL); - if (!card->bc[i].hsbuf) { - pr_info("%s: no B%d send buffer\n", card->name, i + 1); - return -ENOMEM; - } - card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_KERNEL); - if (!card->bc[i].hrbuf) { - pr_info("%s: no B%d recv buffer\n", card->name, i + 1); - return -ENOMEM; - } - } - memset(card->dma_p, 0xff, NJ_DMA_SIZE); - - card->send.start = card->dma_p; - card->send.dmastart = (u32)card->dma; - card->send.dmaend = card->send.dmastart + - (4 * (NJ_DMA_TXSIZE - 1)); - card->send.dmairq = card->send.dmastart + - (4 * ((NJ_DMA_TXSIZE / 2) - 1)); - card->send.size = NJ_DMA_TXSIZE; - - if (debug & DEBUG_HW) - pr_notice("%s: send buffer phy %#x - %#x - %#x virt %p" - " size %zu u32\n", card->name, - card->send.dmastart, card->send.dmairq, - card->send.dmaend, card->send.start, card->send.size); - - outl(card->send.dmastart, card->base + NJ_DMA_READ_START); - outl(card->send.dmairq, card->base + NJ_DMA_READ_IRQ); - outl(card->send.dmaend, card->base + NJ_DMA_READ_END); - - card->recv.start = card->dma_p + (NJ_DMA_SIZE / 2); - card->recv.dmastart = (u32)card->dma + (NJ_DMA_SIZE / 2); - card->recv.dmaend = card->recv.dmastart + - (4 * (NJ_DMA_RXSIZE - 1)); - card->recv.dmairq = card->recv.dmastart + - (4 * ((NJ_DMA_RXSIZE / 2) - 1)); - card->recv.size = NJ_DMA_RXSIZE; - - if (debug & DEBUG_HW) - pr_notice("%s: recv buffer phy %#x - %#x - %#x virt %p" - " size %zu u32\n", card->name, - card->recv.dmastart, card->recv.dmairq, - card->recv.dmaend, card->recv.start, card->recv.size); - - outl(card->recv.dmastart, card->base + NJ_DMA_WRITE_START); - outl(card->recv.dmairq, card->base + NJ_DMA_WRITE_IRQ); - outl(card->recv.dmaend, card->base + NJ_DMA_WRITE_END); - return 0; -} - -static void -read_dma(struct tiger_ch *bc, u32 idx, int cnt) -{ - struct tiger_hw *card = bc->bch.hw; - int i, stat; - u32 val; - u8 *p, *pn; - - if (bc->lastrx == idx) { - bc->rxstate |= RX_OVERRUN; - pr_info("%s: B%1d overrun at idx %d\n", card->name, - bc->bch.nr, idx); - } - bc->lastrx = idx; - if (!bc->bch.rx_skb) { - bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen, GFP_ATOMIC); - if (!bc->bch.rx_skb) { - pr_info("%s: B%1d receive out of memory\n", - card->name, bc->bch.nr); - return; - } - } - - if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) { - if ((bc->bch.rx_skb->len + cnt) > bc->bch.maxlen) { - pr_debug("%s: B%1d overrun %d\n", card->name, - bc->bch.nr, bc->bch.rx_skb->len + cnt); - skb_trim(bc->bch.rx_skb, 0); - return; - } - p = skb_put(bc->bch.rx_skb, cnt); - } else - p = bc->hrbuf; - - for (i = 0; i < cnt; i++) { - val = card->recv.start[idx++]; - if (bc->bch.nr & 2) - val >>= 8; - if (idx >= card->recv.size) - idx = 0; - p[i] = val & 0xff; - } - pn = bc->hrbuf; -next_frame: - if (test_bit(FLG_HDLC, &bc->bch.Flags)) { - stat = isdnhdlc_decode(&bc->hrecv, pn, cnt, &i, - bc->bch.rx_skb->data, bc->bch.maxlen); - if (stat > 0) /* valid frame received */ - p = skb_put(bc->bch.rx_skb, stat); - else if (stat == -HDLC_CRC_ERROR) - pr_info("%s: B%1d receive frame CRC error\n", - card->name, bc->bch.nr); - else if (stat == -HDLC_FRAMING_ERROR) - pr_info("%s: B%1d receive framing error\n", - card->name, bc->bch.nr); - else if (stat == -HDLC_LENGTH_ERROR) - pr_info("%s: B%1d receive frame too long (> %d)\n", - card->name, bc->bch.nr, bc->bch.maxlen); - } else - stat = cnt; - - if (stat > 0) { - if (debug & DEBUG_HW_BFIFO) { - snprintf(card->log, LOG_SIZE, "B%1d-recv %s %d ", - bc->bch.nr, card->name, stat); - print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, - p, stat); - } - recv_Bchannel(&bc->bch, 0); - } - if (test_bit(FLG_HDLC, &bc->bch.Flags)) { - pn += i; - cnt -= i; - if (!bc->bch.rx_skb) { - bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen, - GFP_ATOMIC); - if (!bc->bch.rx_skb) { - pr_info("%s: B%1d receive out of memory\n", - card->name, bc->bch.nr); - return; - } - } - if (cnt > 0) - goto next_frame; - } -} - -static void -recv_tiger(struct tiger_hw *card, u8 irq_stat) -{ - u32 idx; - int cnt = card->recv.size / 2; - - /* Note receive is via the WRITE DMA channel */ - card->last_is0 &= ~NJ_IRQM0_WR_MASK; - card->last_is0 |= (irq_stat & NJ_IRQM0_WR_MASK); - - if (irq_stat & NJ_IRQM0_WR_END) - idx = cnt - 1; - else - idx = card->recv.size - 1; - - if (test_bit(FLG_ACTIVE, &card->bc[0].bch.Flags)) - read_dma(&card->bc[0], idx, cnt); - if (test_bit(FLG_ACTIVE, &card->bc[1].bch.Flags)) - read_dma(&card->bc[1], idx, cnt); -} - -/* sync with current DMA address at start or after exception */ -static void -resync(struct tiger_ch *bc, struct tiger_hw *card) -{ - card->send.dmacur = inl(card->base | NJ_DMA_READ_ADR); - card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2; - if (bc->free > card->send.size / 2) - bc->free = card->send.size / 2; - /* currently we simple sync to the next complete free area - * this hast the advantage that we have always maximum time to - * handle TX irq - */ - if (card->send.idx < ((card->send.size / 2) - 1)) - bc->idx = (card->recv.size / 2) - 1; - else - bc->idx = card->recv.size - 1; - bc->txstate = TX_RUN; - pr_debug("%s: %s B%1d free %d idx %d/%d\n", card->name, - __func__, bc->bch.nr, bc->free, bc->idx, card->send.idx); -} - -static int bc_next_frame(struct tiger_ch *); - -static void -fill_hdlc_flag(struct tiger_ch *bc) -{ - struct tiger_hw *card = bc->bch.hw; - int count, i; - u32 m, v; - u8 *p; - - if (bc->free == 0) - return; - pr_debug("%s: %s B%1d %d state %x idx %d/%d\n", card->name, - __func__, bc->bch.nr, bc->free, bc->txstate, - bc->idx, card->send.idx); - if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN)) - resync(bc, card); - count = isdnhdlc_encode(&bc->hsend, NULL, 0, &i, - bc->hsbuf, bc->free); - pr_debug("%s: B%1d hdlc encoded %d flags\n", card->name, - bc->bch.nr, count); - bc->free -= count; - p = bc->hsbuf; - m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff; - for (i = 0; i < count; i++) { - if (bc->idx >= card->send.size) - bc->idx = 0; - v = card->send.start[bc->idx]; - v &= m; - v |= (bc->bch.nr & 1) ? (u32)(p[i]) : ((u32)(p[i])) << 8; - card->send.start[bc->idx++] = v; - } - if (debug & DEBUG_HW_BFIFO) { - snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ", - bc->bch.nr, card->name, count); - print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, p, count); - } -} - -static void -fill_dma(struct tiger_ch *bc) -{ - struct tiger_hw *card = bc->bch.hw; - int count, i; - u32 m, v; - u8 *p; - - if (bc->free == 0) - return; - count = bc->bch.tx_skb->len - bc->bch.tx_idx; - if (count <= 0) - return; - pr_debug("%s: %s B%1d %d/%d/%d/%d state %x idx %d/%d\n", card->name, - __func__, bc->bch.nr, count, bc->free, bc->bch.tx_idx, - bc->bch.tx_skb->len, bc->txstate, bc->idx, card->send.idx); - if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN)) - resync(bc, card); - p = bc->bch.tx_skb->data + bc->bch.tx_idx; - if (test_bit(FLG_HDLC, &bc->bch.Flags)) { - count = isdnhdlc_encode(&bc->hsend, p, count, &i, - bc->hsbuf, bc->free); - pr_debug("%s: B%1d hdlc encoded %d in %d\n", card->name, - bc->bch.nr, i, count); - bc->bch.tx_idx += i; - bc->free -= count; - p = bc->hsbuf; - } else { - if (count > bc->free) - count = bc->free; - bc->bch.tx_idx += count; - bc->free -= count; - } - m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff; - for (i = 0; i < count; i++) { - if (bc->idx >= card->send.size) - bc->idx = 0; - v = card->send.start[bc->idx]; - v &= m; - v |= (bc->bch.nr & 1) ? (u32)(p[i]) : ((u32)(p[i])) << 8; - card->send.start[bc->idx++] = v; - } - if (debug & DEBUG_HW_BFIFO) { - snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ", - bc->bch.nr, card->name, count); - print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, p, count); - } - if (bc->free) - bc_next_frame(bc); -} - - -static int -bc_next_frame(struct tiger_ch *bc) -{ - if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) - fill_dma(bc); - else { - if (bc->bch.tx_skb) { - /* send confirm, on trans, free on hdlc. */ - if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) - confirm_Bsend(&bc->bch); - dev_kfree_skb(bc->bch.tx_skb); - } - if (get_next_bframe(&bc->bch)) - fill_dma(bc); - else - return 0; - } - return 1; -} - -static void -send_tiger_bc(struct tiger_hw *card, struct tiger_ch *bc) -{ - int ret; - - bc->free += card->send.size / 2; - if (bc->free >= card->send.size) { - if (!(bc->txstate & (TX_UNDERRUN | TX_INIT))) { - pr_info("%s: B%1d TX underrun state %x\n", card->name, - bc->bch.nr, bc->txstate); - bc->txstate |= TX_UNDERRUN; - } - bc->free = card->send.size; - } - ret = bc_next_frame(bc); - if (!ret) { - if (test_bit(FLG_HDLC, &bc->bch.Flags)) { - fill_hdlc_flag(bc); - return; - } - pr_debug("%s: B%1d TX no data free %d idx %d/%d\n", card->name, - bc->bch.nr, bc->free, bc->idx, card->send.idx); - if (!(bc->txstate & (TX_IDLE | TX_INIT))) { - fill_mem(bc, bc->idx, bc->free, 0xff); - if (bc->free == card->send.size) - bc->txstate |= TX_IDLE; - } - } -} - -static void -send_tiger(struct tiger_hw *card, u8 irq_stat) -{ - int i; - - /* Note send is via the READ DMA channel */ - if ((irq_stat & card->last_is0) & NJ_IRQM0_RD_MASK) { - pr_info("%s: tiger warn write double dma %x/%x\n", - card->name, irq_stat, card->last_is0); - return; - } else { - card->last_is0 &= ~NJ_IRQM0_RD_MASK; - card->last_is0 |= (irq_stat & NJ_IRQM0_RD_MASK); - } - for (i = 0; i < 2; i++) { - if (test_bit(FLG_ACTIVE, &card->bc[i].bch.Flags)) - send_tiger_bc(card, &card->bc[i]); - } -} - -static irqreturn_t -nj_irq(int intno, void *dev_id) -{ - struct tiger_hw *card = dev_id; - u8 val, s1val, s0val; - - spin_lock(&card->lock); - s0val = inb(card->base | NJ_IRQSTAT0); - s1val = inb(card->base | NJ_IRQSTAT1); - if ((s1val & NJ_ISACIRQ) && (s0val == 0)) { - /* shared IRQ */ - spin_unlock(&card->lock); - return IRQ_NONE; - } - pr_debug("%s: IRQSTAT0 %02x IRQSTAT1 %02x\n", card->name, s0val, s1val); - card->irqcnt++; - if (!(s1val & NJ_ISACIRQ)) { - val = ReadISAC_nj(card, ISAC_ISTA); - if (val) - mISDNisac_irq(&card->isac, val); - } - - if (s0val) - /* write to clear */ - outb(s0val, card->base | NJ_IRQSTAT0); - else - goto end; - s1val = s0val; - /* set bits in sval to indicate which page is free */ - card->recv.dmacur = inl(card->base | NJ_DMA_WRITE_ADR); - card->recv.idx = (card->recv.dmacur - card->recv.dmastart) >> 2; - if (card->recv.dmacur < card->recv.dmairq) - s0val = 0x08; /* the 2nd write area is free */ - else - s0val = 0x04; /* the 1st write area is free */ - - card->send.dmacur = inl(card->base | NJ_DMA_READ_ADR); - card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2; - if (card->send.dmacur < card->send.dmairq) - s0val |= 0x02; /* the 2nd read area is free */ - else - s0val |= 0x01; /* the 1st read area is free */ - - pr_debug("%s: DMA Status %02x/%02x/%02x %d/%d\n", card->name, - s1val, s0val, card->last_is0, - card->recv.idx, card->send.idx); - /* test if we have a DMA interrupt */ - if (s0val != card->last_is0) { - if ((s0val & NJ_IRQM0_RD_MASK) != - (card->last_is0 & NJ_IRQM0_RD_MASK)) - /* got a write dma int */ - send_tiger(card, s0val); - if ((s0val & NJ_IRQM0_WR_MASK) != - (card->last_is0 & NJ_IRQM0_WR_MASK)) - /* got a read dma int */ - recv_tiger(card, s0val); - } -end: - spin_unlock(&card->lock); - return IRQ_HANDLED; -} - -static int -nj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb) -{ - int ret = -EINVAL; - struct bchannel *bch = container_of(ch, struct bchannel, ch); - struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch); - struct tiger_hw *card = bch->hw; - struct mISDNhead *hh = mISDN_HEAD_P(skb); - u32 id; - u_long flags; - - switch (hh->prim) { - case PH_DATA_REQ: - spin_lock_irqsave(&card->lock, flags); - ret = bchannel_senddata(bch, skb); - if (ret > 0) { /* direct TX */ - id = hh->id; /* skb can be freed */ - fill_dma(bc); - ret = 0; - spin_unlock_irqrestore(&card->lock, flags); - if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) - queue_ch_frame(ch, PH_DATA_CNF, id, NULL); - } else - spin_unlock_irqrestore(&card->lock, flags); - return ret; - case PH_ACTIVATE_REQ: - spin_lock_irqsave(&card->lock, flags); - if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) - ret = mode_tiger(bc, ch->protocol); - else - ret = 0; - spin_unlock_irqrestore(&card->lock, flags); - if (!ret) - _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, - NULL, GFP_KERNEL); - break; - case PH_DEACTIVATE_REQ: - spin_lock_irqsave(&card->lock, flags); - mISDN_clear_bchannel(bch); - mode_tiger(bc, ISDN_P_NONE); - spin_unlock_irqrestore(&card->lock, flags); - _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, - NULL, GFP_KERNEL); - ret = 0; - break; - } - if (!ret) - dev_kfree_skb(skb); - return ret; -} - -static int -channel_bctrl(struct tiger_ch *bc, struct mISDN_ctrl_req *cq) -{ - int ret = 0; - struct tiger_hw *card = bc->bch.hw; - - switch (cq->op) { - case MISDN_CTRL_GETOP: - cq->op = 0; - break; - /* Nothing implemented yet */ - case MISDN_CTRL_FILL_EMPTY: - default: - pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op); - ret = -EINVAL; - break; - } - return ret; -} - -static int -nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) -{ - struct bchannel *bch = container_of(ch, struct bchannel, ch); - struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch); - struct tiger_hw *card = bch->hw; - int ret = -EINVAL; - u_long flags; - - pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg); - switch (cmd) { - case CLOSE_CHANNEL: - test_and_clear_bit(FLG_OPEN, &bch->Flags); - if (test_bit(FLG_ACTIVE, &bch->Flags)) { - spin_lock_irqsave(&card->lock, flags); - mISDN_freebchannel(bch); - test_and_clear_bit(FLG_TX_BUSY, &bch->Flags); - test_and_clear_bit(FLG_ACTIVE, &bch->Flags); - mode_tiger(bc, ISDN_P_NONE); - spin_unlock_irqrestore(&card->lock, flags); - } - ch->protocol = ISDN_P_NONE; - ch->peer = NULL; - module_put(THIS_MODULE); - ret = 0; - break; - case CONTROL_CHANNEL: - ret = channel_bctrl(bc, arg); - break; - default: - pr_info("%s: %s unknown prim(%x)\n", card->name, __func__, cmd); - } - return ret; -} - -static int -channel_ctrl(struct tiger_hw *card, struct mISDN_ctrl_req *cq) -{ - int ret = 0; - - switch (cq->op) { - case MISDN_CTRL_GETOP: - cq->op = MISDN_CTRL_LOOP; - break; - case MISDN_CTRL_LOOP: - /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */ - if (cq->channel < 0 || cq->channel > 3) { - ret = -EINVAL; - break; - } - ret = card->isac.ctrl(&card->isac, HW_TESTLOOP, cq->channel); - break; - default: - pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op); - ret = -EINVAL; - break; - } - return ret; -} - -static int -open_bchannel(struct tiger_hw *card, struct channel_req *rq) -{ - struct bchannel *bch; - - if (rq->adr.channel > 2) - return -EINVAL; - if (rq->protocol == ISDN_P_NONE) - return -EINVAL; - bch = &card->bc[rq->adr.channel - 1].bch; - if (test_and_set_bit(FLG_OPEN, &bch->Flags)) - return -EBUSY; /* b-channel can be only open once */ - test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); - bch->ch.protocol = rq->protocol; - rq->ch = &bch->ch; - return 0; -} - -/* - * device control function - */ -static int -nj_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg) -{ - struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); - struct dchannel *dch = container_of(dev, struct dchannel, dev); - struct tiger_hw *card = dch->hw; - struct channel_req *rq; - int err = 0; - - pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg); - switch (cmd) { - case OPEN_CHANNEL: - rq = arg; - if (rq->protocol == ISDN_P_TE_S0) - err = card->isac.open(&card->isac, rq); - else - err = open_bchannel(card, rq); - if (err) - break; - if (!try_module_get(THIS_MODULE)) - pr_info("%s: cannot get module\n", card->name); - break; - case CLOSE_CHANNEL: - pr_debug("%s: dev(%d) close from %p\n", card->name, dch->dev.id, - __builtin_return_address(0)); - module_put(THIS_MODULE); - break; - case CONTROL_CHANNEL: - err = channel_ctrl(card, arg); - break; - default: - pr_debug("%s: %s unknown command %x\n", - card->name, __func__, cmd); - return -EINVAL; - } - return err; -} - -static int -nj_init_card(struct tiger_hw *card) -{ - u_long flags; - int ret; - - spin_lock_irqsave(&card->lock, flags); - nj_disable_hwirq(card); - spin_unlock_irqrestore(&card->lock, flags); - - card->irq = card->pdev->irq; - if (request_irq(card->irq, nj_irq, IRQF_SHARED, card->name, card)) { - pr_info("%s: couldn't get interrupt %d\n", - card->name, card->irq); - card->irq = -1; - return -EIO; - } - - spin_lock_irqsave(&card->lock, flags); - nj_reset(card); - ret = card->isac.init(&card->isac); - if (ret) - goto error; - ret = inittiger(card); - if (ret) - goto error; - mode_tiger(&card->bc[0], ISDN_P_NONE); - mode_tiger(&card->bc[1], ISDN_P_NONE); -error: - spin_unlock_irqrestore(&card->lock, flags); - return ret; -} - - -static void -nj_release(struct tiger_hw *card) -{ - u_long flags; - int i; - - if (card->base_s) { - spin_lock_irqsave(&card->lock, flags); - nj_disable_hwirq(card); - mode_tiger(&card->bc[0], ISDN_P_NONE); - mode_tiger(&card->bc[1], ISDN_P_NONE); - card->isac.release(&card->isac); - spin_unlock_irqrestore(&card->lock, flags); - release_region(card->base, card->base_s); - card->base_s = 0; - } - if (card->irq > 0) - free_irq(card->irq, card); - if (card->isac.dch.dev.dev.class) - mISDN_unregister_device(&card->isac.dch.dev); - - for (i = 0; i < 2; i++) { - mISDN_freebchannel(&card->bc[i].bch); - kfree(card->bc[i].hsbuf); - kfree(card->bc[i].hrbuf); - } - if (card->dma_p) - pci_free_consistent(card->pdev, NJ_DMA_SIZE, - card->dma_p, card->dma); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - pci_clear_master(card->pdev); - pci_disable_device(card->pdev); - pci_set_drvdata(card->pdev, NULL); - kfree(card); -} - - -static int -nj_setup(struct tiger_hw *card) -{ - card->base = pci_resource_start(card->pdev, 0); - card->base_s = pci_resource_len(card->pdev, 0); - if (!request_region(card->base, card->base_s, card->name)) { - pr_info("%s: NETjet config port %#x-%#x already in use\n", - card->name, card->base, - (u32)(card->base + card->base_s - 1)); - card->base_s = 0; - return -EIO; - } - ASSIGN_FUNC(nj, ISAC, card->isac); - return 0; -} - - -static int __devinit -setup_instance(struct tiger_hw *card) -{ - int i, err; - u_long flags; - - snprintf(card->name, MISDN_MAX_IDLEN - 1, "netjet.%d", nj_cnt + 1); - write_lock_irqsave(&card_lock, flags); - list_add_tail(&card->list, &Cards); - write_unlock_irqrestore(&card_lock, flags); - - _set_debug(card); - card->isac.name = card->name; - spin_lock_init(&card->lock); - card->isac.hwlock = &card->lock; - mISDNisac_init(&card->isac, card); - - card->isac.dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | - (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); - card->isac.dch.dev.D.ctrl = nj_dctrl; - for (i = 0; i < 2; i++) { - card->bc[i].bch.nr = i + 1; - set_channelmap(i + 1, card->isac.dch.dev.channelmap); - mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM); - card->bc[i].bch.hw = card; - card->bc[i].bch.ch.send = nj_l2l1B; - card->bc[i].bch.ch.ctrl = nj_bctrl; - card->bc[i].bch.ch.nr = i + 1; - list_add(&card->bc[i].bch.ch.list, - &card->isac.dch.dev.bchannels); - card->bc[i].bch.hw = card; - } - err = nj_setup(card); - if (err) - goto error; - err = mISDN_register_device(&card->isac.dch.dev, &card->pdev->dev, - card->name); - if (err) - goto error; - err = nj_init_card(card); - if (!err) { - nj_cnt++; - pr_notice("Netjet %d cards installed\n", nj_cnt); - return 0; - } -error: - nj_release(card); - return err; -} - -static int __devinit -nj_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int err = -ENOMEM; - int cfg; - struct tiger_hw *card; - - if (pdev->subsystem_vendor == 0x8086 && - pdev->subsystem_device == 0x0003) { - pr_notice("Netjet: Digium X100P/X101P not handled\n"); - return -ENODEV; - } - - if (pdev->subsystem_vendor == 0x55 && - pdev->subsystem_device == 0x02) { - pr_notice("Netjet: Enter!Now not handled yet\n"); - return -ENODEV; - } - - card = kzalloc(sizeof(struct tiger_hw), GFP_ATOMIC); - if (!card) { - pr_info("No kmem for Netjet\n"); - return err; - } - - card->pdev = pdev; - - err = pci_enable_device(pdev); - if (err) { - kfree(card); - return err; - } - - printk(KERN_INFO "nj_probe(mISDN): found adapter at %s\n", - pci_name(pdev)); - - pci_set_master(pdev); - - /* the TJ300 and TJ320 must be detected, the IRQ handling is different - * unfortunately the chips use the same device ID, but the TJ320 has - * the bit20 in status PCI cfg register set - */ - pci_read_config_dword(pdev, 0x04, &cfg); - if (cfg & 0x00100000) - card->typ = NETJET_S_TJ320; - else - card->typ = NETJET_S_TJ300; - - card->base = pci_resource_start(pdev, 0); - card->irq = pdev->irq; - pci_set_drvdata(pdev, card); - err = setup_instance(card); - if (err) - pci_set_drvdata(pdev, NULL); - - return err; -} - - -static void __devexit nj_remove(struct pci_dev *pdev) -{ - struct tiger_hw *card = pci_get_drvdata(pdev); - - if (card) - nj_release(card); - else - pr_info("%s drvdata already removed\n", __func__); -} - -/* We cannot select cards with PCI_SUB... IDs, since here are cards with - * SUB IDs set to PCI_ANY_ID, so we need to match all and reject - * known other cards which not work with this driver - see probe function */ -static struct pci_device_id nj_pci_ids[] __devinitdata = { - { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { } -}; -MODULE_DEVICE_TABLE(pci, nj_pci_ids); - -static struct pci_driver nj_driver = { - .name = "netjet", - .probe = nj_probe, - .remove = __devexit_p(nj_remove), - .id_table = nj_pci_ids, -}; - -static int __init nj_init(void) -{ - int err; - - pr_notice("Netjet PCI driver Rev. %s\n", NETJET_REV); - err = pci_register_driver(&nj_driver); - return err; -} - -static void __exit nj_cleanup(void) -{ - pci_unregister_driver(&nj_driver); -} - -module_init(nj_init); -module_exit(nj_cleanup); diff --git a/trunk/drivers/isdn/hardware/mISDN/netjet.h b/trunk/drivers/isdn/hardware/mISDN/netjet.h deleted file mode 100644 index d061ff995607..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/netjet.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * NETjet common header file - * - * Author Karsten Keil - * based on work of Matt Henderson and Daniel Potts, - * Traverse Technologies P/L www.traverse.com.au - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#define NJ_CTRL 0x00 -#define NJ_DMACTRL 0x01 -#define NJ_AUXCTRL 0x02 -#define NJ_AUXDATA 0x03 -#define NJ_IRQMASK0 0x04 -#define NJ_IRQMASK1 0x05 -#define NJ_IRQSTAT0 0x06 -#define NJ_IRQSTAT1 0x07 -#define NJ_DMA_READ_START 0x08 -#define NJ_DMA_READ_IRQ 0x0c -#define NJ_DMA_READ_END 0x10 -#define NJ_DMA_READ_ADR 0x14 -#define NJ_DMA_WRITE_START 0x18 -#define NJ_DMA_WRITE_IRQ 0x1c -#define NJ_DMA_WRITE_END 0x20 -#define NJ_DMA_WRITE_ADR 0x24 -#define NJ_PULSE_CNT 0x28 - -#define NJ_ISAC_OFF 0xc0 -#define NJ_ISACIRQ 0x10 - -#define NJ_IRQM0_RD_MASK 0x03 -#define NJ_IRQM0_RD_IRQ 0x01 -#define NJ_IRQM0_RD_END 0x02 -#define NJ_IRQM0_WR_MASK 0x0c -#define NJ_IRQM0_WR_IRQ 0x04 -#define NJ_IRQM0_WR_END 0x08 - -/* one page here is no need to be smaller */ -#define NJ_DMA_SIZE 4096 -/* 2 * 64 byte is a compromise between IRQ count and latency */ -#define NJ_DMA_RXSIZE 128 /* 2 * 64 */ -#define NJ_DMA_TXSIZE 128 /* 2 * 64 */ - diff --git a/trunk/drivers/isdn/hardware/mISDN/speedfax.c b/trunk/drivers/isdn/hardware/mISDN/speedfax.c deleted file mode 100644 index ff3a4e290da3..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/speedfax.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * speedfax.c low level stuff for Sedlbauer Speedfax+ cards - * based on the ISAR DSP - * Thanks to Sedlbauer AG for informations and HW - * - * Author Karsten Keil - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include "ipac.h" -#include "isar.h" - -#define SPEEDFAX_REV "2.0" - -#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51 -#define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54 -#define PCI_SUB_ID_SEDLBAUER 0x01 - -#define SFAX_PCI_ADDR 0xc8 -#define SFAX_PCI_ISAC 0xd0 -#define SFAX_PCI_ISAR 0xe0 - -/* TIGER 100 Registers */ - -#define TIGER_RESET_ADDR 0x00 -#define TIGER_EXTERN_RESET_ON 0x01 -#define TIGER_EXTERN_RESET_OFF 0x00 -#define TIGER_AUX_CTRL 0x02 -#define TIGER_AUX_DATA 0x03 -#define TIGER_AUX_IRQMASK 0x05 -#define TIGER_AUX_STATUS 0x07 - -/* Tiger AUX BITs */ -#define SFAX_AUX_IOMASK 0xdd /* 1 and 5 are inputs */ -#define SFAX_ISAR_RESET_BIT_OFF 0x00 -#define SFAX_ISAR_RESET_BIT_ON 0x01 -#define SFAX_TIGER_IRQ_BIT 0x02 -#define SFAX_LED1_BIT 0x08 -#define SFAX_LED2_BIT 0x10 - -#define SFAX_PCI_RESET_ON (SFAX_ISAR_RESET_BIT_ON) -#define SFAX_PCI_RESET_OFF (SFAX_LED1_BIT | SFAX_LED2_BIT) - -static int sfax_cnt; -static u32 debug; -static u32 irqloops = 4; - -struct sfax_hw { - struct list_head list; - struct pci_dev *pdev; - char name[MISDN_MAX_IDLEN]; - u32 irq; - u32 irqcnt; - u32 cfg; - struct _ioport p_isac; - struct _ioport p_isar; - u8 aux_data; - spinlock_t lock; /* HW access lock */ - struct isac_hw isac; - struct isar_hw isar; -}; - -static LIST_HEAD(Cards); -static DEFINE_RWLOCK(card_lock); /* protect Cards */ - -static void -_set_debug(struct sfax_hw *card) -{ - card->isac.dch.debug = debug; - card->isar.ch[0].bch.debug = debug; - card->isar.ch[1].bch.debug = debug; -} - -static int -set_debug(const char *val, struct kernel_param *kp) -{ - int ret; - struct sfax_hw *card; - - ret = param_set_uint(val, kp); - if (!ret) { - read_lock(&card_lock); - list_for_each_entry(card, &Cards, list) - _set_debug(card); - read_unlock(&card_lock); - } - return ret; -} - -MODULE_AUTHOR("Karsten Keil"); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(SPEEDFAX_REV); -module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Speedfax debug mask"); -module_param(irqloops, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(irqloops, "Speedfax maximal irqloops (default 4)"); - -IOFUNC_IND(ISAC, sfax_hw, p_isac) -IOFUNC_IND(ISAR, sfax_hw, p_isar) - -static irqreturn_t -speedfax_irq(int intno, void *dev_id) -{ - struct sfax_hw *sf = dev_id; - u8 val; - int cnt = irqloops; - - spin_lock(&sf->lock); - val = inb(sf->cfg + TIGER_AUX_STATUS); - if (val & SFAX_TIGER_IRQ_BIT) { /* for us or shared ? */ - spin_unlock(&sf->lock); - return IRQ_NONE; /* shared */ - } - sf->irqcnt++; - val = ReadISAR_IND(sf, ISAR_IRQBIT); -Start_ISAR: - if (val & ISAR_IRQSTA) - mISDNisar_irq(&sf->isar); - val = ReadISAC_IND(sf, ISAC_ISTA); - if (val) - mISDNisac_irq(&sf->isac, val); - val = ReadISAR_IND(sf, ISAR_IRQBIT); - if ((val & ISAR_IRQSTA) && cnt--) - goto Start_ISAR; - if (cnt < irqloops) - pr_debug("%s: %d irqloops cpu%d\n", sf->name, - irqloops - cnt, smp_processor_id()); - if (irqloops && !cnt) - pr_notice("%s: %d IRQ LOOP cpu%d\n", sf->name, - irqloops, smp_processor_id()); - spin_unlock(&sf->lock); - return IRQ_HANDLED; -} - -static void -enable_hwirq(struct sfax_hw *sf) -{ - WriteISAC_IND(sf, ISAC_MASK, 0); - WriteISAR_IND(sf, ISAR_IRQBIT, ISAR_IRQMSK); - outb(SFAX_TIGER_IRQ_BIT, sf->cfg + TIGER_AUX_IRQMASK); -} - -static void -disable_hwirq(struct sfax_hw *sf) -{ - WriteISAC_IND(sf, ISAC_MASK, 0xFF); - WriteISAR_IND(sf, ISAR_IRQBIT, 0); - outb(0, sf->cfg + TIGER_AUX_IRQMASK); -} - -static void -reset_speedfax(struct sfax_hw *sf) -{ - - pr_debug("%s: resetting card\n", sf->name); - outb(TIGER_EXTERN_RESET_ON, sf->cfg + TIGER_RESET_ADDR); - outb(SFAX_PCI_RESET_ON, sf->cfg + TIGER_AUX_DATA); - mdelay(1); - outb(TIGER_EXTERN_RESET_OFF, sf->cfg + TIGER_RESET_ADDR); - sf->aux_data = SFAX_PCI_RESET_OFF; - outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA); - mdelay(1); -} - -static int -sfax_ctrl(struct sfax_hw *sf, u32 cmd, u_long arg) -{ - int ret = 0; - - switch (cmd) { - case HW_RESET_REQ: - reset_speedfax(sf); - break; - case HW_ACTIVATE_IND: - if (arg & 1) - sf->aux_data &= ~SFAX_LED1_BIT; - if (arg & 2) - sf->aux_data &= ~SFAX_LED2_BIT; - outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA); - break; - case HW_DEACT_IND: - if (arg & 1) - sf->aux_data |= SFAX_LED1_BIT; - if (arg & 2) - sf->aux_data |= SFAX_LED2_BIT; - outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA); - break; - default: - pr_info("%s: %s unknown command %x %lx\n", - sf->name, __func__, cmd, arg); - ret = -EINVAL; - break; - } - return ret; -} - -static int -channel_ctrl(struct sfax_hw *sf, struct mISDN_ctrl_req *cq) -{ - int ret = 0; - - switch (cq->op) { - case MISDN_CTRL_GETOP: - cq->op = MISDN_CTRL_LOOP; - break; - case MISDN_CTRL_LOOP: - /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */ - if (cq->channel < 0 || cq->channel > 3) { - ret = -EINVAL; - break; - } - ret = sf->isac.ctrl(&sf->isac, HW_TESTLOOP, cq->channel); - break; - default: - pr_info("%s: unknown Op %x\n", sf->name, cq->op); - ret = -EINVAL; - break; - } - return ret; -} - -static int -sfax_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg) -{ - struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); - struct dchannel *dch = container_of(dev, struct dchannel, dev); - struct sfax_hw *sf = dch->hw; - struct channel_req *rq; - int err = 0; - - pr_debug("%s: cmd:%x %p\n", sf->name, cmd, arg); - switch (cmd) { - case OPEN_CHANNEL: - rq = arg; - if (rq->protocol == ISDN_P_TE_S0) - err = sf->isac.open(&sf->isac, rq); - else - err = sf->isar.open(&sf->isar, rq); - if (err) - break; - if (!try_module_get(THIS_MODULE)) - pr_info("%s: cannot get module\n", sf->name); - break; - case CLOSE_CHANNEL: - pr_debug("%s: dev(%d) close from %p\n", sf->name, - dch->dev.id, __builtin_return_address(0)); - module_put(THIS_MODULE); - break; - case CONTROL_CHANNEL: - err = channel_ctrl(sf, arg); - break; - default: - pr_debug("%s: unknown command %x\n", sf->name, cmd); - return -EINVAL; - } - return err; -} - -static int __devinit -init_card(struct sfax_hw *sf) -{ - int ret, cnt = 3; - u_long flags; - - ret = request_irq(sf->irq, speedfax_irq, IRQF_SHARED, sf->name, sf); - if (ret) { - pr_info("%s: couldn't get interrupt %d\n", sf->name, sf->irq); - return ret; - } - while (cnt--) { - spin_lock_irqsave(&sf->lock, flags); - ret = sf->isac.init(&sf->isac); - if (ret) { - spin_unlock_irqrestore(&sf->lock, flags); - pr_info("%s: ISAC init failed with %d\n", - sf->name, ret); - break; - } - enable_hwirq(sf); - /* RESET Receiver and Transmitter */ - WriteISAC_IND(sf, ISAC_CMDR, 0x41); - spin_unlock_irqrestore(&sf->lock, flags); - msleep_interruptible(10); - if (debug & DEBUG_HW) - pr_notice("%s: IRQ %d count %d\n", sf->name, - sf->irq, sf->irqcnt); - if (!sf->irqcnt) { - pr_info("%s: IRQ(%d) got no requests during init %d\n", - sf->name, sf->irq, 3 - cnt); - } else - return 0; - } - free_irq(sf->irq, sf); - return -EIO; -} - - -static int __devinit -setup_speedfax(struct sfax_hw *sf) -{ - u_long flags; - - if (!request_region(sf->cfg, 256, sf->name)) { - pr_info("mISDN: %s config port %x-%x already in use\n", - sf->name, sf->cfg, sf->cfg + 255); - return -EIO; - } - outb(0xff, sf->cfg); - outb(0, sf->cfg); - outb(0xdd, sf->cfg + TIGER_AUX_CTRL); - outb(0, sf->cfg + TIGER_AUX_IRQMASK); - - sf->isac.type = IPAC_TYPE_ISAC; - sf->p_isac.ale = sf->cfg + SFAX_PCI_ADDR; - sf->p_isac.port = sf->cfg + SFAX_PCI_ISAC; - sf->p_isar.ale = sf->cfg + SFAX_PCI_ADDR; - sf->p_isar.port = sf->cfg + SFAX_PCI_ISAR; - ASSIGN_FUNC(IND, ISAC, sf->isac); - ASSIGN_FUNC(IND, ISAR, sf->isar); - spin_lock_irqsave(&sf->lock, flags); - reset_speedfax(sf); - disable_hwirq(sf); - spin_unlock_irqrestore(&sf->lock, flags); - return 0; -} - -static void -release_card(struct sfax_hw *card) { - u_long flags; - - spin_lock_irqsave(&card->lock, flags); - disable_hwirq(card); - spin_unlock_irqrestore(&card->lock, flags); - card->isac.release(&card->isac); - free_irq(card->irq, card); - card->isar.release(&card->isar); - mISDN_unregister_device(&card->isac.dch.dev); - release_region(card->cfg, 256); - pci_disable_device(card->pdev); - pci_set_drvdata(card->pdev, NULL); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - kfree(card); - sfax_cnt--; -} - -static int __devinit -setup_instance(struct sfax_hw *card) -{ - const struct firmware *firmware; - int i, err; - u_long flags; - - snprintf(card->name, MISDN_MAX_IDLEN - 1, "Speedfax.%d", sfax_cnt + 1); - write_lock_irqsave(&card_lock, flags); - list_add_tail(&card->list, &Cards); - write_unlock_irqrestore(&card_lock, flags); - _set_debug(card); - spin_lock_init(&card->lock); - card->isac.hwlock = &card->lock; - card->isar.hwlock = &card->lock; - card->isar.ctrl = (void *)&sfax_ctrl; - card->isac.name = card->name; - card->isar.name = card->name; - card->isar.owner = THIS_MODULE; - - err = request_firmware(&firmware, "isdn/ISAR.BIN", &card->pdev->dev); - if (err < 0) { - pr_info("%s: firmware request failed %d\n", - card->name, err); - goto error_fw; - } - if (debug & DEBUG_HW) - pr_notice("%s: got firmware %zu bytes\n", - card->name, firmware->size); - - mISDNisac_init(&card->isac, card); - - card->isac.dch.dev.D.ctrl = sfax_dctrl; - card->isac.dch.dev.Bprotocols = - mISDNisar_init(&card->isar, card); - for (i = 0; i < 2; i++) { - set_channelmap(i + 1, card->isac.dch.dev.channelmap); - list_add(&card->isar.ch[i].bch.ch.list, - &card->isac.dch.dev.bchannels); - } - - err = setup_speedfax(card); - if (err) - goto error_setup; - err = card->isar.init(&card->isar); - if (err) - goto error; - err = mISDN_register_device(&card->isac.dch.dev, - &card->pdev->dev, card->name); - if (err) - goto error; - err = init_card(card); - if (err) - goto error_init; - err = card->isar.firmware(&card->isar, firmware->data, firmware->size); - if (!err) { - release_firmware(firmware); - sfax_cnt++; - pr_notice("SpeedFax %d cards installed\n", sfax_cnt); - return 0; - } - disable_hwirq(card); - free_irq(card->irq, card); -error_init: - mISDN_unregister_device(&card->isac.dch.dev); -error: - release_region(card->cfg, 256); -error_setup: - card->isac.release(&card->isac); - card->isar.release(&card->isar); - release_firmware(firmware); -error_fw: - pci_disable_device(card->pdev); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - kfree(card); - return err; -} - -static int __devinit -sfaxpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int err = -ENOMEM; - struct sfax_hw *card = kzalloc(sizeof(struct sfax_hw), GFP_KERNEL); - - if (!card) { - pr_info("No memory for Speedfax+ PCI\n"); - return err; - } - card->pdev = pdev; - err = pci_enable_device(pdev); - if (err) { - kfree(card); - return err; - } - - pr_notice("mISDN: Speedfax found adapter %s at %s\n", - (char *)ent->driver_data, pci_name(pdev)); - - card->cfg = pci_resource_start(pdev, 0); - card->irq = pdev->irq; - pci_set_drvdata(pdev, card); - err = setup_instance(card); - if (err) - pci_set_drvdata(pdev, NULL); - return err; -} - -static void __devexit -sfax_remove_pci(struct pci_dev *pdev) -{ - struct sfax_hw *card = pci_get_drvdata(pdev); - - if (card) - release_card(card); - else - pr_debug("%s: drvdata allready removed\n", __func__); -} - -static struct pci_device_id sfaxpci_ids[] __devinitdata = { - { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, - PCI_SUBVENDOR_SPEEDFAX_PYRAMID, PCI_SUB_ID_SEDLBAUER, - 0, 0, (unsigned long) "Pyramid Speedfax + PCI" - }, - { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, - PCI_SUBVENDOR_SPEEDFAX_PCI, PCI_SUB_ID_SEDLBAUER, - 0, 0, (unsigned long) "Sedlbauer Speedfax + PCI" - }, - { } -}; -MODULE_DEVICE_TABLE(pci, sfaxpci_ids); - -static struct pci_driver sfaxpci_driver = { - .name = "speedfax+ pci", - .probe = sfaxpci_probe, - .remove = __devexit_p(sfax_remove_pci), - .id_table = sfaxpci_ids, -}; - -static int __init -Speedfax_init(void) -{ - int err; - - pr_notice("Sedlbauer Speedfax+ Driver Rev. %s\n", - SPEEDFAX_REV); - err = pci_register_driver(&sfaxpci_driver); - return err; -} - -static void __exit -Speedfax_cleanup(void) -{ - pci_unregister_driver(&sfaxpci_driver); -} - -module_init(Speedfax_init); -module_exit(Speedfax_cleanup); diff --git a/trunk/drivers/isdn/hardware/mISDN/w6692.c b/trunk/drivers/isdn/hardware/mISDN/w6692.c deleted file mode 100644 index 1b9008f13d6a..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/w6692.c +++ /dev/null @@ -1,1440 +0,0 @@ -/* - * w6692.c mISDN driver for Winbond w6692 based cards - * - * Author Karsten Keil - * based on the w6692 I4L driver from Petr Novak - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include "w6692.h" - -#define W6692_REV "2.0" - -#define DBUSY_TIMER_VALUE 80 - -enum { - W6692_ASUS, - W6692_WINBOND, - W6692_USR -}; - -/* private data in the PCI devices list */ -struct w6692map { - u_int subtype; - char *name; -}; - -static const struct w6692map w6692_map[] = -{ - {W6692_ASUS, "Dynalink/AsusCom IS64PH"}, - {W6692_WINBOND, "Winbond W6692"}, - {W6692_USR, "USR W6692"} -}; - -#ifndef PCI_VENDOR_ID_USR -#define PCI_VENDOR_ID_USR 0x16ec -#define PCI_DEVICE_ID_USR_6692 0x3409 -#endif - -struct w6692_ch { - struct bchannel bch; - u32 addr; - struct timer_list timer; - u8 b_mode; -}; - -struct w6692_hw { - struct list_head list; - struct pci_dev *pdev; - char name[MISDN_MAX_IDLEN]; - u32 irq; - u32 irqcnt; - u32 addr; - u32 fmask; /* feature mask - bit set per card nr */ - int subtype; - spinlock_t lock; /* hw lock */ - u8 imask; - u8 pctl; - u8 xaddr; - u8 xdata; - u8 state; - struct w6692_ch bc[2]; - struct dchannel dch; - char log[64]; -}; - -static LIST_HEAD(Cards); -static DEFINE_RWLOCK(card_lock); /* protect Cards */ - -static int w6692_cnt; -static int debug; -static u32 led; -static u32 pots; - -static void -_set_debug(struct w6692_hw *card) -{ - card->dch.debug = debug; - card->bc[0].bch.debug = debug; - card->bc[1].bch.debug = debug; -} - -static int -set_debug(const char *val, struct kernel_param *kp) -{ - int ret; - struct w6692_hw *card; - - ret = param_set_uint(val, kp); - if (!ret) { - read_lock(&card_lock); - list_for_each_entry(card, &Cards, list) - _set_debug(card); - read_unlock(&card_lock); - } - return ret; -} - -MODULE_AUTHOR("Karsten Keil"); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(W6692_REV); -module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "W6692 debug mask"); -module_param(led, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(led, "W6692 LED support bitmask (one bit per card)"); -module_param(pots, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(pots, "W6692 POTS support bitmask (one bit per card)"); - -static inline u8 -ReadW6692(struct w6692_hw *card, u8 offset) -{ - return inb(card->addr + offset); -} - -static inline void -WriteW6692(struct w6692_hw *card, u8 offset, u8 value) -{ - outb(value, card->addr + offset); -} - -static inline u8 -ReadW6692B(struct w6692_ch *bc, u8 offset) -{ - return inb(bc->addr + offset); -} - -static inline void -WriteW6692B(struct w6692_ch *bc, u8 offset, u8 value) -{ - outb(value, bc->addr + offset); -} - -static void -enable_hwirq(struct w6692_hw *card) -{ - WriteW6692(card, W_IMASK, card->imask); -} - -static void -disable_hwirq(struct w6692_hw *card) -{ - WriteW6692(card, W_IMASK, 0xff); -} - -static const char *W6692Ver[] = {"V00", "V01", "V10", "V11"}; - -static void -W6692Version(struct w6692_hw *card) -{ - int val; - - val = ReadW6692(card, W_D_RBCH); - pr_notice("%s: Winbond W6692 version: %s\n", card->name, - W6692Ver[(val >> 6) & 3]); -} - -static void -w6692_led_handler(struct w6692_hw *card, int on) -{ - if ((!(card->fmask & led)) || card->subtype == W6692_USR) - return; - if (on) { - card->xdata &= 0xfb; /* LED ON */ - WriteW6692(card, W_XDATA, card->xdata); - } else { - card->xdata |= 0x04; /* LED OFF */ - WriteW6692(card, W_XDATA, card->xdata); - } -} - -static void -ph_command(struct w6692_hw *card, u8 cmd) -{ - pr_debug("%s: ph_command %x\n", card->name, cmd); - WriteW6692(card, W_CIX, cmd); -} - -static void -W6692_new_ph(struct w6692_hw *card) -{ - if (card->state == W_L1CMD_RST) - ph_command(card, W_L1CMD_DRC); - schedule_event(&card->dch, FLG_PHCHANGE); -} - -static void -W6692_ph_bh(struct dchannel *dch) -{ - struct w6692_hw *card = dch->hw; - - switch (card->state) { - case W_L1CMD_RST: - dch->state = 0; - l1_event(dch->l1, HW_RESET_IND); - break; - case W_L1IND_CD: - dch->state = 3; - l1_event(dch->l1, HW_DEACT_CNF); - break; - case W_L1IND_DRD: - dch->state = 3; - l1_event(dch->l1, HW_DEACT_IND); - break; - case W_L1IND_CE: - dch->state = 4; - l1_event(dch->l1, HW_POWERUP_IND); - break; - case W_L1IND_LD: - if (dch->state <= 5) { - dch->state = 5; - l1_event(dch->l1, ANYSIGNAL); - } else { - dch->state = 8; - l1_event(dch->l1, LOSTFRAMING); - } - break; - case W_L1IND_ARD: - dch->state = 6; - l1_event(dch->l1, INFO2); - break; - case W_L1IND_AI8: - dch->state = 7; - l1_event(dch->l1, INFO4_P8); - break; - case W_L1IND_AI10: - dch->state = 7; - l1_event(dch->l1, INFO4_P10); - break; - default: - pr_debug("%s: TE unknown state %02x dch state %02x\n", - card->name, card->state, dch->state); - break; - } - pr_debug("%s: TE newstate %02x\n", card->name, dch->state); -} - -static void -W6692_empty_Dfifo(struct w6692_hw *card, int count) -{ - struct dchannel *dch = &card->dch; - u8 *ptr; - - pr_debug("%s: empty_Dfifo %d\n", card->name, count); - if (!dch->rx_skb) { - dch->rx_skb = mI_alloc_skb(card->dch.maxlen, GFP_ATOMIC); - if (!dch->rx_skb) { - pr_info("%s: D receive out of memory\n", card->name); - WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK); - return; - } - } - if ((dch->rx_skb->len + count) >= dch->maxlen) { - pr_debug("%s: empty_Dfifo overrun %d\n", card->name, - dch->rx_skb->len + count); - WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK); - return; - } - ptr = skb_put(dch->rx_skb, count); - insb(card->addr + W_D_RFIFO, ptr, count); - WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK); - if (debug & DEBUG_HW_DFIFO) { - snprintf(card->log, 63, "D-recv %s %d ", - card->name, count); - print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count); - } -} - -static void -W6692_fill_Dfifo(struct w6692_hw *card) -{ - struct dchannel *dch = &card->dch; - int count; - u8 *ptr; - u8 cmd = W_D_CMDR_XMS; - - pr_debug("%s: fill_Dfifo\n", card->name); - if (!dch->tx_skb) - return; - count = dch->tx_skb->len - dch->tx_idx; - if (count <= 0) - return; - if (count > W_D_FIFO_THRESH) - count = W_D_FIFO_THRESH; - else - cmd |= W_D_CMDR_XME; - ptr = dch->tx_skb->data + dch->tx_idx; - dch->tx_idx += count; - outsb(card->addr + W_D_XFIFO, ptr, count); - WriteW6692(card, W_D_CMDR, cmd); - if (test_and_set_bit(FLG_BUSY_TIMER, &dch->Flags)) { - pr_debug("%s: fill_Dfifo dbusytimer running\n", card->name); - del_timer(&dch->timer); - } - init_timer(&dch->timer); - dch->timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); - add_timer(&dch->timer); - if (debug & DEBUG_HW_DFIFO) { - snprintf(card->log, 63, "D-send %s %d ", - card->name, count); - print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count); - } -} - -static void -d_retransmit(struct w6692_hw *card) -{ - struct dchannel *dch = &card->dch; - - if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) - del_timer(&dch->timer); -#ifdef FIXME - if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags)) - dchannel_sched_event(dch, D_CLEARBUSY); -#endif - if (test_bit(FLG_TX_BUSY, &dch->Flags)) { - /* Restart frame */ - dch->tx_idx = 0; - W6692_fill_Dfifo(card); - } else if (dch->tx_skb) { /* should not happen */ - pr_info("%s: %s without TX_BUSY\n", card->name, __func__); - test_and_set_bit(FLG_TX_BUSY, &dch->Flags); - dch->tx_idx = 0; - W6692_fill_Dfifo(card); - } else { - pr_info("%s: XDU no TX_BUSY\n", card->name); - if (get_next_dframe(dch)) - W6692_fill_Dfifo(card); - } -} - -static void -handle_rxD(struct w6692_hw *card) { - u8 stat; - int count; - - stat = ReadW6692(card, W_D_RSTA); - if (stat & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) { - if (stat & W_D_RSTA_RDOV) { - pr_debug("%s: D-channel RDOV\n", card->name); -#ifdef ERROR_STATISTIC - card->dch.err_rx++; -#endif - } - if (stat & W_D_RSTA_CRCE) { - pr_debug("%s: D-channel CRC error\n", card->name); -#ifdef ERROR_STATISTIC - card->dch.err_crc++; -#endif - } - if (stat & W_D_RSTA_RMB) { - pr_debug("%s: D-channel ABORT\n", card->name); -#ifdef ERROR_STATISTIC - card->dch.err_rx++; -#endif - } - if (card->dch.rx_skb) - dev_kfree_skb(card->dch.rx_skb); - card->dch.rx_skb = NULL; - WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); - } else { - count = ReadW6692(card, W_D_RBCL) & (W_D_FIFO_THRESH - 1); - if (count == 0) - count = W_D_FIFO_THRESH; - W6692_empty_Dfifo(card, count); - recv_Dchannel(&card->dch); - } -} - -static void -handle_txD(struct w6692_hw *card) { - if (test_and_clear_bit(FLG_BUSY_TIMER, &card->dch.Flags)) - del_timer(&card->dch.timer); - if (card->dch.tx_skb && card->dch.tx_idx < card->dch.tx_skb->len) { - W6692_fill_Dfifo(card); - } else { - if (card->dch.tx_skb) - dev_kfree_skb(card->dch.tx_skb); - if (get_next_dframe(&card->dch)) - W6692_fill_Dfifo(card); - } -} - -static void -handle_statusD(struct w6692_hw *card) -{ - struct dchannel *dch = &card->dch; - u8 exval, v1, cir; - - exval = ReadW6692(card, W_D_EXIR); - - pr_debug("%s: D_EXIR %02x\n", card->name, exval); - if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) { - /* Transmit underrun/collision */ - pr_debug("%s: D-channel underrun/collision\n", card->name); -#ifdef ERROR_STATISTIC - dch->err_tx++; -#endif - d_retransmit(card); - } - if (exval & W_D_EXI_RDOV) { /* RDOV */ - pr_debug("%s: D-channel RDOV\n", card->name); - WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST); - } - if (exval & W_D_EXI_TIN2) /* TIN2 - never */ - pr_debug("%s: spurious TIN2 interrupt\n", card->name); - if (exval & W_D_EXI_MOC) { /* MOC - not supported */ - v1 = ReadW6692(card, W_MOSR); - pr_debug("%s: spurious MOC interrupt MOSR %02x\n", - card->name, v1); - } - if (exval & W_D_EXI_ISC) { /* ISC - Level1 change */ - cir = ReadW6692(card, W_CIR); - pr_debug("%s: ISC CIR %02X\n", card->name, cir); - if (cir & W_CIR_ICC) { - v1 = cir & W_CIR_COD_MASK; - pr_debug("%s: ph_state_change %x -> %x\n", card->name, - dch->state, v1); - card->state = v1; - if (card->fmask & led) { - switch (v1) { - case W_L1IND_AI8: - case W_L1IND_AI10: - w6692_led_handler(card, 1); - break; - default: - w6692_led_handler(card, 0); - break; - } - } - W6692_new_ph(card); - } - if (cir & W_CIR_SCC) { - v1 = ReadW6692(card, W_SQR); - pr_debug("%s: SCC SQR %02X\n", card->name, v1); - } - } - if (exval & W_D_EXI_WEXP) - pr_debug("%s: spurious WEXP interrupt!\n", card->name); - if (exval & W_D_EXI_TEXP) - pr_debug("%s: spurious TEXP interrupt!\n", card->name); -} - -static void -W6692_empty_Bfifo(struct w6692_ch *wch, int count) -{ - struct w6692_hw *card = wch->bch.hw; - u8 *ptr; - - pr_debug("%s: empty_Bfifo %d\n", card->name, count); - if (unlikely(wch->bch.state == ISDN_P_NONE)) { - pr_debug("%s: empty_Bfifo ISDN_P_NONE\n", card->name); - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); - if (wch->bch.rx_skb) - skb_trim(wch->bch.rx_skb, 0); - return; - } - if (!wch->bch.rx_skb) { - wch->bch.rx_skb = mI_alloc_skb(wch->bch.maxlen, GFP_ATOMIC); - if (unlikely(!wch->bch.rx_skb)) { - pr_info("%s: B receive out of memory\n", card->name); - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | - W_B_CMDR_RACT); - return; - } - } - if (wch->bch.rx_skb->len + count > wch->bch.maxlen) { - pr_debug("%s: empty_Bfifo incoming packet too large\n", - card->name); - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); - skb_trim(wch->bch.rx_skb, 0); - return; - } - ptr = skb_put(wch->bch.rx_skb, count); - insb(wch->addr + W_B_RFIFO, ptr, count); - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); - if (debug & DEBUG_HW_DFIFO) { - snprintf(card->log, 63, "B%1d-recv %s %d ", - wch->bch.nr, card->name, count); - print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count); - } -} - -static void -W6692_fill_Bfifo(struct w6692_ch *wch) -{ - struct w6692_hw *card = wch->bch.hw; - int count; - u8 *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS; - - pr_debug("%s: fill Bfifo\n", card->name); - if (!wch->bch.tx_skb) - return; - count = wch->bch.tx_skb->len - wch->bch.tx_idx; - if (count <= 0) - return; - ptr = wch->bch.tx_skb->data + wch->bch.tx_idx; - if (count > W_B_FIFO_THRESH) - count = W_B_FIFO_THRESH; - else if (test_bit(FLG_HDLC, &wch->bch.Flags)) - cmd |= W_B_CMDR_XME; - - pr_debug("%s: fill Bfifo%d/%d\n", card->name, - count, wch->bch.tx_idx); - wch->bch.tx_idx += count; - outsb(wch->addr + W_B_XFIFO, ptr, count); - WriteW6692B(wch, W_B_CMDR, cmd); - if (debug & DEBUG_HW_DFIFO) { - snprintf(card->log, 63, "B%1d-send %s %d ", - wch->bch.nr, card->name, count); - print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count); - } -} - -static int -setvolume(struct w6692_ch *wch, int mic, struct sk_buff *skb) -{ - struct w6692_hw *card = wch->bch.hw; - u16 *vol = (u16 *)skb->data; - u8 val; - - if ((!(card->fmask & pots)) || - !test_bit(FLG_TRANSPARENT, &wch->bch.Flags)) - return -ENODEV; - if (skb->len < 2) - return -EINVAL; - if (*vol > 7) - return -EINVAL; - val = *vol & 7; - val = 7 - val; - if (mic) { - val <<= 3; - card->xaddr &= 0xc7; - } else { - card->xaddr &= 0xf8; - } - card->xaddr |= val; - WriteW6692(card, W_XADDR, card->xaddr); - return 0; -} - -static int -enable_pots(struct w6692_ch *wch) -{ - struct w6692_hw *card = wch->bch.hw; - - if ((!(card->fmask & pots)) || - !test_bit(FLG_TRANSPARENT, &wch->bch.Flags)) - return -ENODEV; - wch->b_mode |= W_B_MODE_EPCM | W_B_MODE_BSW0; - WriteW6692B(wch, W_B_MODE, wch->b_mode); - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST); - card->pctl |= ((wch->bch.nr & 2) ? W_PCTL_PCX : 0); - WriteW6692(card, W_PCTL, card->pctl); - return 0; -} - -static int -disable_pots(struct w6692_ch *wch) -{ - struct w6692_hw *card = wch->bch.hw; - - if (!(card->fmask & pots)) - return -ENODEV; - wch->b_mode &= ~(W_B_MODE_EPCM | W_B_MODE_BSW0); - WriteW6692B(wch, W_B_MODE, wch->b_mode); - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | - W_B_CMDR_XRST); - return 0; -} - -static int -w6692_mode(struct w6692_ch *wch, u32 pr) -{ - struct w6692_hw *card; - - card = wch->bch.hw; - pr_debug("%s: B%d protocol %x-->%x\n", card->name, - wch->bch.nr, wch->bch.state, pr); - switch (pr) { - case ISDN_P_NONE: - if ((card->fmask & pots) && (wch->b_mode & W_B_MODE_EPCM)) - disable_pots(wch); - wch->b_mode = 0; - mISDN_clear_bchannel(&wch->bch); - WriteW6692B(wch, W_B_MODE, wch->b_mode); - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST); - test_and_clear_bit(FLG_HDLC, &wch->bch.Flags); - test_and_clear_bit(FLG_TRANSPARENT, &wch->bch.Flags); - break; - case ISDN_P_B_RAW: - wch->b_mode = W_B_MODE_MMS; - WriteW6692B(wch, W_B_MODE, wch->b_mode); - WriteW6692B(wch, W_B_EXIM, 0); - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | - W_B_CMDR_XRST); - test_and_set_bit(FLG_TRANSPARENT, &wch->bch.Flags); - break; - case ISDN_P_B_HDLC: - wch->b_mode = W_B_MODE_ITF; - WriteW6692B(wch, W_B_MODE, wch->b_mode); - WriteW6692B(wch, W_B_ADM1, 0xff); - WriteW6692B(wch, W_B_ADM2, 0xff); - WriteW6692B(wch, W_B_EXIM, 0); - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | - W_B_CMDR_XRST); - test_and_set_bit(FLG_HDLC, &wch->bch.Flags); - break; - default: - pr_info("%s: protocol %x not known\n", card->name, pr); - return -ENOPROTOOPT; - } - wch->bch.state = pr; - return 0; -} - -static void -send_next(struct w6692_ch *wch) -{ - if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) - W6692_fill_Bfifo(wch); - else { - if (wch->bch.tx_skb) { - /* send confirm, on trans, free on hdlc. */ - if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags)) - confirm_Bsend(&wch->bch); - dev_kfree_skb(wch->bch.tx_skb); - } - if (get_next_bframe(&wch->bch)) - W6692_fill_Bfifo(wch); - } -} - -static void -W6692B_interrupt(struct w6692_hw *card, int ch) -{ - struct w6692_ch *wch = &card->bc[ch]; - int count; - u8 stat, star = 0; - - stat = ReadW6692B(wch, W_B_EXIR); - pr_debug("%s: B%d EXIR %02x\n", card->name, wch->bch.nr, stat); - if (stat & W_B_EXI_RME) { - star = ReadW6692B(wch, W_B_STAR); - if (star & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) { - if ((star & W_B_STAR_RDOV) && - test_bit(FLG_ACTIVE, &wch->bch.Flags)) { - pr_debug("%s: B%d RDOV proto=%x\n", card->name, - wch->bch.nr, wch->bch.state); -#ifdef ERROR_STATISTIC - wch->bch.err_rdo++; -#endif - } - if (test_bit(FLG_HDLC, &wch->bch.Flags)) { - if (star & W_B_STAR_CRCE) { - pr_debug("%s: B%d CRC error\n", - card->name, wch->bch.nr); -#ifdef ERROR_STATISTIC - wch->bch.err_crc++; -#endif - } - if (star & W_B_STAR_RMB) { - pr_debug("%s: B%d message abort\n", - card->name, wch->bch.nr); -#ifdef ERROR_STATISTIC - wch->bch.err_inv++; -#endif - } - } - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | - W_B_CMDR_RRST | W_B_CMDR_RACT); - if (wch->bch.rx_skb) - skb_trim(wch->bch.rx_skb, 0); - } else { - count = ReadW6692B(wch, W_B_RBCL) & - (W_B_FIFO_THRESH - 1); - if (count == 0) - count = W_B_FIFO_THRESH; - W6692_empty_Bfifo(wch, count); - recv_Bchannel(&wch->bch, 0); - } - } - if (stat & W_B_EXI_RMR) { - if (!(stat & W_B_EXI_RME)) - star = ReadW6692B(wch, W_B_STAR); - if (star & W_B_STAR_RDOV) { - pr_debug("%s: B%d RDOV proto=%x\n", card->name, - wch->bch.nr, wch->bch.state); -#ifdef ERROR_STATISTIC - wch->bch.err_rdo++; -#endif - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | - W_B_CMDR_RRST | W_B_CMDR_RACT); - } else { - W6692_empty_Bfifo(wch, W_B_FIFO_THRESH); - if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags) && - wch->bch.rx_skb && (wch->bch.rx_skb->len > 0)) - recv_Bchannel(&wch->bch, 0); - } - } - if (stat & W_B_EXI_RDOV) { - /* only if it is not handled yet */ - if (!(star & W_B_STAR_RDOV)) { - pr_debug("%s: B%d RDOV IRQ proto=%x\n", card->name, - wch->bch.nr, wch->bch.state); -#ifdef ERROR_STATISTIC - wch->bch.err_rdo++; -#endif - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | - W_B_CMDR_RRST | W_B_CMDR_RACT); - } - } - if (stat & W_B_EXI_XFR) { - if (!(stat & (W_B_EXI_RME | W_B_EXI_RMR))) { - star = ReadW6692B(wch, W_B_STAR); - pr_debug("%s: B%d star %02x\n", card->name, - wch->bch.nr, star); - } - if (star & W_B_STAR_XDOW) { - pr_debug("%s: B%d XDOW proto=%x\n", card->name, - wch->bch.nr, wch->bch.state); -#ifdef ERROR_STATISTIC - wch->bch.err_xdu++; -#endif - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_XRST | - W_B_CMDR_RACT); - /* resend */ - if (wch->bch.tx_skb) { - if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags)) - wch->bch.tx_idx = 0; - } - } - send_next(wch); - if (stat & W_B_EXI_XDUN) - return; /* handle XDOW only once */ - } - if (stat & W_B_EXI_XDUN) { - pr_debug("%s: B%d XDUN proto=%x\n", card->name, - wch->bch.nr, wch->bch.state); -#ifdef ERROR_STATISTIC - wch->bch.err_xdu++; -#endif - WriteW6692B(wch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); - /* resend */ - if (wch->bch.tx_skb) { - if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags)) - wch->bch.tx_idx = 0; - } - send_next(wch); - } -} - -static irqreturn_t -w6692_irq(int intno, void *dev_id) -{ - struct w6692_hw *card = dev_id; - u8 ista; - - spin_lock(&card->lock); - ista = ReadW6692(card, W_ISTA); - if ((ista | card->imask) == card->imask) { - /* possible a shared IRQ reqest */ - spin_unlock(&card->lock); - return IRQ_NONE; - } - card->irqcnt++; - pr_debug("%s: ista %02x\n", card->name, ista); - ista &= ~card->imask; - if (ista & W_INT_B1_EXI) - W6692B_interrupt(card, 0); - if (ista & W_INT_B2_EXI) - W6692B_interrupt(card, 1); - if (ista & W_INT_D_RME) - handle_rxD(card); - if (ista & W_INT_D_RMR) - W6692_empty_Dfifo(card, W_D_FIFO_THRESH); - if (ista & W_INT_D_XFR) - handle_txD(card); - if (ista & W_INT_D_EXI) - handle_statusD(card); - if (ista & (W_INT_XINT0 | W_INT_XINT1)) /* XINT0/1 - never */ - pr_debug("%s: W6692 spurious XINT!\n", card->name); -/* End IRQ Handler */ - spin_unlock(&card->lock); - return IRQ_HANDLED; -} - -static void -dbusy_timer_handler(struct dchannel *dch) -{ - struct w6692_hw *card = dch->hw; - int rbch, star; - u_long flags; - - if (test_bit(FLG_BUSY_TIMER, &dch->Flags)) { - spin_lock_irqsave(&card->lock, flags); - rbch = ReadW6692(card, W_D_RBCH); - star = ReadW6692(card, W_D_STAR); - pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n", - card->name, rbch, star); - if (star & W_D_STAR_XBZ) /* D-Channel Busy */ - test_and_set_bit(FLG_L1_BUSY, &dch->Flags); - else { - /* discard frame; reset transceiver */ - test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags); - if (dch->tx_idx) - dch->tx_idx = 0; - else - pr_info("%s: W6692 D-Channel Busy no tx_idx\n", - card->name); - /* Transmitter reset */ - WriteW6692(card, W_D_CMDR, W_D_CMDR_XRST); - } - spin_unlock_irqrestore(&card->lock, flags); - } -} - -void initW6692(struct w6692_hw *card) -{ - u8 val; - - card->dch.timer.function = (void *)dbusy_timer_handler; - card->dch.timer.data = (u_long)&card->dch; - init_timer(&card->dch.timer); - w6692_mode(&card->bc[0], ISDN_P_NONE); - w6692_mode(&card->bc[1], ISDN_P_NONE); - WriteW6692(card, W_D_CTL, 0x00); - disable_hwirq(card); - WriteW6692(card, W_D_SAM, 0xff); - WriteW6692(card, W_D_TAM, 0xff); - WriteW6692(card, W_D_MODE, W_D_MODE_RACT); - card->state = W_L1CMD_RST; - ph_command(card, W_L1CMD_RST); - ph_command(card, W_L1CMD_ECK); - /* enable all IRQ but extern */ - card->imask = 0x18; - WriteW6692(card, W_D_EXIM, 0x00); - WriteW6692B(&card->bc[0], W_B_EXIM, 0); - WriteW6692B(&card->bc[1], W_B_EXIM, 0); - /* Reset D-chan receiver and transmitter */ - WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); - /* Reset B-chan receiver and transmitter */ - WriteW6692B(&card->bc[0], W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST); - WriteW6692B(&card->bc[1], W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST); - /* enable peripheral */ - if (card->subtype == W6692_USR) { - /* seems that USR implemented some power control features - * Pin 79 is connected to the oscilator circuit so we - * have to handle it here - */ - card->pctl = 0x80; - card->xdata = 0; - WriteW6692(card, W_PCTL, card->pctl); - WriteW6692(card, W_XDATA, card->xdata); - } else { - card->pctl = W_PCTL_OE5 | W_PCTL_OE4 | W_PCTL_OE2 | - W_PCTL_OE1 | W_PCTL_OE0; - card->xaddr = 0x00;/* all sw off */ - if (card->fmask & pots) - card->xdata |= 0x06; /* POWER UP/ LED OFF / ALAW */ - if (card->fmask & led) - card->xdata |= 0x04; /* LED OFF */ - if ((card->fmask & pots) || (card->fmask & led)) { - WriteW6692(card, W_PCTL, card->pctl); - WriteW6692(card, W_XADDR, card->xaddr); - WriteW6692(card, W_XDATA, card->xdata); - val = ReadW6692(card, W_XADDR); - if (debug & DEBUG_HW) - pr_notice("%s: W_XADDR=%02x\n", - card->name, val); - } - } -} - -static void -reset_w6692(struct w6692_hw *card) -{ - WriteW6692(card, W_D_CTL, W_D_CTL_SRST); - mdelay(10); - WriteW6692(card, W_D_CTL, 0); -} - -static int -init_card(struct w6692_hw *card) -{ - int cnt = 3; - u_long flags; - - spin_lock_irqsave(&card->lock, flags); - disable_hwirq(card); - spin_unlock_irqrestore(&card->lock, flags); - if (request_irq(card->irq, w6692_irq, IRQF_SHARED, card->name, card)) { - pr_info("%s: couldn't get interrupt %d\n", card->name, - card->irq); - return -EIO; - } - while (cnt--) { - spin_lock_irqsave(&card->lock, flags); - initW6692(card); - enable_hwirq(card); - spin_unlock_irqrestore(&card->lock, flags); - /* Timeout 10ms */ - msleep_interruptible(10); - if (debug & DEBUG_HW) - pr_notice("%s: IRQ %d count %d\n", card->name, - card->irq, card->irqcnt); - if (!card->irqcnt) { - pr_info("%s: IRQ(%d) getting no IRQs during init %d\n", - card->name, card->irq, 3 - cnt); - reset_w6692(card); - } else - return 0; - } - free_irq(card->irq, card); - return -EIO; -} - -static int -w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb) -{ - struct bchannel *bch = container_of(ch, struct bchannel, ch); - struct w6692_ch *bc = container_of(bch, struct w6692_ch, bch); - struct w6692_hw *card = bch->hw; - int ret = -EINVAL; - struct mISDNhead *hh = mISDN_HEAD_P(skb); - u32 id; - u_long flags; - - switch (hh->prim) { - case PH_DATA_REQ: - spin_lock_irqsave(&card->lock, flags); - ret = bchannel_senddata(bch, skb); - if (ret > 0) { /* direct TX */ - id = hh->id; /* skb can be freed */ - ret = 0; - W6692_fill_Bfifo(bc); - spin_unlock_irqrestore(&card->lock, flags); - if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) - queue_ch_frame(ch, PH_DATA_CNF, id, NULL); - } else - spin_unlock_irqrestore(&card->lock, flags); - return ret; - case PH_ACTIVATE_REQ: - spin_lock_irqsave(&card->lock, flags); - if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) - ret = w6692_mode(bc, ch->protocol); - else - ret = 0; - spin_unlock_irqrestore(&card->lock, flags); - if (!ret) - _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, - NULL, GFP_KERNEL); - break; - case PH_DEACTIVATE_REQ: - spin_lock_irqsave(&card->lock, flags); - mISDN_clear_bchannel(bch); - w6692_mode(bc, ISDN_P_NONE); - spin_unlock_irqrestore(&card->lock, flags); - _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, - NULL, GFP_KERNEL); - ret = 0; - break; - default: - pr_info("%s: %s unknown prim(%x,%x)\n", - card->name, __func__, hh->prim, hh->id); - ret = -EINVAL; - } - if (!ret) - dev_kfree_skb(skb); - return ret; -} - -static int -channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) -{ - int ret = 0; - - switch (cq->op) { - case MISDN_CTRL_GETOP: - cq->op = 0; - break; - /* Nothing implemented yet */ - case MISDN_CTRL_FILL_EMPTY: - default: - pr_info("%s: unknown Op %x\n", __func__, cq->op); - ret = -EINVAL; - break; - } - return ret; -} - -static int -open_bchannel(struct w6692_hw *card, struct channel_req *rq) -{ - struct bchannel *bch; - - if (rq->adr.channel > 2) - return -EINVAL; - if (rq->protocol == ISDN_P_NONE) - return -EINVAL; - bch = &card->bc[rq->adr.channel - 1].bch; - if (test_and_set_bit(FLG_OPEN, &bch->Flags)) - return -EBUSY; /* b-channel can be only open once */ - test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); - bch->ch.protocol = rq->protocol; - rq->ch = &bch->ch; - return 0; -} - -static int -channel_ctrl(struct w6692_hw *card, struct mISDN_ctrl_req *cq) -{ - int ret = 0; - - switch (cq->op) { - case MISDN_CTRL_GETOP: - cq->op = 0; - break; - default: - pr_info("%s: unknown CTRL OP %x\n", card->name, cq->op); - ret = -EINVAL; - break; - } - return ret; -} - -static int -w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) -{ - struct bchannel *bch = container_of(ch, struct bchannel, ch); - struct w6692_ch *bc = container_of(bch, struct w6692_ch, bch); - struct w6692_hw *card = bch->hw; - int ret = -EINVAL; - u_long flags; - - pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg); - switch (cmd) { - case CLOSE_CHANNEL: - test_and_clear_bit(FLG_OPEN, &bch->Flags); - if (test_bit(FLG_ACTIVE, &bch->Flags)) { - spin_lock_irqsave(&card->lock, flags); - mISDN_freebchannel(bch); - w6692_mode(bc, ISDN_P_NONE); - spin_unlock_irqrestore(&card->lock, flags); - } else { - skb_queue_purge(&bch->rqueue); - bch->rcount = 0; - } - ch->protocol = ISDN_P_NONE; - ch->peer = NULL; - module_put(THIS_MODULE); - ret = 0; - break; - case CONTROL_CHANNEL: - ret = channel_bctrl(bch, arg); - break; - default: - pr_info("%s: %s unknown prim(%x)\n", - card->name, __func__, cmd); - } - return ret; -} - -static int -w6692_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb) -{ - struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); - struct dchannel *dch = container_of(dev, struct dchannel, dev); - struct w6692_hw *card = container_of(dch, struct w6692_hw, dch); - int ret = -EINVAL; - struct mISDNhead *hh = mISDN_HEAD_P(skb); - u32 id; - u_long flags; - - switch (hh->prim) { - case PH_DATA_REQ: - spin_lock_irqsave(&card->lock, flags); - ret = dchannel_senddata(dch, skb); - if (ret > 0) { /* direct TX */ - id = hh->id; /* skb can be freed */ - W6692_fill_Dfifo(card); - ret = 0; - spin_unlock_irqrestore(&card->lock, flags); - queue_ch_frame(ch, PH_DATA_CNF, id, NULL); - } else - spin_unlock_irqrestore(&card->lock, flags); - return ret; - case PH_ACTIVATE_REQ: - ret = l1_event(dch->l1, hh->prim); - break; - case PH_DEACTIVATE_REQ: - test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); - ret = l1_event(dch->l1, hh->prim); - break; - } - - if (!ret) - dev_kfree_skb(skb); - return ret; -} - -static int -w6692_l1callback(struct dchannel *dch, u32 cmd) -{ - struct w6692_hw *card = container_of(dch, struct w6692_hw, dch); - u_long flags; - - pr_debug("%s: cmd(%x) state(%02x)\n", card->name, cmd, card->state); - switch (cmd) { - case INFO3_P8: - spin_lock_irqsave(&card->lock, flags); - ph_command(card, W_L1CMD_AR8); - spin_unlock_irqrestore(&card->lock, flags); - break; - case INFO3_P10: - spin_lock_irqsave(&card->lock, flags); - ph_command(card, W_L1CMD_AR10); - spin_unlock_irqrestore(&card->lock, flags); - break; - case HW_RESET_REQ: - spin_lock_irqsave(&card->lock, flags); - if (card->state != W_L1IND_DRD) - ph_command(card, W_L1CMD_RST); - ph_command(card, W_L1CMD_ECK); - spin_unlock_irqrestore(&card->lock, flags); - break; - case HW_DEACT_REQ: - skb_queue_purge(&dch->squeue); - if (dch->tx_skb) { - dev_kfree_skb(dch->tx_skb); - dch->tx_skb = NULL; - } - dch->tx_idx = 0; - if (dch->rx_skb) { - dev_kfree_skb(dch->rx_skb); - dch->rx_skb = NULL; - } - test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); - if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) - del_timer(&dch->timer); - break; - case HW_POWERUP_REQ: - spin_lock_irqsave(&card->lock, flags); - ph_command(card, W_L1CMD_ECK); - spin_unlock_irqrestore(&card->lock, flags); - break; - case PH_ACTIVATE_IND: - test_and_set_bit(FLG_ACTIVE, &dch->Flags); - _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL, - GFP_ATOMIC); - break; - case PH_DEACTIVATE_IND: - test_and_clear_bit(FLG_ACTIVE, &dch->Flags); - _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL, - GFP_ATOMIC); - break; - default: - pr_debug("%s: %s unknown command %x\n", card->name, - __func__, cmd); - return -1; - } - return 0; -} - -static int -open_dchannel(struct w6692_hw *card, struct channel_req *rq) -{ - pr_debug("%s: %s dev(%d) open from %p\n", card->name, __func__, - card->dch.dev.id, __builtin_return_address(1)); - if (rq->protocol != ISDN_P_TE_S0) - return -EINVAL; - if (rq->adr.channel == 1) - /* E-Channel not supported */ - return -EINVAL; - rq->ch = &card->dch.dev.D; - rq->ch->protocol = rq->protocol; - if (card->dch.state == 7) - _queue_data(rq->ch, PH_ACTIVATE_IND, MISDN_ID_ANY, - 0, NULL, GFP_KERNEL); - return 0; -} - -static int -w6692_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg) -{ - struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); - struct dchannel *dch = container_of(dev, struct dchannel, dev); - struct w6692_hw *card = container_of(dch, struct w6692_hw, dch); - struct channel_req *rq; - int err = 0; - - pr_debug("%s: DCTRL: %x %p\n", card->name, cmd, arg); - switch (cmd) { - case OPEN_CHANNEL: - rq = arg; - if (rq->protocol == ISDN_P_TE_S0) - err = open_dchannel(card, rq); - else - err = open_bchannel(card, rq); - if (err) - break; - if (!try_module_get(THIS_MODULE)) - pr_info("%s: cannot get module\n", card->name); - break; - case CLOSE_CHANNEL: - pr_debug("%s: dev(%d) close from %p\n", card->name, - dch->dev.id, __builtin_return_address(0)); - module_put(THIS_MODULE); - break; - case CONTROL_CHANNEL: - err = channel_ctrl(card, arg); - break; - default: - pr_debug("%s: unknown DCTRL command %x\n", card->name, cmd); - return -EINVAL; - } - return err; -} - -int -setup_w6692(struct w6692_hw *card) -{ - u32 val; - - if (!request_region(card->addr, 256, card->name)) { - pr_info("%s: config port %x-%x already in use\n", card->name, - card->addr, card->addr + 255); - return -EIO; - } - W6692Version(card); - card->bc[0].addr = card->addr; - card->bc[1].addr = card->addr + 0x40; - val = ReadW6692(card, W_ISTA); - if (debug & DEBUG_HW) - pr_notice("%s ISTA=%02x\n", card->name, val); - val = ReadW6692(card, W_IMASK); - if (debug & DEBUG_HW) - pr_notice("%s IMASK=%02x\n", card->name, val); - val = ReadW6692(card, W_D_EXIR); - if (debug & DEBUG_HW) - pr_notice("%s D_EXIR=%02x\n", card->name, val); - val = ReadW6692(card, W_D_EXIM); - if (debug & DEBUG_HW) - pr_notice("%s D_EXIM=%02x\n", card->name, val); - val = ReadW6692(card, W_D_RSTA); - if (debug & DEBUG_HW) - pr_notice("%s D_RSTA=%02x\n", card->name, val); - return 0; -} - -static void -release_card(struct w6692_hw *card) -{ - u_long flags; - - spin_lock_irqsave(&card->lock, flags); - disable_hwirq(card); - w6692_mode(&card->bc[0], ISDN_P_NONE); - w6692_mode(&card->bc[1], ISDN_P_NONE); - if ((card->fmask & led) || card->subtype == W6692_USR) { - card->xdata |= 0x04; /* LED OFF */ - WriteW6692(card, W_XDATA, card->xdata); - } - spin_unlock_irqrestore(&card->lock, flags); - free_irq(card->irq, card); - l1_event(card->dch.l1, CLOSE_CHANNEL); - mISDN_unregister_device(&card->dch.dev); - release_region(card->addr, 256); - mISDN_freebchannel(&card->bc[1].bch); - mISDN_freebchannel(&card->bc[0].bch); - mISDN_freedchannel(&card->dch); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - pci_disable_device(card->pdev); - pci_set_drvdata(card->pdev, NULL); - kfree(card); -} - -static int -setup_instance(struct w6692_hw *card) -{ - int i, err; - u_long flags; - - snprintf(card->name, MISDN_MAX_IDLEN - 1, "w6692.%d", w6692_cnt + 1); - write_lock_irqsave(&card_lock, flags); - list_add_tail(&card->list, &Cards); - write_unlock_irqrestore(&card_lock, flags); - card->fmask = (1 << w6692_cnt); - _set_debug(card); - spin_lock_init(&card->lock); - mISDN_initdchannel(&card->dch, MAX_DFRAME_LEN_L1, W6692_ph_bh); - card->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0); - card->dch.dev.D.send = w6692_l2l1D; - card->dch.dev.D.ctrl = w6692_dctrl; - card->dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | - (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); - card->dch.hw = card; - card->dch.dev.nrbchan = 2; - for (i = 0; i < 2; i++) { - mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM); - card->bc[i].bch.hw = card; - card->bc[i].bch.nr = i + 1; - card->bc[i].bch.ch.nr = i + 1; - card->bc[i].bch.ch.send = w6692_l2l1B; - card->bc[i].bch.ch.ctrl = w6692_bctrl; - set_channelmap(i + 1, card->dch.dev.channelmap); - list_add(&card->bc[i].bch.ch.list, &card->dch.dev.bchannels); - } - err = setup_w6692(card); - if (err) - goto error_setup; - err = mISDN_register_device(&card->dch.dev, &card->pdev->dev, - card->name); - if (err) - goto error_reg; - err = init_card(card); - if (err) - goto error_init; - err = create_l1(&card->dch, w6692_l1callback); - if (!err) { - w6692_cnt++; - pr_notice("W6692 %d cards installed\n", w6692_cnt); - return 0; - } - - free_irq(card->irq, card); -error_init: - mISDN_unregister_device(&card->dch.dev); -error_reg: - release_region(card->addr, 256); -error_setup: - mISDN_freebchannel(&card->bc[1].bch); - mISDN_freebchannel(&card->bc[0].bch); - mISDN_freedchannel(&card->dch); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - kfree(card); - return err; -} - -static int __devinit -w6692_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int err = -ENOMEM; - struct w6692_hw *card; - struct w6692map *m = (struct w6692map *)ent->driver_data; - - card = kzalloc(sizeof(struct w6692_hw), GFP_KERNEL); - if (!card) { - pr_info("No kmem for w6692 card\n"); - return err; - } - card->pdev = pdev; - card->subtype = m->subtype; - err = pci_enable_device(pdev); - if (err) { - kfree(card); - return err; - } - - printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n", - m->name, pci_name(pdev)); - - card->addr = pci_resource_start(pdev, 1); - card->irq = pdev->irq; - pci_set_drvdata(pdev, card); - err = setup_instance(card); - if (err) - pci_set_drvdata(pdev, NULL); - return err; -} - -static void __devexit -w6692_remove_pci(struct pci_dev *pdev) -{ - struct w6692_hw *card = pci_get_drvdata(pdev); - - if (card) - release_card(card); - else - if (debug) - pr_notice("%s: drvdata allready removed\n", __func__); -} - -static struct pci_device_id w6692_ids[] = { - { PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, (ulong)&w6692_map[0]}, - { PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, - PCI_VENDOR_ID_USR, PCI_DEVICE_ID_USR_6692, 0, 0, - (ulong)&w6692_map[2]}, - { PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, (ulong)&w6692_map[1]}, - { } -}; -MODULE_DEVICE_TABLE(pci, w6692_ids); - -static struct pci_driver w6692_driver = { - .name = "w6692", - .probe = w6692_probe, - .remove = __devexit_p(w6692_remove_pci), - .id_table = w6692_ids, -}; - -static int __init w6692_init(void) -{ - int err; - - pr_notice("Winbond W6692 PCI driver Rev. %s\n", W6692_REV); - - err = pci_register_driver(&w6692_driver); - return err; -} - -static void __exit w6692_cleanup(void) -{ - pci_unregister_driver(&w6692_driver); -} - -module_init(w6692_init); -module_exit(w6692_cleanup); diff --git a/trunk/drivers/isdn/hardware/mISDN/w6692.h b/trunk/drivers/isdn/hardware/mISDN/w6692.h deleted file mode 100644 index f95697757fd0..000000000000 --- a/trunk/drivers/isdn/hardware/mISDN/w6692.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Winbond W6692 specific defines - * - * Author Karsten Keil - * based on the w6692 I4L driver from Petr Novak - * - * Copyright 2009 by Karsten Keil - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* Specifications of W6692 registers */ - -#define W_D_RFIFO 0x00 /* R */ -#define W_D_XFIFO 0x04 /* W */ -#define W_D_CMDR 0x08 /* W */ -#define W_D_MODE 0x0c /* R/W */ -#define W_D_TIMR 0x10 /* R/W */ -#define W_ISTA 0x14 /* R_clr */ -#define W_IMASK 0x18 /* R/W */ -#define W_D_EXIR 0x1c /* R_clr */ -#define W_D_EXIM 0x20 /* R/W */ -#define W_D_STAR 0x24 /* R */ -#define W_D_RSTA 0x28 /* R */ -#define W_D_SAM 0x2c /* R/W */ -#define W_D_SAP1 0x30 /* R/W */ -#define W_D_SAP2 0x34 /* R/W */ -#define W_D_TAM 0x38 /* R/W */ -#define W_D_TEI1 0x3c /* R/W */ -#define W_D_TEI2 0x40 /* R/W */ -#define W_D_RBCH 0x44 /* R */ -#define W_D_RBCL 0x48 /* R */ -#define W_TIMR2 0x4c /* W */ -#define W_L1_RC 0x50 /* R/W */ -#define W_D_CTL 0x54 /* R/W */ -#define W_CIR 0x58 /* R */ -#define W_CIX 0x5c /* W */ -#define W_SQR 0x60 /* R */ -#define W_SQX 0x64 /* W */ -#define W_PCTL 0x68 /* R/W */ -#define W_MOR 0x6c /* R */ -#define W_MOX 0x70 /* R/W */ -#define W_MOSR 0x74 /* R_clr */ -#define W_MOCR 0x78 /* R/W */ -#define W_GCR 0x7c /* R/W */ - -#define W_B_RFIFO 0x80 /* R */ -#define W_B_XFIFO 0x84 /* W */ -#define W_B_CMDR 0x88 /* W */ -#define W_B_MODE 0x8c /* R/W */ -#define W_B_EXIR 0x90 /* R_clr */ -#define W_B_EXIM 0x94 /* R/W */ -#define W_B_STAR 0x98 /* R */ -#define W_B_ADM1 0x9c /* R/W */ -#define W_B_ADM2 0xa0 /* R/W */ -#define W_B_ADR1 0xa4 /* R/W */ -#define W_B_ADR2 0xa8 /* R/W */ -#define W_B_RBCL 0xac /* R */ -#define W_B_RBCH 0xb0 /* R */ - -#define W_XADDR 0xf4 /* R/W */ -#define W_XDATA 0xf8 /* R/W */ -#define W_EPCTL 0xfc /* W */ - -/* W6692 register bits */ - -#define W_D_CMDR_XRST 0x01 -#define W_D_CMDR_XME 0x02 -#define W_D_CMDR_XMS 0x08 -#define W_D_CMDR_STT 0x10 -#define W_D_CMDR_RRST 0x40 -#define W_D_CMDR_RACK 0x80 - -#define W_D_MODE_RLP 0x01 -#define W_D_MODE_DLP 0x02 -#define W_D_MODE_MFD 0x04 -#define W_D_MODE_TEE 0x08 -#define W_D_MODE_TMS 0x10 -#define W_D_MODE_RACT 0x40 -#define W_D_MODE_MMS 0x80 - -#define W_INT_B2_EXI 0x01 -#define W_INT_B1_EXI 0x02 -#define W_INT_D_EXI 0x04 -#define W_INT_XINT0 0x08 -#define W_INT_XINT1 0x10 -#define W_INT_D_XFR 0x20 -#define W_INT_D_RME 0x40 -#define W_INT_D_RMR 0x80 - -#define W_D_EXI_WEXP 0x01 -#define W_D_EXI_TEXP 0x02 -#define W_D_EXI_ISC 0x04 -#define W_D_EXI_MOC 0x08 -#define W_D_EXI_TIN2 0x10 -#define W_D_EXI_XCOL 0x20 -#define W_D_EXI_XDUN 0x40 -#define W_D_EXI_RDOV 0x80 - -#define W_D_STAR_DRDY 0x10 -#define W_D_STAR_XBZ 0x20 -#define W_D_STAR_XDOW 0x80 - -#define W_D_RSTA_RMB 0x10 -#define W_D_RSTA_CRCE 0x20 -#define W_D_RSTA_RDOV 0x40 - -#define W_D_CTL_SRST 0x20 - -#define W_CIR_SCC 0x80 -#define W_CIR_ICC 0x40 -#define W_CIR_COD_MASK 0x0f - -#define W_PCTL_PCX 0x01 -#define W_PCTL_XMODE 0x02 -#define W_PCTL_OE0 0x04 -#define W_PCTL_OE1 0x08 -#define W_PCTL_OE2 0x10 -#define W_PCTL_OE3 0x20 -#define W_PCTL_OE4 0x40 -#define W_PCTL_OE5 0x80 - -#define W_B_CMDR_XRST 0x01 -#define W_B_CMDR_XME 0x02 -#define W_B_CMDR_XMS 0x04 -#define W_B_CMDR_RACT 0x20 -#define W_B_CMDR_RRST 0x40 -#define W_B_CMDR_RACK 0x80 - -#define W_B_MODE_FTS0 0x01 -#define W_B_MODE_FTS1 0x02 -#define W_B_MODE_SW56 0x04 -#define W_B_MODE_BSW0 0x08 -#define W_B_MODE_BSW1 0x10 -#define W_B_MODE_EPCM 0x20 -#define W_B_MODE_ITF 0x40 -#define W_B_MODE_MMS 0x80 - -#define W_B_EXI_XDUN 0x01 -#define W_B_EXI_XFR 0x02 -#define W_B_EXI_RDOV 0x10 -#define W_B_EXI_RME 0x20 -#define W_B_EXI_RMR 0x40 - -#define W_B_STAR_XBZ 0x01 -#define W_B_STAR_XDOW 0x04 -#define W_B_STAR_RMB 0x10 -#define W_B_STAR_CRCE 0x20 -#define W_B_STAR_RDOV 0x40 - -#define W_B_RBCH_LOV 0x20 - -/* W6692 Layer1 commands */ - -#define W_L1CMD_ECK 0x00 -#define W_L1CMD_RST 0x01 -#define W_L1CMD_SCP 0x04 -#define W_L1CMD_SSP 0x02 -#define W_L1CMD_AR8 0x08 -#define W_L1CMD_AR10 0x09 -#define W_L1CMD_EAL 0x0a -#define W_L1CMD_DRC 0x0f - -/* W6692 Layer1 indications */ - -#define W_L1IND_CE 0x07 -#define W_L1IND_DRD 0x00 -#define W_L1IND_LD 0x04 -#define W_L1IND_ARD 0x08 -#define W_L1IND_TI 0x0a -#define W_L1IND_ATI 0x0b -#define W_L1IND_AI8 0x0c -#define W_L1IND_AI10 0x0d -#define W_L1IND_CD 0x0f - -/* FIFO thresholds */ -#define W_D_FIFO_THRESH 64 -#define W_B_FIFO_THRESH 64 diff --git a/trunk/drivers/isdn/hisax/Kconfig b/trunk/drivers/isdn/hisax/Kconfig index 3464ebc4cdbc..7832d8ba8e44 100644 --- a/trunk/drivers/isdn/hisax/Kconfig +++ b/trunk/drivers/isdn/hisax/Kconfig @@ -391,7 +391,6 @@ comment "HiSax sub driver modules" config HISAX_ST5481 tristate "ST5481 USB ISDN modem (EXPERIMENTAL)" depends on USB && EXPERIMENTAL - select ISDN_HDLC select CRC_CCITT select BITREVERSE help @@ -419,6 +418,11 @@ config HISAX_FRITZ_PCIPNP (the latter also needs you to select "ISA Plug and Play support" from the menu "Plug and Play configuration") +config HISAX_HDLC + bool + depends on HISAX_ST5481 + default y + config HISAX_AVM_A1_PCMCIA bool depends on HISAX_AVM_A1_CS diff --git a/trunk/drivers/isdn/hisax/Makefile b/trunk/drivers/isdn/hisax/Makefile index ab638b083df9..c7a3794bdae4 100644 --- a/trunk/drivers/isdn/hisax/Makefile +++ b/trunk/drivers/isdn/hisax/Makefile @@ -16,6 +16,10 @@ obj-$(CONFIG_HISAX_HFCUSB) += hfc_usb.o obj-$(CONFIG_HISAX_HFC4S8S) += hfc4s8s_l1.o obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o +ifdef CONFIG_HISAX_HDLC +obj-$(CONFIG_ISDN_DRV_HISAX) += isdnhdlc.o +endif + # Multipart objects. hisax_st5481-y := st5481_init.o st5481_usb.o st5481_d.o \ diff --git a/trunk/drivers/isdn/hisax/amd7930_fn.c b/trunk/drivers/isdn/hisax/amd7930_fn.c index bf526a7a63af..341faf58a65c 100644 --- a/trunk/drivers/isdn/hisax/amd7930_fn.c +++ b/trunk/drivers/isdn/hisax/amd7930_fn.c @@ -238,6 +238,8 @@ Amd7930_bh(struct work_struct *work) container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; + if (!cs) + return; if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { if (cs->debug) debugl1(cs, "Amd7930: bh, D-Channel Busy cleared"); diff --git a/trunk/drivers/isdn/hisax/callc.c b/trunk/drivers/isdn/hisax/callc.c index 475b1a020003..025a20d487c5 100644 --- a/trunk/drivers/isdn/hisax/callc.c +++ b/trunk/drivers/isdn/hisax/callc.c @@ -833,6 +833,8 @@ static struct FsmNode fnlist[] __initdata = }; /* *INDENT-ON* */ +#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode)) + int __init CallcNew(void) { @@ -840,7 +842,7 @@ CallcNew(void) callcfsm.event_count = EVENT_COUNT; callcfsm.strEvent = strEvent; callcfsm.strState = strState; - return FsmNew(&callcfsm, fnlist, ARRAY_SIZE(fnlist)); + return FsmNew(&callcfsm, fnlist, FNCOUNT); } void diff --git a/trunk/drivers/isdn/hisax/hfc_pci.c b/trunk/drivers/isdn/hisax/hfc_pci.c index d110a77940a4..3d337d924c23 100644 --- a/trunk/drivers/isdn/hisax/hfc_pci.c +++ b/trunk/drivers/isdn/hisax/hfc_pci.c @@ -1506,6 +1506,8 @@ hfcpci_bh(struct work_struct *work) u_long flags; // struct PStack *stptr; + if (!cs) + return; if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { if (!cs->hw.hfcpci.nt_mode) switch (cs->dc.hfcpci.ph_state) { diff --git a/trunk/drivers/isdn/hisax/hfc_sx.c b/trunk/drivers/isdn/hisax/hfc_sx.c index 419f87cad8cb..d92e8d6c2ae2 100644 --- a/trunk/drivers/isdn/hisax/hfc_sx.c +++ b/trunk/drivers/isdn/hisax/hfc_sx.c @@ -1255,6 +1255,8 @@ hfcsx_bh(struct work_struct *work) container_of(work, struct IsdnCardState, tqueue); u_long flags; + if (!cs) + return; if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { if (!cs->hw.hfcsx.nt_mode) switch (cs->dc.hfcsx.ph_state) { diff --git a/trunk/drivers/isdn/hisax/icc.c b/trunk/drivers/isdn/hisax/icc.c index 9aba646ba221..682cac32f259 100644 --- a/trunk/drivers/isdn/hisax/icc.c +++ b/trunk/drivers/isdn/hisax/icc.c @@ -83,6 +83,8 @@ icc_bh(struct work_struct *work) container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; + if (!cs) + return; if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { if (cs->debug) debugl1(cs, "D-Channel Busy cleared"); diff --git a/trunk/drivers/isdn/hisax/isac.c b/trunk/drivers/isdn/hisax/isac.c index a19354d94343..07b1673122b8 100644 --- a/trunk/drivers/isdn/hisax/isac.c +++ b/trunk/drivers/isdn/hisax/isac.c @@ -86,6 +86,8 @@ isac_bh(struct work_struct *work) container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; + if (!cs) + return; if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { if (cs->debug) debugl1(cs, "D-Channel Busy cleared"); diff --git a/trunk/drivers/isdn/i4l/isdnhdlc.c b/trunk/drivers/isdn/hisax/isdnhdlc.c similarity index 54% rename from trunk/drivers/isdn/i4l/isdnhdlc.c rename to trunk/drivers/isdn/hisax/isdnhdlc.c index c989aa35dc2f..c69a77a80062 100644 --- a/trunk/drivers/isdn/i4l/isdnhdlc.c +++ b/trunk/drivers/isdn/hisax/isdnhdlc.c @@ -1,32 +1,29 @@ /* * isdnhdlc.c -- General purpose ISDN HDLC decoder. * - * Copyright (C) - * 2009 Karsten Keil - * 2002 Wolfgang Mües - * 2001 Frode Isaksen - * 2001 Kai Germaschewski + *Copyright (C) 2002 Wolfgang Mües + * 2001 Frode Isaksen + * 2001 Kai Germaschewski * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include -#include -#include +#include "isdnhdlc.h" /*-------------------------------------------------------------------*/ @@ -39,32 +36,44 @@ MODULE_LICENSE("GPL"); /*-------------------------------------------------------------------*/ enum { - HDLC_FAST_IDLE, HDLC_GET_FLAG_B0, HDLC_GETFLAG_B1A6, HDLC_GETFLAG_B7, - HDLC_GET_DATA, HDLC_FAST_FLAG + HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7, + HDLC_GET_DATA,HDLC_FAST_FLAG }; enum { - HDLC_SEND_DATA, HDLC_SEND_CRC1, HDLC_SEND_FAST_FLAG, - HDLC_SEND_FIRST_FLAG, HDLC_SEND_CRC2, HDLC_SEND_CLOSING_FLAG, - HDLC_SEND_IDLE1, HDLC_SEND_FAST_IDLE, HDLC_SENDFLAG_B0, - HDLC_SENDFLAG_B1A6, HDLC_SENDFLAG_B7, STOPPED, HDLC_SENDFLAG_ONE + HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG, + HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG, + HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0, + HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED }; -void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, u32 features) +void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56) { - memset(hdlc, 0, sizeof(struct isdnhdlc_vars)); + hdlc->bit_shift = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->ffbit_shift = 0; + hdlc->data_received = 0; hdlc->state = HDLC_GET_DATA; - if (features & HDLC_56KBIT) - hdlc->do_adapt56 = 1; - if (features & HDLC_BITREVERSE) - hdlc->do_bitreverse = 1; + hdlc->do_adapt56 = do_adapt56; + hdlc->dchannel = 0; + hdlc->crc = 0; + hdlc->cbin = 0; + hdlc->shift_reg = 0; + hdlc->ffvalue = 0; + hdlc->dstpos = 0; } -EXPORT_SYMBOL(isdnhdlc_out_init); -void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, u32 features) +void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56) { - memset(hdlc, 0, sizeof(struct isdnhdlc_vars)); - if (features & HDLC_DCHANNEL) { + hdlc->bit_shift = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->ffbit_shift = 0; + hdlc->data_received = 0; + hdlc->do_closing = 0; + hdlc->ffvalue = 0; + if (is_d_channel) { hdlc->dchannel = 1; hdlc->state = HDLC_SEND_FIRST_FLAG; } else { @@ -73,32 +82,16 @@ void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, u32 features) hdlc->ffvalue = 0x7e; } hdlc->cbin = 0x7e; - if (features & HDLC_56KBIT) { + hdlc->bit_shift = 0; + if(do_adapt56){ hdlc->do_adapt56 = 1; + hdlc->data_bits = 0; hdlc->state = HDLC_SENDFLAG_B0; - } else + } else { + hdlc->do_adapt56 = 0; hdlc->data_bits = 8; - if (features & HDLC_BITREVERSE) - hdlc->do_bitreverse = 1; -} -EXPORT_SYMBOL(isdnhdlc_rcv_init); - -static int -check_frame(struct isdnhdlc_vars *hdlc) -{ - int status; - - if (hdlc->dstpos < 2) /* too small - framing error */ - status = -HDLC_FRAMING_ERROR; - else if (hdlc->crc != 0xf0b8) /* crc error */ - status = -HDLC_CRC_ERROR; - else { - /* remove CRC */ - hdlc->dstpos -= 2; - /* good frame */ - status = hdlc->dstpos; } - return status; + hdlc->shift_reg = 0; } /* @@ -128,67 +121,40 @@ check_frame(struct isdnhdlc_vars *hdlc) returns - number of decoded bytes in the destination buffer and status flag. */ -int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, - int *count, u8 *dst, int dsize) +int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, + int slen, int *count, unsigned char *dst, int dsize) { - int status = 0; + int status=0; - static const unsigned char fast_flag[] = { - 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f + static const unsigned char fast_flag[]={ + 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f }; - static const unsigned char fast_flag_value[] = { - 0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f + static const unsigned char fast_flag_value[]={ + 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f }; - static const unsigned char fast_abort[] = { - 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff + static const unsigned char fast_abort[]={ + 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; -#define handle_fast_flag(h) \ - do {\ - if (h->cbin == fast_flag[h->bit_shift]) {\ - h->ffvalue = fast_flag_value[h->bit_shift];\ - h->state = HDLC_FAST_FLAG;\ - h->ffbit_shift = h->bit_shift;\ - h->bit_shift = 1;\ - } else {\ - h->state = HDLC_GET_DATA;\ - h->data_received = 0;\ - } \ - } while (0) - -#define handle_abort(h) \ - do {\ - h->shift_reg = fast_abort[h->ffbit_shift - 1];\ - h->hdlc_bits1 = h->ffbit_shift - 2;\ - if (h->hdlc_bits1 < 0)\ - h->hdlc_bits1 = 0;\ - h->data_bits = h->ffbit_shift - 1;\ - h->state = HDLC_GET_DATA;\ - h->data_received = 0;\ - } while (0) - *count = slen; - while (slen > 0) { - if (hdlc->bit_shift == 0) { - /* the code is for bitreverse streams */ - if (hdlc->do_bitreverse == 0) - hdlc->cbin = bitrev8(*src++); - else - hdlc->cbin = *src++; + while(slen > 0){ + if(hdlc->bit_shift==0){ + hdlc->cbin = *src++; slen--; hdlc->bit_shift = 8; - if (hdlc->do_adapt56) - hdlc->bit_shift--; + if(hdlc->do_adapt56){ + hdlc->bit_shift --; + } } - switch (hdlc->state) { + switch(hdlc->state){ case STOPPED: return 0; case HDLC_FAST_IDLE: - if (hdlc->cbin == 0xff) { + if(hdlc->cbin == 0xff){ hdlc->bit_shift = 0; break; } @@ -197,30 +163,32 @@ int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, hdlc->bit_shift = 8; break; case HDLC_GET_FLAG_B0: - if (!(hdlc->cbin & 0x80)) { + if(!(hdlc->cbin & 0x80)) { hdlc->state = HDLC_GETFLAG_B1A6; hdlc->hdlc_bits1 = 0; } else { - if ((!hdlc->do_adapt56) && - (++hdlc->hdlc_bits1 >= 8) && - (hdlc->bit_shift == 1)) + if(!hdlc->do_adapt56){ + if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1) hdlc->state = HDLC_FAST_IDLE; + } } - hdlc->cbin <<= 1; - hdlc->bit_shift--; + hdlc->cbin<<=1; + hdlc->bit_shift --; break; case HDLC_GETFLAG_B1A6: - if (hdlc->cbin & 0x80) { + if(hdlc->cbin & 0x80){ hdlc->hdlc_bits1++; - if (hdlc->hdlc_bits1 == 6) + if(hdlc->hdlc_bits1==6){ hdlc->state = HDLC_GETFLAG_B7; - } else + } + } else { hdlc->hdlc_bits1 = 0; - hdlc->cbin <<= 1; - hdlc->bit_shift--; + } + hdlc->cbin<<=1; + hdlc->bit_shift --; break; case HDLC_GETFLAG_B7: - if (hdlc->cbin & 0x80) { + if(hdlc->cbin & 0x80) { hdlc->state = HDLC_GET_FLAG_B0; } else { hdlc->state = HDLC_GET_DATA; @@ -230,55 +198,74 @@ int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, hdlc->data_bits = 0; hdlc->data_received = 0; } - hdlc->cbin <<= 1; - hdlc->bit_shift--; + hdlc->cbin<<=1; + hdlc->bit_shift --; break; case HDLC_GET_DATA: - if (hdlc->cbin & 0x80) { + if(hdlc->cbin & 0x80){ hdlc->hdlc_bits1++; - switch (hdlc->hdlc_bits1) { + switch(hdlc->hdlc_bits1){ case 6: break; case 7: - if (hdlc->data_received) - /* bad frame */ + if(hdlc->data_received) { + // bad frame status = -HDLC_FRAMING_ERROR; - if (!hdlc->do_adapt56) { - if (hdlc->cbin == fast_abort - [hdlc->bit_shift + 1]) { - hdlc->state = - HDLC_FAST_IDLE; - hdlc->bit_shift = 1; + } + if(!hdlc->do_adapt56){ + if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){ + hdlc->state = HDLC_FAST_IDLE; + hdlc->bit_shift=1; break; } - } else + } else { hdlc->state = HDLC_GET_FLAG_B0; + } break; default: - hdlc->shift_reg >>= 1; + hdlc->shift_reg>>=1; hdlc->shift_reg |= 0x80; hdlc->data_bits++; break; } } else { - switch (hdlc->hdlc_bits1) { + switch(hdlc->hdlc_bits1){ case 5: break; case 6: - if (hdlc->data_received) - status = check_frame(hdlc); + if(hdlc->data_received){ + if (hdlc->dstpos < 2) { + status = -HDLC_FRAMING_ERROR; + } else if (hdlc->crc != 0xf0b8){ + // crc error + status = -HDLC_CRC_ERROR; + } else { + // remove CRC + hdlc->dstpos -= 2; + // good frame + status = hdlc->dstpos; + } + } hdlc->crc = 0xffff; hdlc->shift_reg = 0; hdlc->data_bits = 0; - if (!hdlc->do_adapt56) - handle_fast_flag(hdlc); - else { + if(!hdlc->do_adapt56){ + if(hdlc->cbin==fast_flag[hdlc->bit_shift]){ + hdlc->ffvalue = fast_flag_value[hdlc->bit_shift]; + hdlc->state = HDLC_FAST_FLAG; + hdlc->ffbit_shift = hdlc->bit_shift; + hdlc->bit_shift = 1; + } else { + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } + } else { hdlc->state = HDLC_GET_DATA; hdlc->data_received = 0; } break; default: - hdlc->shift_reg >>= 1; + hdlc->shift_reg>>=1; hdlc->data_bits++; break; } @@ -291,17 +278,16 @@ int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, hdlc->bit_shift--; return status; } - if (hdlc->data_bits == 8) { + if(hdlc->data_bits==8){ hdlc->data_bits = 0; hdlc->data_received = 1; - hdlc->crc = crc_ccitt_byte(hdlc->crc, - hdlc->shift_reg); + hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); - /* good byte received */ - if (hdlc->dstpos < dsize) + // good byte received + if (hdlc->dstpos < dsize) { dst[hdlc->dstpos++] = hdlc->shift_reg; - else { - /* frame too long */ + } else { + // frame too long status = -HDLC_LENGTH_ERROR; hdlc->dstpos = 0; } @@ -310,18 +296,24 @@ int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, hdlc->bit_shift--; break; case HDLC_FAST_FLAG: - if (hdlc->cbin == hdlc->ffvalue) { + if(hdlc->cbin==hdlc->ffvalue){ hdlc->bit_shift = 0; break; } else { - if (hdlc->cbin == 0xff) { + if(hdlc->cbin == 0xff){ hdlc->state = HDLC_FAST_IDLE; - hdlc->bit_shift = 0; - } else if (hdlc->ffbit_shift == 8) { + hdlc->bit_shift=0; + } else if(hdlc->ffbit_shift==8){ hdlc->state = HDLC_GETFLAG_B7; break; - } else - handle_abort(hdlc); + } else { + hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1]; + hdlc->hdlc_bits1 = hdlc->ffbit_shift-2; + if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0; + hdlc->data_bits = hdlc->ffbit_shift-1; + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } } break; default: @@ -331,7 +323,7 @@ int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen, *count -= slen; return 0; } -EXPORT_SYMBOL(isdnhdlc_decode); + /* isdnhdlc_encode - encodes HDLC frames to a transparent bit stream. @@ -351,70 +343,59 @@ EXPORT_SYMBOL(isdnhdlc_decode); dsize - destination buffer size returns - number of encoded bytes in the destination buffer */ -int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, - int *count, u8 *dst, int dsize) +int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, + unsigned short slen, int *count, + unsigned char *dst, int dsize) { static const unsigned char xfast_flag_value[] = { - 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e + 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e }; int len = 0; *count = slen; - /* special handling for one byte frames */ - if ((slen == 1) && (hdlc->state == HDLC_SEND_FAST_FLAG)) - hdlc->state = HDLC_SENDFLAG_ONE; while (dsize > 0) { - if (hdlc->bit_shift == 0) { - if (slen && !hdlc->do_closing) { + if(hdlc->bit_shift==0){ + if(slen && !hdlc->do_closing){ hdlc->shift_reg = *src++; slen--; if (slen == 0) - /* closing sequence, CRC + flag(s) */ - hdlc->do_closing = 1; + hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */ hdlc->bit_shift = 8; } else { - if (hdlc->state == HDLC_SEND_DATA) { - if (hdlc->data_received) { + if(hdlc->state == HDLC_SEND_DATA){ + if(hdlc->data_received){ hdlc->state = HDLC_SEND_CRC1; hdlc->crc ^= 0xffff; hdlc->bit_shift = 8; - hdlc->shift_reg = - hdlc->crc & 0xff; - } else if (!hdlc->do_adapt56) - hdlc->state = - HDLC_SEND_FAST_FLAG; - else - hdlc->state = - HDLC_SENDFLAG_B0; + hdlc->shift_reg = hdlc->crc & 0xff; + } else if(!hdlc->do_adapt56){ + hdlc->state = HDLC_SEND_FAST_FLAG; + } else { + hdlc->state = HDLC_SENDFLAG_B0; + } } } } - switch (hdlc->state) { + switch(hdlc->state){ case STOPPED: while (dsize--) *dst++ = 0xff; + return dsize; case HDLC_SEND_FAST_FLAG: hdlc->do_closing = 0; - if (slen == 0) { - /* the code is for bitreverse streams */ - if (hdlc->do_bitreverse == 0) - *dst++ = bitrev8(hdlc->ffvalue); - else - *dst++ = hdlc->ffvalue; + if(slen == 0){ + *dst++ = hdlc->ffvalue; len++; dsize--; break; } - /* fall through */ - case HDLC_SENDFLAG_ONE: - if (hdlc->bit_shift == 8) { - hdlc->cbin = hdlc->ffvalue >> - (8 - hdlc->data_bits); + if(hdlc->bit_shift==8){ + hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits); hdlc->state = HDLC_SEND_DATA; hdlc->crc = 0xffff; hdlc->hdlc_bits1 = 0; @@ -432,17 +413,17 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, hdlc->cbin <<= 1; hdlc->data_bits++; hdlc->cbin++; - if (++hdlc->hdlc_bits1 == 6) + if(++hdlc->hdlc_bits1 == 6) hdlc->state = HDLC_SENDFLAG_B7; break; case HDLC_SENDFLAG_B7: hdlc->cbin <<= 1; hdlc->data_bits++; - if (slen == 0) { + if(slen == 0){ hdlc->state = HDLC_SENDFLAG_B0; break; } - if (hdlc->bit_shift == 8) { + if(hdlc->bit_shift==8){ hdlc->state = HDLC_SEND_DATA; hdlc->crc = 0xffff; hdlc->hdlc_bits1 = 0; @@ -451,7 +432,7 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, break; case HDLC_SEND_FIRST_FLAG: hdlc->data_received = 1; - if (hdlc->data_bits == 8) { + if(hdlc->data_bits==8){ hdlc->state = HDLC_SEND_DATA; hdlc->crc = 0xffff; hdlc->hdlc_bits1 = 0; @@ -459,11 +440,11 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, } hdlc->cbin <<= 1; hdlc->data_bits++; - if (hdlc->shift_reg & 0x01) + if(hdlc->shift_reg & 0x01) hdlc->cbin++; hdlc->shift_reg >>= 1; hdlc->bit_shift--; - if (hdlc->bit_shift == 0) { + if(hdlc->bit_shift==0){ hdlc->state = HDLC_SEND_DATA; hdlc->crc = 0xffff; hdlc->hdlc_bits1 = 0; @@ -472,14 +453,14 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, case HDLC_SEND_DATA: hdlc->cbin <<= 1; hdlc->data_bits++; - if (hdlc->hdlc_bits1 == 5) { + if(hdlc->hdlc_bits1 == 5){ hdlc->hdlc_bits1 = 0; break; } - if (hdlc->bit_shift == 8) - hdlc->crc = crc_ccitt_byte(hdlc->crc, - hdlc->shift_reg); - if (hdlc->shift_reg & 0x01) { + if(hdlc->bit_shift==8){ + hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg); + } + if(hdlc->shift_reg & 0x01){ hdlc->hdlc_bits1++; hdlc->cbin++; hdlc->shift_reg >>= 1; @@ -493,11 +474,11 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, case HDLC_SEND_CRC1: hdlc->cbin <<= 1; hdlc->data_bits++; - if (hdlc->hdlc_bits1 == 5) { + if(hdlc->hdlc_bits1 == 5){ hdlc->hdlc_bits1 = 0; break; } - if (hdlc->shift_reg & 0x01) { + if(hdlc->shift_reg & 0x01){ hdlc->hdlc_bits1++; hdlc->cbin++; hdlc->shift_reg >>= 1; @@ -507,7 +488,7 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, hdlc->shift_reg >>= 1; hdlc->bit_shift--; } - if (hdlc->bit_shift == 0) { + if(hdlc->bit_shift==0){ hdlc->shift_reg = (hdlc->crc >> 8); hdlc->state = HDLC_SEND_CRC2; hdlc->bit_shift = 8; @@ -516,11 +497,11 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, case HDLC_SEND_CRC2: hdlc->cbin <<= 1; hdlc->data_bits++; - if (hdlc->hdlc_bits1 == 5) { + if(hdlc->hdlc_bits1 == 5){ hdlc->hdlc_bits1 = 0; break; } - if (hdlc->shift_reg & 0x01) { + if(hdlc->shift_reg & 0x01){ hdlc->hdlc_bits1++; hdlc->cbin++; hdlc->shift_reg >>= 1; @@ -530,7 +511,7 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, hdlc->shift_reg >>= 1; hdlc->bit_shift--; } - if (hdlc->bit_shift == 0) { + if(hdlc->bit_shift==0){ hdlc->shift_reg = 0x7e; hdlc->state = HDLC_SEND_CLOSING_FLAG; hdlc->bit_shift = 8; @@ -539,36 +520,33 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, case HDLC_SEND_CLOSING_FLAG: hdlc->cbin <<= 1; hdlc->data_bits++; - if (hdlc->hdlc_bits1 == 5) { + if(hdlc->hdlc_bits1 == 5){ hdlc->hdlc_bits1 = 0; break; } - if (hdlc->shift_reg & 0x01) + if(hdlc->shift_reg & 0x01){ hdlc->cbin++; + } hdlc->shift_reg >>= 1; hdlc->bit_shift--; - if (hdlc->bit_shift == 0) { - hdlc->ffvalue = - xfast_flag_value[hdlc->data_bits]; - if (hdlc->dchannel) { + if(hdlc->bit_shift==0){ + hdlc->ffvalue = xfast_flag_value[hdlc->data_bits]; + if(hdlc->dchannel){ hdlc->ffvalue = 0x7e; hdlc->state = HDLC_SEND_IDLE1; hdlc->bit_shift = 8-hdlc->data_bits; - if (hdlc->bit_shift == 0) - hdlc->state = - HDLC_SEND_FAST_IDLE; + if(hdlc->bit_shift==0) + hdlc->state = HDLC_SEND_FAST_IDLE; } else { - if (!hdlc->do_adapt56) { - hdlc->state = - HDLC_SEND_FAST_FLAG; + if(!hdlc->do_adapt56){ + hdlc->state = HDLC_SEND_FAST_FLAG; hdlc->data_received = 0; } else { hdlc->state = HDLC_SENDFLAG_B0; hdlc->data_received = 0; } - /* Finished this frame, send flags */ - if (dsize > 1) - dsize = 1; + // Finished with this frame, send flags + if (dsize > 1) dsize = 1; } } break; @@ -578,7 +556,7 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, hdlc->cbin++; hdlc->data_bits++; hdlc->bit_shift--; - if (hdlc->bit_shift == 0) { + if(hdlc->bit_shift==0){ hdlc->state = HDLC_SEND_FAST_IDLE; hdlc->bit_shift = 0; } @@ -587,17 +565,12 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, hdlc->do_closing = 0; hdlc->cbin = 0xff; hdlc->data_bits = 8; - if (hdlc->bit_shift == 8) { + if(hdlc->bit_shift == 8){ hdlc->cbin = 0x7e; hdlc->state = HDLC_SEND_FIRST_FLAG; } else { - /* the code is for bitreverse streams */ - if (hdlc->do_bitreverse == 0) - *dst++ = bitrev8(hdlc->cbin); - else - *dst++ = hdlc->cbin; - hdlc->bit_shift = 0; - hdlc->data_bits = 0; + *dst++ = hdlc->cbin; + hdlc->bit_shift = hdlc->data_bits = 0; len++; dsize = 0; } @@ -605,19 +578,15 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, default: break; } - if (hdlc->do_adapt56) { - if (hdlc->data_bits == 7) { + if(hdlc->do_adapt56){ + if(hdlc->data_bits==7){ hdlc->cbin <<= 1; hdlc->cbin++; hdlc->data_bits++; } } - if (hdlc->data_bits == 8) { - /* the code is for bitreverse streams */ - if (hdlc->do_bitreverse == 0) - *dst++ = bitrev8(hdlc->cbin); - else - *dst++ = hdlc->cbin; + if(hdlc->data_bits==8){ + *dst++ = hdlc->cbin; hdlc->data_bits = 0; len++; dsize--; @@ -627,4 +596,8 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, return len; } + +EXPORT_SYMBOL(isdnhdlc_rcv_init); +EXPORT_SYMBOL(isdnhdlc_decode); +EXPORT_SYMBOL(isdnhdlc_out_init); EXPORT_SYMBOL(isdnhdlc_encode); diff --git a/trunk/drivers/isdn/hisax/isdnhdlc.h b/trunk/drivers/isdn/hisax/isdnhdlc.h new file mode 100644 index 000000000000..cf0a95a24015 --- /dev/null +++ b/trunk/drivers/isdn/hisax/isdnhdlc.h @@ -0,0 +1,70 @@ +/* + * isdnhdlc.h -- General purpose ISDN HDLC decoder. + * + * Implementation of a HDLC decoder/encoder in software. + * Neccessary because some ISDN devices don't have HDLC + * controllers. Also included: a bit reversal table. + * + *Copyright (C) 2002 Wolfgang Mües + * 2001 Frode Isaksen + * 2001 Kai Germaschewski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ISDNHDLC_H__ +#define __ISDNHDLC_H__ + +struct isdnhdlc_vars { + int bit_shift; + int hdlc_bits1; + int data_bits; + int ffbit_shift; // encoding only + int state; + int dstpos; + + unsigned short crc; + + unsigned char cbin; + unsigned char shift_reg; + unsigned char ffvalue; + + unsigned int data_received:1; // set if transferring data + unsigned int dchannel:1; // set if D channel (send idle instead of flags) + unsigned int do_adapt56:1; // set if 56K adaptation + unsigned int do_closing:1; // set if in closing phase (need to send CRC + flag +}; + + +/* + The return value from isdnhdlc_decode is + the frame length, 0 if no complete frame was decoded, + or a negative error number +*/ +#define HDLC_FRAMING_ERROR 1 +#define HDLC_CRC_ERROR 2 +#define HDLC_LENGTH_ERROR 3 + +extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56); + +extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count, + unsigned char *dst, int dsize); + +extern void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc,int is_d_channel,int do_adapt56); + +extern int isdnhdlc_encode (struct isdnhdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count, + unsigned char *dst,int dsize); + +#endif /* __ISDNHDLC_H__ */ diff --git a/trunk/drivers/isdn/hisax/isdnl1.c b/trunk/drivers/isdn/hisax/isdnl1.c index 9ce6abe05b1a..317f16f516f2 100644 --- a/trunk/drivers/isdn/hisax/isdnl1.c +++ b/trunk/drivers/isdn/hisax/isdnl1.c @@ -647,6 +647,8 @@ static struct FsmNode L1SFnList[] __initdata = {ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact}, }; +#define L1S_FN_COUNT (sizeof(L1SFnList)/sizeof(struct FsmNode)) + #ifdef HISAX_UINTERFACE static void l1_deact_req_u(struct FsmInst *fi, int event, void *arg) @@ -704,6 +706,8 @@ static struct FsmNode L1UFnList[] __initdata = {ST_L1_RESET, EV_TIMER_DEACT, l1_timer_deact}, }; +#define L1U_FN_COUNT (sizeof(L1UFnList)/sizeof(struct FsmNode)) + #endif static void @@ -750,6 +754,8 @@ static struct FsmNode L1BFnList[] __initdata = {ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact}, }; +#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode)) + int __init Isdnl1New(void) { @@ -759,7 +765,7 @@ Isdnl1New(void) l1fsm_s.event_count = L1_EVENT_COUNT; l1fsm_s.strEvent = strL1Event; l1fsm_s.strState = strL1SState; - retval = FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList)); + retval = FsmNew(&l1fsm_s, L1SFnList, L1S_FN_COUNT); if (retval) return retval; @@ -767,7 +773,7 @@ Isdnl1New(void) l1fsm_b.event_count = L1_EVENT_COUNT; l1fsm_b.strEvent = strL1Event; l1fsm_b.strState = strL1BState; - retval = FsmNew(&l1fsm_b, L1BFnList, ARRAY_SIZE(L1BFnList)); + retval = FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT); if (retval) { FsmFree(&l1fsm_s); return retval; @@ -777,7 +783,7 @@ Isdnl1New(void) l1fsm_u.event_count = L1_EVENT_COUNT; l1fsm_u.strEvent = strL1Event; l1fsm_u.strState = strL1UState; - retval = FsmNew(&l1fsm_u, L1UFnList, ARRAY_SIZE(L1UFnList)); + retval = FsmNew(&l1fsm_u, L1UFnList, L1U_FN_COUNT); if (retval) { FsmFree(&l1fsm_s); FsmFree(&l1fsm_b); diff --git a/trunk/drivers/isdn/hisax/isdnl2.c b/trunk/drivers/isdn/hisax/isdnl2.c index 7b9496a63b5f..3446f249d675 100644 --- a/trunk/drivers/isdn/hisax/isdnl2.c +++ b/trunk/drivers/isdn/hisax/isdnl2.c @@ -1623,6 +1623,8 @@ static struct FsmNode L2FnList[] __initdata = {ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da}, }; +#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode)) + static void isdnl2_l1l2(struct PStack *st, int pr, void *arg) { @@ -1834,7 +1836,7 @@ Isdnl2New(void) l2fsm.event_count = L2_EVENT_COUNT; l2fsm.strEvent = strL2Event; l2fsm.strState = strL2State; - return FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList)); + return FsmNew(&l2fsm, L2FnList, L2_FN_COUNT); } void diff --git a/trunk/drivers/isdn/hisax/isdnl3.c b/trunk/drivers/isdn/hisax/isdnl3.c index 06766022d3ae..935f23356fae 100644 --- a/trunk/drivers/isdn/hisax/isdnl3.c +++ b/trunk/drivers/isdn/hisax/isdnl3.c @@ -543,6 +543,8 @@ static struct FsmNode L3FnList[] __initdata = }; /* *INDENT-ON* */ +#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode)) + void l3_msg(struct PStack *st, int pr, void *arg) { @@ -585,7 +587,7 @@ Isdnl3New(void) l3fsm.event_count = L3_EVENT_COUNT; l3fsm.strEvent = strL3Event; l3fsm.strState = strL3State; - return FsmNew(&l3fsm, L3FnList, ARRAY_SIZE(L3FnList)); + return FsmNew(&l3fsm, L3FnList, L3_FN_COUNT); } void diff --git a/trunk/drivers/isdn/hisax/l3_1tr6.c b/trunk/drivers/isdn/hisax/l3_1tr6.c index b0554f80bfb3..c5c36eeff261 100644 --- a/trunk/drivers/isdn/hisax/l3_1tr6.c +++ b/trunk/drivers/isdn/hisax/l3_1tr6.c @@ -698,6 +698,9 @@ static struct stateentry downstl[] = CC_T308_2, l3_1tr6_t308_2}, }; +#define DOWNSTL_LEN \ + (sizeof(downstl) / sizeof(struct stateentry)) + static struct stateentry datastln1[] = { {SBIT(0), @@ -732,6 +735,9 @@ static struct stateentry datastln1[] = MT_N1_REL_ACK, l3_1tr6_rel_ack} }; +#define DATASTLN1_LEN \ + (sizeof(datastln1) / sizeof(struct stateentry)) + static struct stateentry manstatelist[] = { {SBIT(2), @@ -740,6 +746,8 @@ static struct stateentry manstatelist[] = DL_RELEASE | INDICATION, l3_1tr6_dl_release}, }; +#define MANSLLEN \ + (sizeof(manstatelist) / sizeof(struct stateentry)) /* *INDENT-ON* */ static void @@ -832,11 +840,11 @@ up1tr6(struct PStack *st, int pr, void *arg) mt = MT_N1_INVALID; } } - for (i = 0; i < ARRAY_SIZE(datastln1); i++) + for (i = 0; i < DATASTLN1_LEN; i++) if ((mt == datastln1[i].primitive) && ((1 << proc->state) & datastln1[i].state)) break; - if (i == ARRAY_SIZE(datastln1)) { + if (i == DATASTLN1_LEN) { dev_kfree_skb(skb); if (st->l3.debug & L3_DEB_STATE) { sprintf(tmp, "up1tr6%sstate %d mt %x unhandled", @@ -884,11 +892,11 @@ down1tr6(struct PStack *st, int pr, void *arg) proc = arg; } - for (i = 0; i < ARRAY_SIZE(downstl); i++) + for (i = 0; i < DOWNSTL_LEN; i++) if ((pr == downstl[i].primitive) && ((1 << proc->state) & downstl[i].state)) break; - if (i == ARRAY_SIZE(downstl)) { + if (i == DOWNSTL_LEN) { if (st->l3.debug & L3_DEB_STATE) { sprintf(tmp, "down1tr6 state %d prim %d unhandled", proc->state, pr); @@ -914,11 +922,11 @@ man1tr6(struct PStack *st, int pr, void *arg) printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr); return; } - for (i = 0; i < ARRAY_SIZE(manstatelist); i++) + for (i = 0; i < MANSLLEN; i++) if ((pr == manstatelist[i].primitive) && ((1 << proc->state) & manstatelist[i].state)) break; - if (i == ARRAY_SIZE(manstatelist)) { + if (i == MANSLLEN) { if (st->l3.debug & L3_DEB_STATE) { l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled", proc->callref & 0x7f, proc->state, pr); diff --git a/trunk/drivers/isdn/hisax/l3dss1.c b/trunk/drivers/isdn/hisax/l3dss1.c index a12fa4d34903..99feae8b9210 100644 --- a/trunk/drivers/isdn/hisax/l3dss1.c +++ b/trunk/drivers/isdn/hisax/l3dss1.c @@ -2820,6 +2820,9 @@ static struct stateentry downstatelist[] = CC_T309, l3dss1_dl_release}, }; +#define DOWNSLLEN \ + (sizeof(downstatelist) / sizeof(struct stateentry)) + static struct stateentry datastatelist[] = { {ALL_STATES, @@ -2872,6 +2875,9 @@ static struct stateentry datastatelist[] = MT_RESUME_REJECT, l3dss1_resume_rej}, }; +#define DATASLLEN \ + (sizeof(datastatelist) / sizeof(struct stateentry)) + static struct stateentry globalmes_list[] = { {ALL_STATES, @@ -2882,6 +2888,8 @@ static struct stateentry globalmes_list[] = MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack}, */ }; +#define GLOBALM_LEN \ + (sizeof(globalmes_list) / sizeof(struct stateentry)) static struct stateentry manstatelist[] = { @@ -2895,6 +2903,8 @@ static struct stateentry manstatelist[] = DL_RELEASE | INDICATION, l3dss1_dl_release}, }; +#define MANSLLEN \ + (sizeof(manstatelist) / sizeof(struct stateentry)) /* *INDENT-ON* */ @@ -2908,11 +2918,11 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb) struct l3_process *proc = st->l3.global; proc->callref = skb->data[2]; /* cr flag */ - for (i = 0; i < ARRAY_SIZE(globalmes_list); i++) + for (i = 0; i < GLOBALM_LEN; i++) if ((mt == globalmes_list[i].primitive) && ((1 << proc->state) & globalmes_list[i].state)) break; - if (i == ARRAY_SIZE(globalmes_list)) { + if (i == GLOBALM_LEN) { if (st->l3.debug & L3_DEB_STATE) { l3_debug(st, "dss1 global state %d mt %x unhandled", proc->state, mt); @@ -3087,11 +3097,11 @@ dss1up(struct PStack *st, int pr, void *arg) } if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL) l3dss1_deliver_display(proc, pr, p); /* Display IE included */ - for (i = 0; i < ARRAY_SIZE(datastatelist); i++) + for (i = 0; i < DATASLLEN; i++) if ((mt == datastatelist[i].primitive) && ((1 << proc->state) & datastatelist[i].state)) break; - if (i == ARRAY_SIZE(datastatelist)) { + if (i == DATASLLEN) { if (st->l3.debug & L3_DEB_STATE) { l3_debug(st, "dss1up%sstate %d mt %#x unhandled", (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", @@ -3146,11 +3156,11 @@ dss1down(struct PStack *st, int pr, void *arg) return; } - for (i = 0; i < ARRAY_SIZE(downstatelist); i++) + for (i = 0; i < DOWNSLLEN; i++) if ((pr == downstatelist[i].primitive) && ((1 << proc->state) & downstatelist[i].state)) break; - if (i == ARRAY_SIZE(downstatelist)) { + if (i == DOWNSLLEN) { if (st->l3.debug & L3_DEB_STATE) { l3_debug(st, "dss1down state %d prim %#x unhandled", proc->state, pr); @@ -3174,11 +3184,11 @@ dss1man(struct PStack *st, int pr, void *arg) printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr); return; } - for (i = 0; i < ARRAY_SIZE(manstatelist); i++) + for (i = 0; i < MANSLLEN; i++) if ((pr == manstatelist[i].primitive) && ((1 << proc->state) & manstatelist[i].state)) break; - if (i == ARRAY_SIZE(manstatelist)) { + if (i == MANSLLEN) { if (st->l3.debug & L3_DEB_STATE) { l3_debug(st, "cr %d dss1man state %d prim %#x unhandled", proc->callref & 0x7f, proc->state, pr); diff --git a/trunk/drivers/isdn/hisax/l3ni1.c b/trunk/drivers/isdn/hisax/l3ni1.c index 4622d43c7e10..f7041d5ba64e 100644 --- a/trunk/drivers/isdn/hisax/l3ni1.c +++ b/trunk/drivers/isdn/hisax/l3ni1.c @@ -2755,6 +2755,9 @@ static struct stateentry downstatelist[] = CC_TSPID, l3ni1_spid_tout }, }; +#define DOWNSLLEN \ + (sizeof(downstatelist) / sizeof(struct stateentry)) + static struct stateentry datastatelist[] = { {ALL_STATES, @@ -2807,6 +2810,9 @@ static struct stateentry datastatelist[] = MT_RESUME_REJECT, l3ni1_resume_rej}, }; +#define DATASLLEN \ + (sizeof(datastatelist) / sizeof(struct stateentry)) + static struct stateentry globalmes_list[] = { {ALL_STATES, @@ -2819,6 +2825,8 @@ static struct stateentry globalmes_list[] = { SBIT( 0 ), MT_DL_ESTABLISHED, l3ni1_spid_send }, { SBIT( 20 ) | SBIT( 21 ) | SBIT( 22 ), MT_INFORMATION, l3ni1_spid_epid }, }; +#define GLOBALM_LEN \ + (sizeof(globalmes_list) / sizeof(struct stateentry)) static struct stateentry manstatelist[] = { @@ -2832,6 +2840,8 @@ static struct stateentry manstatelist[] = DL_RELEASE | INDICATION, l3ni1_dl_release}, }; +#define MANSLLEN \ + (sizeof(manstatelist) / sizeof(struct stateentry)) /* *INDENT-ON* */ @@ -2848,11 +2858,11 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb) proc->callref = skb->data[2]; /* cr flag */ else proc->callref = 0; - for (i = 0; i < ARRAY_SIZE(globalmes_list); i++) + for (i = 0; i < GLOBALM_LEN; i++) if ((mt == globalmes_list[i].primitive) && ((1 << proc->state) & globalmes_list[i].state)) break; - if (i == ARRAY_SIZE(globalmes_list)) { + if (i == GLOBALM_LEN) { if (st->l3.debug & L3_DEB_STATE) { l3_debug(st, "ni1 global state %d mt %x unhandled", proc->state, mt); @@ -3039,11 +3049,11 @@ ni1up(struct PStack *st, int pr, void *arg) } if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL) l3ni1_deliver_display(proc, pr, p); /* Display IE included */ - for (i = 0; i < ARRAY_SIZE(datastatelist); i++) + for (i = 0; i < DATASLLEN; i++) if ((mt == datastatelist[i].primitive) && ((1 << proc->state) & datastatelist[i].state)) break; - if (i == ARRAY_SIZE(datastatelist)) { + if (i == DATASLLEN) { if (st->l3.debug & L3_DEB_STATE) { l3_debug(st, "ni1up%sstate %d mt %#x unhandled", (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", @@ -3098,11 +3108,11 @@ ni1down(struct PStack *st, int pr, void *arg) return; } - for (i = 0; i < ARRAY_SIZE(downstatelist); i++) + for (i = 0; i < DOWNSLLEN; i++) if ((pr == downstatelist[i].primitive) && ((1 << proc->state) & downstatelist[i].state)) break; - if (i == ARRAY_SIZE(downstatelist)) { + if (i == DOWNSLLEN) { if (st->l3.debug & L3_DEB_STATE) { l3_debug(st, "ni1down state %d prim %#x unhandled", proc->state, pr); @@ -3126,11 +3136,11 @@ ni1man(struct PStack *st, int pr, void *arg) printk(KERN_ERR "HiSax ni1man without proc pr=%04x\n", pr); return; } - for (i = 0; i < ARRAY_SIZE(manstatelist); i++) + for (i = 0; i < MANSLLEN; i++) if ((pr == manstatelist[i].primitive) && ((1 << proc->state) & manstatelist[i].state)) break; - if (i == ARRAY_SIZE(manstatelist)) { + if (i == MANSLLEN) { if (st->l3.debug & L3_DEB_STATE) { l3_debug(st, "cr %d ni1man state %d prim %#x unhandled", proc->callref & 0x7f, proc->state, pr); diff --git a/trunk/drivers/isdn/hisax/q931.c b/trunk/drivers/isdn/hisax/q931.c index 8b853d58e820..aacbf0d14b64 100644 --- a/trunk/drivers/isdn/hisax/q931.c +++ b/trunk/drivers/isdn/hisax/q931.c @@ -140,7 +140,7 @@ struct MessageType { } }; -#define MTSIZE ARRAY_SIZE(mtlist) +#define MTSIZE sizeof(mtlist)/sizeof(struct MessageType) static struct MessageType mt_n0[] = @@ -157,7 +157,7 @@ struct MessageType mt_n0[] = {MT_N0_CLO_ACK, "CLOse ACKnowledge"} }; -#define MT_N0_LEN ARRAY_SIZE(mt_n0) +#define MT_N0_LEN (sizeof(mt_n0) / sizeof(struct MessageType)) static struct MessageType mt_n1[] = @@ -194,7 +194,7 @@ struct MessageType mt_n1[] = {MT_N1_STAT, "STATus"} }; -#define MT_N1_LEN ARRAY_SIZE(mt_n1) +#define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType)) static int @@ -438,7 +438,7 @@ struct CauseValue { }, }; -#define CVSIZE ARRAY_SIZE(cvlist) +#define CVSIZE sizeof(cvlist)/sizeof(struct CauseValue) static int @@ -516,7 +516,7 @@ struct MessageType cause_1tr6[] = {CAUSE_UserInfoDiscarded, "User Info Discarded"} }; -static int cause_1tr6_len = ARRAY_SIZE(cause_1tr6); +static int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType)); static int prcause_1tr6(char *dest, u_char * p) @@ -865,7 +865,7 @@ struct DTag { /* Display tags */ { 0x96, "Redirection name" }, { 0x9e, "Text" }, }; -#define DTAGSIZE ARRAY_SIZE(dtaglist) +#define DTAGSIZE sizeof(dtaglist)/sizeof(struct DTag) static int disptext_ni1(char *dest, u_char * p) @@ -1074,7 +1074,7 @@ struct InformationElement { }; -#define IESIZE ARRAY_SIZE(ielist) +#define IESIZE sizeof(ielist)/sizeof(struct InformationElement) static struct InformationElement ielist_ni1[] = { @@ -1102,7 +1102,7 @@ struct InformationElement ielist_ni1[] = { }; -#define IESIZE_NI1 ARRAY_SIZE(ielist_ni1) +#define IESIZE_NI1 sizeof(ielist_ni1)/sizeof(struct InformationElement) static struct InformationElement ielist_ni1_cs5[] = { @@ -1110,14 +1110,14 @@ struct InformationElement ielist_ni1_cs5[] = { { 0x2a, "Display text", disptext_ni1 }, }; -#define IESIZE_NI1_CS5 ARRAY_SIZE(ielist_ni1_cs5) +#define IESIZE_NI1_CS5 sizeof(ielist_ni1_cs5)/sizeof(struct InformationElement) static struct InformationElement ielist_ni1_cs6[] = { { 0x7b, "Call appearance", general_ni1 }, }; -#define IESIZE_NI1_CS6 ARRAY_SIZE(ielist_ni1_cs6) +#define IESIZE_NI1_CS6 sizeof(ielist_ni1_cs6)/sizeof(struct InformationElement) static struct InformationElement we_0[] = { @@ -1133,7 +1133,7 @@ static struct InformationElement we_0[] = {WE0_userInfo, "User Info", general} }; -#define WE_0_LEN ARRAY_SIZE(we_0) +#define WE_0_LEN (sizeof(we_0) / sizeof(struct InformationElement)) static struct InformationElement we_6[] = { @@ -1145,7 +1145,7 @@ static struct InformationElement we_6[] = {WE6_statusCalled, "Status Called", general}, {WE6_addTransAttr, "Additional Transmission Attributes", general} }; -#define WE_6_LEN ARRAY_SIZE(we_6) +#define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement)) int QuickHex(char *txt, u_char * p, int cnt) diff --git a/trunk/drivers/isdn/hisax/st5481.h b/trunk/drivers/isdn/hisax/st5481.h index 64f78a8c28c5..cff7a6354334 100644 --- a/trunk/drivers/isdn/hisax/st5481.h +++ b/trunk/drivers/isdn/hisax/st5481.h @@ -226,7 +226,7 @@ printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __func__ , ## arg) #define INFO(format, arg...) \ printk(KERN_INFO "%s:%s: " format "\n" , __FILE__, __func__ , ## arg) -#include +#include "isdnhdlc.h" #include "fsm.h" #include "hisax_if.h" #include diff --git a/trunk/drivers/isdn/hisax/st5481_b.c b/trunk/drivers/isdn/hisax/st5481_b.c index 95b1cdd97958..0074b600a0ef 100644 --- a/trunk/drivers/isdn/hisax/st5481_b.c +++ b/trunk/drivers/isdn/hisax/st5481_b.c @@ -218,10 +218,7 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode) if (bcs->mode != L1_MODE_NULL) { // Open the B channel if (bcs->mode != L1_MODE_TRANS) { - u32 features = HDLC_BITREVERSE; - if (bcs->mode == L1_MODE_HDLC_56K) - features |= HDLC_56KBIT; - isdnhdlc_out_init(&b_out->hdlc_state, features); + isdnhdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K); } st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2, NULL, NULL); diff --git a/trunk/drivers/isdn/hisax/st5481_d.c b/trunk/drivers/isdn/hisax/st5481_d.c index 39e8e49cfd2d..077991c1cd05 100644 --- a/trunk/drivers/isdn/hisax/st5481_d.c +++ b/trunk/drivers/isdn/hisax/st5481_d.c @@ -417,7 +417,7 @@ static void dout_start_xmit(struct FsmInst *fsm, int event, void *arg) DBG(2,"len=%d",skb->len); - isdnhdlc_out_init(&d_out->hdlc_state, HDLC_DCHANNEL | HDLC_BITREVERSE); + isdnhdlc_out_init(&d_out->hdlc_state, 1, 0); if (test_and_set_bit(buf_nr, &d_out->busy)) { WARNING("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy); diff --git a/trunk/drivers/isdn/hisax/st5481_usb.c b/trunk/drivers/isdn/hisax/st5481_usb.c index 10d41c5d73ed..2b3a055059ea 100644 --- a/trunk/drivers/isdn/hisax/st5481_usb.c +++ b/trunk/drivers/isdn/hisax/st5481_usb.c @@ -637,13 +637,10 @@ void st5481_in_mode(struct st5481_in *in, int mode) usb_unlink_urb(in->urb[1]); if (in->mode != L1_MODE_NULL) { - if (in->mode != L1_MODE_TRANS) { - u32 features = HDLC_BITREVERSE; - - if (in->mode == L1_MODE_HDLC_56K) - features |= HDLC_56KBIT; - isdnhdlc_rcv_init(&in->hdlc_state, features); - } + if (in->mode != L1_MODE_TRANS) + isdnhdlc_rcv_init(&in->hdlc_state, + in->mode == L1_MODE_HDLC_56K); + st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL); st5481_usb_device_ctrl_msg(in->adapter, in->counter, in->packet_size, diff --git a/trunk/drivers/isdn/hisax/tei.c b/trunk/drivers/isdn/hisax/tei.c index 6e65424f1f04..ceb0df92fd3e 100644 --- a/trunk/drivers/isdn/hisax/tei.c +++ b/trunk/drivers/isdn/hisax/tei.c @@ -447,6 +447,8 @@ static struct FsmNode TeiFnList[] __initdata = {ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req}, }; +#define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode)) + int __init TeiNew(void) { @@ -454,7 +456,7 @@ TeiNew(void) teifsm.event_count = TEI_EVENT_COUNT; teifsm.strEvent = strTeiEvent; teifsm.strState = strTeiState; - return FsmNew(&teifsm, TeiFnList, ARRAY_SIZE(TeiFnList)); + return FsmNew(&teifsm, TeiFnList, TEI_FN_COUNT); } void diff --git a/trunk/drivers/isdn/hisax/w6692.c b/trunk/drivers/isdn/hisax/w6692.c index c4d862c11a60..bb1c8dd1a230 100644 --- a/trunk/drivers/isdn/hisax/w6692.c +++ b/trunk/drivers/isdn/hisax/w6692.c @@ -105,6 +105,8 @@ W6692_bh(struct work_struct *work) container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; + if (!cs) + return; if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { if (cs->debug) debugl1(cs, "D-Channel Busy cleared"); diff --git a/trunk/drivers/isdn/i4l/Kconfig b/trunk/drivers/isdn/i4l/Kconfig index dd744ffd240b..ed3510f273d8 100644 --- a/trunk/drivers/isdn/i4l/Kconfig +++ b/trunk/drivers/isdn/i4l/Kconfig @@ -2,8 +2,6 @@ # Old ISDN4Linux config # -if ISDN_I4L - config ISDN_PPP bool "Support synchronous PPP" depends on INET @@ -137,12 +135,3 @@ source "drivers/isdn/act2000/Kconfig" source "drivers/isdn/hysdn/Kconfig" endmenu -# end ISDN_I4L -endif - -config ISDN_HDLC - tristate - depends on HISAX_ST5481 - select CRC_CCITT - select BITREVERSE - diff --git a/trunk/drivers/isdn/i4l/Makefile b/trunk/drivers/isdn/i4l/Makefile index cb9d3bb9fae0..49a06c0005dd 100644 --- a/trunk/drivers/isdn/i4l/Makefile +++ b/trunk/drivers/isdn/i4l/Makefile @@ -4,7 +4,6 @@ obj-$(CONFIG_ISDN_I4L) += isdn.o obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o -obj-$(CONFIG_ISDN_HDLC) += isdnhdlc.o # Multipart objects. diff --git a/trunk/drivers/isdn/mISDN/hwchannel.c b/trunk/drivers/isdn/mISDN/hwchannel.c index e8049be552aa..0481a0cdf6db 100644 --- a/trunk/drivers/isdn/mISDN/hwchannel.c +++ b/trunk/drivers/isdn/mISDN/hwchannel.c @@ -114,14 +114,13 @@ mISDN_freedchannel(struct dchannel *ch) } EXPORT_SYMBOL(mISDN_freedchannel); -void -mISDN_clear_bchannel(struct bchannel *ch) +int +mISDN_freebchannel(struct bchannel *ch) { if (ch->tx_skb) { dev_kfree_skb(ch->tx_skb); ch->tx_skb = NULL; } - ch->tx_idx = 0; if (ch->rx_skb) { dev_kfree_skb(ch->rx_skb); ch->rx_skb = NULL; @@ -130,16 +129,6 @@ mISDN_clear_bchannel(struct bchannel *ch) dev_kfree_skb(ch->next_skb); ch->next_skb = NULL; } - test_and_clear_bit(FLG_TX_BUSY, &ch->Flags); - test_and_clear_bit(FLG_TX_NEXT, &ch->Flags); - test_and_clear_bit(FLG_ACTIVE, &ch->Flags); -} -EXPORT_SYMBOL(mISDN_clear_bchannel); - -int -mISDN_freebchannel(struct bchannel *ch) -{ - mISDN_clear_bchannel(ch); skb_queue_purge(&ch->rqueue); ch->rcount = 0; flush_scheduled_work(); diff --git a/trunk/drivers/isdn/mISDN/layer2.c b/trunk/drivers/isdn/mISDN/layer2.c index e17f0044e0b6..9c2589e986d6 100644 --- a/trunk/drivers/isdn/mISDN/layer2.c +++ b/trunk/drivers/isdn/mISDN/layer2.c @@ -1832,6 +1832,8 @@ static struct FsmNode L2FnList[] = {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da}, }; +#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode)) + static int ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) { diff --git a/trunk/drivers/net/igb/e1000_82575.c b/trunk/drivers/net/igb/e1000_82575.c index 6158c0f3b205..ac28dd5a4fd1 100644 --- a/trunk/drivers/net/igb/e1000_82575.c +++ b/trunk/drivers/net/igb/e1000_82575.c @@ -53,7 +53,7 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *); static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16); static void igb_clear_hw_cntrs_82575(struct e1000_hw *); static s32 igb_acquire_swfw_sync_82575(struct e1000_hw *, u16); -static void igb_configure_pcs_link_82575(struct e1000_hw *); +static s32 igb_configure_pcs_link_82575(struct e1000_hw *); static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *, u16 *, u16 *); static s32 igb_get_phy_id_82575(struct e1000_hw *); @@ -61,7 +61,6 @@ static void igb_release_swfw_sync_82575(struct e1000_hw *, u16); static bool igb_sgmii_active_82575(struct e1000_hw *); static s32 igb_reset_init_script_82575(struct e1000_hw *); static s32 igb_read_mac_addr_82575(struct e1000_hw *); -static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw); static s32 igb_get_invariants_82575(struct e1000_hw *hw) { @@ -85,7 +84,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) case E1000_DEV_ID_82576_FIBER: case E1000_DEV_ID_82576_SERDES: case E1000_DEV_ID_82576_QUAD_COPPER: - case E1000_DEV_ID_82576_SERDES_QUAD: mac->type = e1000_82576; break; default: @@ -172,10 +170,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) size = 14; nvm->word_size = 1 << size; - /* if 82576 then initialize mailbox parameters */ - if (mac->type == e1000_82576) - igb_init_mbx_params_pf(hw); - /* setup PHY parameters */ if (phy->media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; @@ -225,6 +219,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) return -E1000_ERR_PHY; } + /* if 82576 then initialize mailbox parameters */ + if (mac->type == e1000_82576) + igb_init_mbx_params_pf(hw); + return 0; } @@ -765,6 +763,98 @@ static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, return 0; } +/** + * igb_init_rx_addrs_82575 - Initialize receive address's + * @hw: pointer to the HW structure + * @rar_count: receive address registers + * + * Setups the receive address registers by setting the base receive address + * register to the devices MAC address and clearing all the other receive + * address registers to 0. + **/ +static void igb_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count) +{ + u32 i; + u8 addr[6] = {0,0,0,0,0,0}; + /* + * This function is essentially the same as that of + * e1000_init_rx_addrs_generic. However it also takes care + * of the special case where the register offset of the + * second set of RARs begins elsewhere. This is implicitly taken care by + * function e1000_rar_set_generic. + */ + + hw_dbg("e1000_init_rx_addrs_82575"); + + /* Setup the receive address */ + hw_dbg("Programming MAC Address into RAR[0]\n"); + hw->mac.ops.rar_set(hw, hw->mac.addr, 0); + + /* Zero out the other (rar_entry_count - 1) receive addresses */ + hw_dbg("Clearing RAR[1-%u]\n", rar_count-1); + for (i = 1; i < rar_count; i++) + hw->mac.ops.rar_set(hw, addr, i); +} + +/** + * igb_update_mc_addr_list - Update Multicast addresses + * @hw: pointer to the HW structure + * @mc_addr_list: array of multicast addresses to program + * @mc_addr_count: number of multicast addresses to program + * @rar_used_count: the first RAR register free to program + * @rar_count: total number of supported Receive Address Registers + * + * Updates the Receive Address Registers and Multicast Table Array. + * The caller must have a packed mc_addr_list of multicast addresses. + * The parameter rar_count will usually be hw->mac.rar_entry_count + * unless there are workarounds that change this. + **/ +void igb_update_mc_addr_list(struct e1000_hw *hw, + u8 *mc_addr_list, u32 mc_addr_count, + u32 rar_used_count, u32 rar_count) +{ + u32 hash_value; + u32 i; + u8 addr[6] = {0,0,0,0,0,0}; + /* + * This function is essentially the same as that of + * igb_update_mc_addr_list_generic. However it also takes care + * of the special case where the register offset of the + * second set of RARs begins elsewhere. This is implicitly taken care by + * function e1000_rar_set_generic. + */ + + /* + * Load the first set of multicast addresses into the exact + * filters (RAR). If there are not enough to fill the RAR + * array, clear the filters. + */ + for (i = rar_used_count; i < rar_count; i++) { + if (mc_addr_count) { + igb_rar_set(hw, mc_addr_list, i); + mc_addr_count--; + mc_addr_list += ETH_ALEN; + } else { + igb_rar_set(hw, addr, i); + } + } + + /* Clear the old settings from the MTA */ + hw_dbg("Clearing MTA\n"); + for (i = 0; i < hw->mac.mta_reg_count; i++) { + array_wr32(E1000_MTA, i, 0); + wrfl(); + } + + /* Load any remaining multicast addresses into the hash table. */ + for (; mc_addr_count > 0; mc_addr_count--) { + hash_value = igb_hash_mc_addr(hw, mc_addr_list); + hw_dbg("Hash value = 0x%03X\n", hash_value); + igb_mta_set(hw, hash_value); + mc_addr_list += ETH_ALEN; + } +} + /** * igb_shutdown_fiber_serdes_link_82575 - Remove link during power down * @hw: pointer to the HW structure @@ -776,7 +866,9 @@ void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw) { u32 reg; - if (hw->phy.media_type != e1000_media_type_internal_serdes) + if (hw->mac.type != e1000_82576 || + (hw->phy.media_type != e1000_media_type_fiber && + hw->phy.media_type != e1000_media_type_internal_serdes)) return; /* if the management interface is not enabled, then power down */ @@ -819,12 +911,6 @@ static s32 igb_reset_hw_82575(struct e1000_hw *hw) if (ret_val) hw_dbg("PCI-E Master disable polling has failed.\n"); - /* set the completion timeout for interface */ - ret_val = igb_set_pcie_completion_timeout(hw); - if (ret_val) { - hw_dbg("PCI-E Set completion timeout has failed.\n"); - } - hw_dbg("Masking off all interrupts\n"); wr32(E1000_IMC, 0xffffffff); @@ -857,8 +943,7 @@ static s32 igb_reset_hw_82575(struct e1000_hw *hw) wr32(E1000_IMC, 0xffffffff); icr = rd32(E1000_ICR); - /* Install any alternate MAC address into RAR0 */ - ret_val = igb_check_alt_mac_addr(hw); + igb_check_alt_mac_addr(hw); return ret_val; } @@ -887,8 +972,7 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw) igb_clear_vfta(hw); /* Setup the receive address */ - igb_init_rx_addrs(hw, rar_count); - + igb_init_rx_addrs_82575(hw, rar_count); /* Zero out the Multicast HASH table */ hw_dbg("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) @@ -918,7 +1002,7 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw) **/ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) { - u32 ctrl; + u32 ctrl, led_ctrl; s32 ret_val; bool link; @@ -933,6 +1017,11 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) break; case e1000_phy_igp_3: ret_val = igb_copper_link_setup_igp(hw); + /* Setup activity LED */ + led_ctrl = rd32(E1000_LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); + wr32(E1000_LEDCTL, led_ctrl); break; default: ret_val = -E1000_ERR_PHY; @@ -963,7 +1052,9 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) } } - igb_configure_pcs_link_82575(hw); + ret_val = igb_configure_pcs_link_82575(hw); + if (ret_val) + goto out; /* * Check link status. Wait up to 100 microseconds for link to become @@ -1072,14 +1163,14 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw) * independent interface (sgmii) is being used. Configures the link * for auto-negotiation or forces speed/duplex. **/ -static void igb_configure_pcs_link_82575(struct e1000_hw *hw) +static s32 igb_configure_pcs_link_82575(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 reg = 0; if (hw->phy.media_type != e1000_media_type_copper || !(igb_sgmii_active_82575(hw))) - return; + goto out; /* For SGMII, we need to issue a PCS autoneg restart */ reg = rd32(E1000_PCS_LCTL); @@ -1122,6 +1213,9 @@ static void igb_configure_pcs_link_82575(struct e1000_hw *hw) reg); } wr32(E1000_PCS_LCTL, reg); + +out: + return 0; } /** @@ -1135,6 +1229,10 @@ static void igb_configure_pcs_link_82575(struct e1000_hw *hw) static bool igb_sgmii_active_82575(struct e1000_hw *hw) { struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; + + if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576) + return false; + return dev_spec->sgmii_active; } @@ -1325,57 +1423,6 @@ void igb_rx_fifo_flush_82575(struct e1000_hw *hw) rd32(E1000_MPC); } -/** - * igb_set_pcie_completion_timeout - set pci-e completion timeout - * @hw: pointer to the HW structure - * - * The defaults for 82575 and 82576 should be in the range of 50us to 50ms, - * however the hardware default for these parts is 500us to 1ms which is less - * than the 10ms recommended by the pci-e spec. To address this we need to - * increase the value to either 10ms to 200ms for capability version 1 config, - * or 16ms to 55ms for version 2. - **/ -static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw) -{ - u32 gcr = rd32(E1000_GCR); - s32 ret_val = 0; - u16 pcie_devctl2; - - /* only take action if timeout value is defaulted to 0 */ - if (gcr & E1000_GCR_CMPL_TMOUT_MASK) - goto out; - - /* - * if capababilities version is type 1 we can write the - * timeout of 10ms to 200ms through the GCR register - */ - if (!(gcr & E1000_GCR_CAP_VER2)) { - gcr |= E1000_GCR_CMPL_TMOUT_10ms; - goto out; - } - - /* - * for version 2 capabilities we need to write the config space - * directly in order to set the completion timeout value for - * 16ms to 55ms - */ - ret_val = igb_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, - &pcie_devctl2); - if (ret_val) - goto out; - - pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms; - - ret_val = igb_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, - &pcie_devctl2); -out: - /* disable completion timeout resend */ - gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND; - - wr32(E1000_GCR, gcr); - return ret_val; -} - /** * igb_vmdq_set_loopback_pf - enable or disable vmdq loopback * @hw: pointer to the hardware struct diff --git a/trunk/drivers/net/igb/e1000_82575.h b/trunk/drivers/net/igb/e1000_82575.h index 8a1e6597061f..0f16abab2565 100644 --- a/trunk/drivers/net/igb/e1000_82575.h +++ b/trunk/drivers/net/igb/e1000_82575.h @@ -28,14 +28,10 @@ #ifndef _E1000_82575_H_ #define _E1000_82575_H_ +void igb_update_mc_addr_list(struct e1000_hw*, u8*, u32, u32, u32); extern void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw); extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); -#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \ - (ID_LED_DEF1_DEF2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_OFF1_ON2)) - #define E1000_RAR_ENTRIES_82575 16 #define E1000_RAR_ENTRIES_82576 24 diff --git a/trunk/drivers/net/igb/e1000_defines.h b/trunk/drivers/net/igb/e1000_defines.h index c85829355d50..3bda3db73f1f 100644 --- a/trunk/drivers/net/igb/e1000_defines.h +++ b/trunk/drivers/net/igb/e1000_defines.h @@ -435,12 +435,6 @@ /* Flow Control */ #define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ -/* PCI Express Control */ -#define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000 -#define E1000_GCR_CMPL_TMOUT_10ms 0x00001000 -#define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000 -#define E1000_GCR_CAP_VER2 0x00040000 - /* PHY Control Register */ #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ @@ -575,11 +569,9 @@ /* PCI/PCI-X/PCI-EX Config space */ #define PCIE_LINK_STATUS 0x12 -#define PCIE_DEVICE_CONTROL2 0x28 #define PCIE_LINK_WIDTH_MASK 0x3F0 #define PCIE_LINK_WIDTH_SHIFT 4 -#define PCIE_DEVICE_CONTROL2_16ms 0x0005 #define PHY_REVISION_MASK 0xFFFFFFF0 #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ diff --git a/trunk/drivers/net/igb/e1000_hw.h b/trunk/drivers/net/igb/e1000_hw.h index 119869b1124d..68aac20c31ca 100644 --- a/trunk/drivers/net/igb/e1000_hw.h +++ b/trunk/drivers/net/igb/e1000_hw.h @@ -42,7 +42,6 @@ struct e1000_hw; #define E1000_DEV_ID_82576_SERDES 0x10E7 #define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 #define E1000_DEV_ID_82576_NS 0x150A -#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D #define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 @@ -62,7 +61,8 @@ enum e1000_mac_type { enum e1000_media_type { e1000_media_type_unknown = 0, e1000_media_type_copper = 1, - e1000_media_type_internal_serdes = 2, + e1000_media_type_fiber = 2, + e1000_media_type_internal_serdes = 3, e1000_num_media_types }; @@ -137,7 +137,7 @@ enum e1000_rev_polarity { e1000_rev_polarity_undefined = 0xFF }; -enum e1000_fc_mode { +enum e1000_fc_type { e1000_fc_none = 0, e1000_fc_rx_pause, e1000_fc_tx_pause, @@ -339,10 +339,6 @@ struct e1000_mac_info { u16 ifs_ratio; u16 ifs_step_size; u16 mta_reg_count; - - /* Maximum size of the MTA register table in all supported adapters */ - #define MAX_MTA_REG 128 - u32 mta_shadow[MAX_MTA_REG]; u16 rar_entry_count; u8 forced_speed_duplex; @@ -429,8 +425,8 @@ struct e1000_fc_info { u16 pause_time; /* Flow control pause timer */ bool send_xon; /* Flow control send XON */ bool strict_ieee; /* Strict IEEE mode */ - enum e1000_fc_mode current_mode; /* Type of flow control */ - enum e1000_fc_mode requested_mode; + enum e1000_fc_type type; /* Type of flow control */ + enum e1000_fc_type original_type; }; struct e1000_mbx_operations { @@ -499,7 +495,5 @@ extern char *igb_get_hw_dev_name(struct e1000_hw *hw); #else #define hw_dbg(format, arg...) #endif + #endif -/* These functions must be implemented by drivers */ -s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); -s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); diff --git a/trunk/drivers/net/igb/e1000_mac.c b/trunk/drivers/net/igb/e1000_mac.c index a0231cd079f1..472f3f124840 100644 --- a/trunk/drivers/net/igb/e1000_mac.c +++ b/trunk/drivers/net/igb/e1000_mac.c @@ -37,6 +37,20 @@ static s32 igb_set_default_fc(struct e1000_hw *hw); static s32 igb_set_fc_watermarks(struct e1000_hw *hw); +static s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) +{ + struct igb_adapter *adapter = hw->back; + u16 cap_offset; + + cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); + if (!cap_offset) + return -E1000_ERR_CONFIG; + + pci_read_config_word(adapter->pdev, cap_offset + reg, value); + + return 0; +} + /** * igb_get_bus_info_pcie - Get PCIe bus information * @hw: pointer to the HW structure @@ -103,31 +117,6 @@ static void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) wrfl(); } -/** - * igb_init_rx_addrs - Initialize receive address's - * @hw: pointer to the HW structure - * @rar_count: receive address registers - * - * Setups the receive address registers by setting the base receive address - * register to the devices MAC address and clearing all the other receive - * address registers to 0. - **/ -void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) -{ - u32 i; - u8 mac_addr[ETH_ALEN] = {0}; - - /* Setup the receive address */ - hw_dbg("Programming MAC Address into RAR[0]\n"); - - hw->mac.ops.rar_set(hw, hw->mac.addr, 0); - - /* Zero out the other (rar_entry_count - 1) receive addresses */ - hw_dbg("Clearing RAR[1-%u]\n", rar_count-1); - for (i = 1; i < rar_count; i++) - hw->mac.ops.rar_set(hw, mac_addr, i); -} - /** * igb_vfta_set - enable or disable vlan in VLAN filter table * @hw: pointer to the HW structure @@ -285,41 +274,6 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value) wrfl(); } -/** - * igb_update_mc_addr_list - Update Multicast addresses - * @hw: pointer to the HW structure - * @mc_addr_list: array of multicast addresses to program - * @mc_addr_count: number of multicast addresses to program - * - * Updates entire Multicast Table Array. - * The caller must have a packed mc_addr_list of multicast addresses. - **/ -void igb_update_mc_addr_list(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count) -{ - u32 hash_value, hash_bit, hash_reg; - int i; - - /* clear mta_shadow */ - memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); - - /* update mta_shadow from mc_addr_list */ - for (i = 0; (u32) i < mc_addr_count; i++) { - hash_value = igb_hash_mc_addr(hw, mc_addr_list); - - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); - mc_addr_list += (ETH_ALEN); - } - - /* replace the entire MTA table */ - for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) - array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]); - wrfl(); -} - /** * igb_hash_mc_addr - Generate a multicast hash value * @hw: pointer to the HW structure @@ -536,24 +490,18 @@ s32 igb_setup_link(struct e1000_hw *hw) if (igb_check_reset_block(hw)) goto out; - /* - * If requested flow control is set to default, set flow control - * based on the EEPROM flow control settings. - */ - if (hw->fc.requested_mode == e1000_fc_default) { - ret_val = igb_set_default_fc(hw); - if (ret_val) - goto out; - } + ret_val = igb_set_default_fc(hw); + if (ret_val) + goto out; /* * We want to save off the original Flow Control configuration just * in case we get disconnected and then reconnected into a different * hub or switch with different Flow Control capabilities. */ - hw->fc.current_mode = hw->fc.requested_mode; + hw->fc.original_type = hw->fc.type; - hw_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); + hw_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.type); /* Call the necessary media_type subroutine to configure the link. */ ret_val = hw->mac.ops.setup_physical_interface(hw); @@ -620,7 +568,7 @@ static s32 igb_set_fc_watermarks(struct e1000_hw *hw) * ability to transmit pause frames is not enabled, then these * registers will be set to 0. */ - if (hw->fc.current_mode & e1000_fc_tx_pause) { + if (hw->fc.type & e1000_fc_tx_pause) { /* * We need to set up the Receive Threshold high and low water * marks as well as (optionally) enabling the transmission of @@ -667,12 +615,12 @@ static s32 igb_set_default_fc(struct e1000_hw *hw) } if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) - hw->fc.requested_mode = e1000_fc_none; + hw->fc.type = e1000_fc_none; else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR) - hw->fc.requested_mode = e1000_fc_tx_pause; + hw->fc.type = e1000_fc_tx_pause; else - hw->fc.requested_mode = e1000_fc_full; + hw->fc.type = e1000_fc_full; out: return ret_val; @@ -702,7 +650,7 @@ s32 igb_force_mac_fc(struct e1000_hw *hw) * receive flow control. * * The "Case" statement below enables/disable flow control - * according to the "hw->fc.current_mode" parameter. + * according to the "hw->fc.type" parameter. * * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled @@ -713,9 +661,9 @@ s32 igb_force_mac_fc(struct e1000_hw *hw) * 3: Both Rx and TX flow control (symmetric) is enabled. * other: No other values should be possible at this point. */ - hw_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode); + hw_dbg("hw->fc.type = %u\n", hw->fc.type); - switch (hw->fc.current_mode) { + switch (hw->fc.type) { case e1000_fc_none: ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); break; @@ -765,7 +713,8 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) * configuration of the MAC to match the "fc" parameter. */ if (mac->autoneg_failed) { - if (hw->phy.media_type == e1000_media_type_internal_serdes) + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) ret_val = igb_force_mac_fc(hw); } else { if (hw->phy.media_type == e1000_media_type_copper) @@ -863,11 +812,11 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ - if (hw->fc.requested_mode == e1000_fc_full) { - hw->fc.current_mode = e1000_fc_full; + if (hw->fc.original_type == e1000_fc_full) { + hw->fc.type = e1000_fc_full; hw_dbg("Flow Control = FULL.\r\n"); } else { - hw->fc.current_mode = e1000_fc_rx_pause; + hw->fc.type = e1000_fc_rx_pause; hw_dbg("Flow Control = " "RX PAUSE frames only.\r\n"); } @@ -884,7 +833,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_tx_pause; + hw->fc.type = e1000_fc_tx_pause; hw_dbg("Flow Control = TX PAUSE frames only.\r\n"); } /* @@ -899,7 +848,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_rx_pause; + hw->fc.type = e1000_fc_rx_pause; hw_dbg("Flow Control = RX PAUSE frames only.\r\n"); } /* @@ -923,13 +872,13 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) * be asked to delay transmission of packets than asking * our link partner to pause transmission of frames. */ - else if ((hw->fc.requested_mode == e1000_fc_none || - hw->fc.requested_mode == e1000_fc_tx_pause) || + else if ((hw->fc.original_type == e1000_fc_none || + hw->fc.original_type == e1000_fc_tx_pause) || hw->fc.strict_ieee) { - hw->fc.current_mode = e1000_fc_none; + hw->fc.type = e1000_fc_none; hw_dbg("Flow Control = NONE.\r\n"); } else { - hw->fc.current_mode = e1000_fc_rx_pause; + hw->fc.type = e1000_fc_rx_pause; hw_dbg("Flow Control = RX PAUSE frames only.\r\n"); } @@ -945,7 +894,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) } if (duplex == HALF_DUPLEX) - hw->fc.current_mode = e1000_fc_none; + hw->fc.type = e1000_fc_none; /* * Now we call a subroutine to actually force the MAC @@ -1116,17 +1065,9 @@ static s32 igb_valid_led_default(struct e1000_hw *hw, u16 *data) goto out; } - if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { - switch(hw->phy.media_type) { - case e1000_media_type_internal_serdes: - *data = ID_LED_DEFAULT_82575_SERDES; - break; - case e1000_media_type_copper: - default: - *data = ID_LED_DEFAULT; - break; - } - } + if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) + *data = ID_LED_DEFAULT; + out: return ret_val; } @@ -1220,16 +1161,22 @@ s32 igb_blink_led(struct e1000_hw *hw) u32 ledctl_blink = 0; u32 i; - /* - * set the blink bit for each LED that's "on" (0x0E) - * in ledctl_mode2 - */ - ledctl_blink = hw->mac.ledctl_mode2; - for (i = 0; i < 4; i++) - if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == - E1000_LEDCTL_MODE_LED_ON) - ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << - (i * 8)); + if (hw->phy.media_type == e1000_media_type_fiber) { + /* always blink LED0 for PCI-E fiber */ + ledctl_blink = E1000_LEDCTL_LED0_BLINK | + (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); + } else { + /* + * set the blink bit for each LED that's "on" (0x0E) + * in ledctl_mode2 + */ + ledctl_blink = hw->mac.ledctl_mode2; + for (i = 0; i < 4; i++) + if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == + E1000_LEDCTL_MODE_LED_ON) + ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << + (i * 8)); + } wr32(E1000_LEDCTL, ledctl_blink); @@ -1244,7 +1191,15 @@ s32 igb_blink_led(struct e1000_hw *hw) **/ s32 igb_led_off(struct e1000_hw *hw) { + u32 ctrl; + switch (hw->phy.media_type) { + case e1000_media_type_fiber: + ctrl = rd32(E1000_CTRL); + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + wr32(E1000_CTRL, ctrl); + break; case e1000_media_type_copper: wr32(E1000_LEDCTL, hw->mac.ledctl_mode1); break; diff --git a/trunk/drivers/net/igb/e1000_mac.h b/trunk/drivers/net/igb/e1000_mac.h index 7518af8cbbf5..1d690b4c9ae4 100644 --- a/trunk/drivers/net/igb/e1000_mac.h +++ b/trunk/drivers/net/igb/e1000_mac.h @@ -51,8 +51,6 @@ s32 igb_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex); s32 igb_id_led_init(struct e1000_hw *hw); s32 igb_led_off(struct e1000_hw *hw); -void igb_update_mc_addr_list(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count); s32 igb_setup_link(struct e1000_hw *hw); s32 igb_validate_mdi_setting(struct e1000_hw *hw); s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, @@ -62,7 +60,6 @@ void igb_clear_hw_cntrs_base(struct e1000_hw *hw); void igb_clear_vfta(struct e1000_hw *hw); s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add); void igb_config_collision_dist(struct e1000_hw *hw); -void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); void igb_mta_set(struct e1000_hw *hw, u32 hash_value); void igb_put_hw_semaphore(struct e1000_hw *hw); void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); diff --git a/trunk/drivers/net/igb/e1000_phy.c b/trunk/drivers/net/igb/e1000_phy.c index c1f4da630420..f50fac25be40 100644 --- a/trunk/drivers/net/igb/e1000_phy.c +++ b/trunk/drivers/net/igb/e1000_phy.c @@ -735,7 +735,7 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw) * other: No software override. The flow control configuration * in the EEPROM is used. */ - switch (hw->fc.current_mode) { + switch (hw->fc.type) { case e1000_fc_none: /* * Flow control (RX & TX) is completely disabled by a @@ -992,7 +992,7 @@ static void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw, u32 ctrl; /* Turn off flow control when forcing speed/duplex */ - hw->fc.current_mode = e1000_fc_none; + hw->fc.type = e1000_fc_none; /* Force speed/duplex on the mac */ ctrl = rd32(E1000_CTRL); diff --git a/trunk/drivers/net/igb/e1000_regs.h b/trunk/drivers/net/igb/e1000_regs.h index 345d1442d6d6..6e5924511e40 100644 --- a/trunk/drivers/net/igb/e1000_regs.h +++ b/trunk/drivers/net/igb/e1000_regs.h @@ -305,7 +305,6 @@ enum { #define E1000_CCMCTL 0x05B48 /* CCM Control Register */ #define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */ #define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */ -#define E1000_GCR 0x05B00 /* PCI-Ex Control */ #define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ #define E1000_SWSM 0x05B50 /* SW Semaphore */ #define E1000_FWSM 0x05B54 /* FW Semaphore */ diff --git a/trunk/drivers/net/igb/igb_ethtool.c b/trunk/drivers/net/igb/igb_ethtool.c index 114ccab1f2be..9598ac09f4b8 100644 --- a/trunk/drivers/net/igb/igb_ethtool.c +++ b/trunk/drivers/net/igb/igb_ethtool.c @@ -168,7 +168,8 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->duplex = -1; } - ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; + ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || + hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; return 0; } @@ -190,20 +191,23 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) if (ecmd->autoneg == AUTONEG_ENABLE) { hw->mac.autoneg = 1; - hw->phy.autoneg_advertised = ecmd->advertising | - ADVERTISED_TP | - ADVERTISED_Autoneg; + if (hw->phy.media_type == e1000_media_type_fiber) + hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full | + ADVERTISED_FIBRE | + ADVERTISED_Autoneg; + else + hw->phy.autoneg_advertised = ecmd->advertising | + ADVERTISED_TP | + ADVERTISED_Autoneg; ecmd->advertising = hw->phy.autoneg_advertised; - if (adapter->fc_autoneg) - hw->fc.requested_mode = e1000_fc_default; - } else { + } else if (igb_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { clear_bit(__IGB_RESETTING, &adapter->state); return -EINVAL; } - } /* reset the link */ + if (netif_running(adapter->netdev)) { igb_down(adapter); igb_up(adapter); @@ -223,11 +227,11 @@ static void igb_get_pauseparam(struct net_device *netdev, pause->autoneg = (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - if (hw->fc.current_mode == e1000_fc_rx_pause) + if (hw->fc.type == e1000_fc_rx_pause) pause->rx_pause = 1; - else if (hw->fc.current_mode == e1000_fc_tx_pause) + else if (hw->fc.type == e1000_fc_tx_pause) pause->tx_pause = 1; - else if (hw->fc.current_mode == e1000_fc_full) { + else if (hw->fc.type == e1000_fc_full) { pause->rx_pause = 1; pause->tx_pause = 1; } @@ -245,28 +249,26 @@ static int igb_set_pauseparam(struct net_device *netdev, while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) msleep(1); + if (pause->rx_pause && pause->tx_pause) + hw->fc.type = e1000_fc_full; + else if (pause->rx_pause && !pause->tx_pause) + hw->fc.type = e1000_fc_rx_pause; + else if (!pause->rx_pause && pause->tx_pause) + hw->fc.type = e1000_fc_tx_pause; + else if (!pause->rx_pause && !pause->tx_pause) + hw->fc.type = e1000_fc_none; + + hw->fc.original_type = hw->fc.type; + if (adapter->fc_autoneg == AUTONEG_ENABLE) { - hw->fc.requested_mode = e1000_fc_default; if (netif_running(adapter->netdev)) { igb_down(adapter); igb_up(adapter); } else igb_reset(adapter); - } else { - if (pause->rx_pause && pause->tx_pause) - hw->fc.requested_mode = e1000_fc_full; - else if (pause->rx_pause && !pause->tx_pause) - hw->fc.requested_mode = e1000_fc_rx_pause; - else if (!pause->rx_pause && pause->tx_pause) - hw->fc.requested_mode = e1000_fc_tx_pause; - else if (!pause->rx_pause && !pause->tx_pause) - hw->fc.requested_mode = e1000_fc_none; - - hw->fc.current_mode = hw->fc.requested_mode; - - retval = ((hw->phy.media_type == e1000_media_type_copper) ? - igb_force_mac_fc(hw) : igb_setup_link(hw)); - } + } else + retval = ((hw->phy.media_type == e1000_media_type_fiber) ? + igb_setup_link(hw) : igb_force_mac_fc(hw)); clear_bit(__IGB_RESETTING, &adapter->state); return retval; @@ -1481,7 +1483,8 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter) struct e1000_hw *hw = &adapter->hw; u32 reg; - if (hw->phy.media_type == e1000_media_type_internal_serdes) { + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) { reg = rd32(E1000_RCTL); reg |= E1000_RCTL_LBM_TCVR; wr32(E1000_RCTL, reg); @@ -1840,6 +1843,7 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; @@ -1848,6 +1852,11 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) !device_can_wakeup(&adapter->pdev->dev)) return wol->wolopts ? -EOPNOTSUPP : 0; + switch (hw->device_id) { + default: + break; + } + /* these settings will always override what we currently have */ adapter->wol = 0; diff --git a/trunk/drivers/net/igb/igb_main.c b/trunk/drivers/net/igb/igb_main.c index fb3273517587..adb09d32625d 100644 --- a/trunk/drivers/net/igb/igb_main.c +++ b/trunk/drivers/net/igb/igb_main.c @@ -65,7 +65,6 @@ static struct pci_device_id igb_pci_tbl[] = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 }, @@ -128,7 +127,7 @@ static void igb_restore_vlan(struct igb_adapter *); static void igb_ping_all_vfs(struct igb_adapter *); static void igb_msg_task(struct igb_adapter *); static int igb_rcv_msg_from_vf(struct igb_adapter *, u32); -static inline void igb_set_rah_pool(struct e1000_hw *, int , int); +static void igb_set_mc_list_pools(struct igb_adapter *, int, u16); static void igb_vmm_control(struct igb_adapter *); static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *); static void igb_restore_vf_multicasts(struct igb_adapter *adapter); @@ -1130,7 +1129,7 @@ void igb_reset(struct igb_adapter *adapter) } fc->pause_time = 0xFFFF; fc->send_xon = 1; - fc->current_mode = fc->requested_mode; + fc->type = fc->original_type; /* disable receive for all VFs and wait one second */ if (adapter->vfs_allocated_count) { @@ -1427,8 +1426,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, hw->mac.autoneg = true; hw->phy.autoneg_advertised = 0x2f; - hw->fc.requested_mode = e1000_fc_default; - hw->fc.current_mode = e1000_fc_default; + hw->fc.original_type = e1000_fc_default; + hw->fc.type = e1000_fc_default; adapter->itr_setting = IGB_DEFAULT_ITR; adapter->itr = IGB_START_ITR; @@ -2536,6 +2535,7 @@ static void igb_set_multi(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; + struct e1000_mac_info *mac = &hw->mac; struct dev_mc_list *mc_ptr; u8 *mta_list = NULL; u32 rctl; @@ -2558,18 +2558,13 @@ static void igb_set_multi(struct net_device *netdev) } wr32(E1000_RCTL, rctl); - if (!netdev->mc_count) { - /* nothing to program, so clear mc list */ - igb_update_mc_addr_list(hw, NULL, 0); - igb_restore_vf_multicasts(adapter); - return; - } - - mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC); - if (!mta_list) { - dev_err(&adapter->pdev->dev, - "failed to allocate multicast filter list\n"); - return; + if (netdev->mc_count) { + mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC); + if (!mta_list) { + dev_err(&adapter->pdev->dev, + "failed to allocate multicast filter list\n"); + return; + } } /* The shared function expects a packed array of only addresses. */ @@ -2581,9 +2576,14 @@ static void igb_set_multi(struct net_device *netdev) memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); mc_ptr = mc_ptr->next; } - igb_update_mc_addr_list(hw, mta_list, i); - kfree(mta_list); + igb_update_mc_addr_list(hw, mta_list, i, + adapter->vfs_allocated_count + 1, + mac->rar_entry_count); + + igb_set_mc_list_pools(adapter, i, mac->rar_entry_count); igb_restore_vf_multicasts(adapter); + + kfree(mta_list); } /* Need to wait a few seconds after link up to get diagnostic information from @@ -2618,6 +2618,10 @@ static bool igb_has_link(struct igb_adapter *adapter) link_active = true; } break; + case e1000_media_type_fiber: + ret_val = hw->mac.ops.check_for_link(hw); + link_active = !!(rd32(E1000_STATUS) & E1000_STATUS_LU); + break; case e1000_media_type_internal_serdes: ret_val = hw->mac.ops.check_for_link(hw); link_active = hw->mac.serdes_has_link; @@ -4538,20 +4542,6 @@ static inline void igb_rx_checksum_adv(struct igb_adapter *adapter, adapter->hw_csum_good++; } -static inline u16 igb_get_hlen(struct igb_adapter *adapter, - union e1000_adv_rx_desc *rx_desc) -{ - /* HW will not DMA in data larger than the given buffer, even if it - * parses the (NFS, of course) header to be larger. In that case, it - * fills the header buffer and spills the rest into the page. - */ - u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) & - E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; - if (hlen > adapter->rx_ps_hdr_size) - hlen = adapter->rx_ps_hdr_size; - return hlen; -} - static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, int *work_done, int budget) { @@ -4566,8 +4556,7 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, int cleaned_count = 0; unsigned int total_bytes = 0, total_packets = 0; unsigned int i; - u32 staterr; - u16 length; + u32 length, hlen, staterr; i = rx_ring->next_to_clean; buffer_info = &rx_ring->buffer_info[i]; @@ -4604,8 +4593,17 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, goto send_up; } - if (buffer_info->dma) { - u16 hlen = igb_get_hlen(adapter, rx_desc); + /* HW will not DMA in data larger than the given buffer, even + * if it parses the (NFS, of course) header to be larger. In + * that case, it fills the header buffer and spills the rest + * into the page. + */ + hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) & + E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; + if (hlen > adapter->rx_ps_hdr_size) + hlen = adapter->rx_ps_hdr_size; + + if (!skb_shinfo(skb)->nr_frags) { pci_unmap_single(pdev, buffer_info->dma, adapter->rx_ps_hdr_size, PCI_DMA_FROMDEVICE); @@ -5035,34 +5033,6 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) } } -s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) -{ - struct igb_adapter *adapter = hw->back; - u16 cap_offset; - - cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); - if (!cap_offset) - return -E1000_ERR_CONFIG; - - pci_read_config_word(adapter->pdev, cap_offset + reg, value); - - return 0; -} - -s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) -{ - struct igb_adapter *adapter = hw->back; - u16 cap_offset; - - cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); - if (!cap_offset) - return -E1000_ERR_CONFIG; - - pci_write_config_word(adapter->pdev, cap_offset + reg, *value); - - return 0; -} - static void igb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) { @@ -5166,6 +5136,14 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx) mac->autoneg = 0; + /* Fiber NICs only allow 1000 gbps Full duplex */ + if ((adapter->hw.phy.media_type == e1000_media_type_fiber) && + spddplx != (SPEED_1000 + DUPLEX_FULL)) { + dev_err(&adapter->pdev->dev, + "Unsupported Speed/Duplex configuration\n"); + return -EINVAL; + } + switch (spddplx) { case SPEED_10 + DUPLEX_HALF: mac->forced_speed_duplex = ADVERTISE_10_HALF; @@ -5474,6 +5452,19 @@ static void igb_io_resume(struct pci_dev *pdev) igb_get_hw_control(adapter); } +static void igb_set_mc_list_pools(struct igb_adapter *adapter, + int entry_count, u16 total_rar_filters) +{ + struct e1000_hw *hw = &adapter->hw; + int i = adapter->vfs_allocated_count + 1; + + if ((i + entry_count) < total_rar_filters) + total_rar_filters = i + entry_count; + + for (; i < total_rar_filters; i++) + igb_set_rah_pool(hw, adapter->vfs_allocated_count, i); +} + static int igb_set_vf_mac(struct igb_adapter *adapter, int vf, unsigned char *mac_addr) { diff --git a/trunk/drivers/net/igbvf/netdev.c b/trunk/drivers/net/igbvf/netdev.c index 926c31b47261..2bc9d63027db 100644 --- a/trunk/drivers/net/igbvf/netdev.c +++ b/trunk/drivers/net/igbvf/netdev.c @@ -149,6 +149,7 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring, bufsz = adapter->rx_ps_hdr_size; else bufsz = adapter->rx_buffer_len; + bufsz += NET_IP_ALIGN; while (cleaned_count--) { rx_desc = IGBVF_RX_DESC_ADV(*rx_ring, i); @@ -172,7 +173,7 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring, } if (!buffer_info->skb) { - skb = netdev_alloc_skb(netdev, bufsz + NET_IP_ALIGN); + skb = netdev_alloc_skb(netdev, bufsz); if (!skb) { adapter->alloc_rx_buff_failed++; goto no_buffers; @@ -285,7 +286,7 @@ static bool igbvf_clean_rx_irq(struct igbvf_adapter *adapter, if (!skb_shinfo(skb)->nr_frags) { pci_unmap_single(pdev, buffer_info->dma, - adapter->rx_ps_hdr_size, + adapter->rx_ps_hdr_size + NET_IP_ALIGN, PCI_DMA_FROMDEVICE); skb_put(skb, hlen); } diff --git a/trunk/include/linux/isdn/hdlc.h b/trunk/include/linux/isdn/hdlc.h deleted file mode 100644 index 4b3ecc40889a..000000000000 --- a/trunk/include/linux/isdn/hdlc.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * hdlc.h -- General purpose ISDN HDLC decoder. - * - * Implementation of a HDLC decoder/encoder in software. - * Neccessary because some ISDN devices don't have HDLC - * controllers. - * - * Copyright (C) - * 2009 Karsten Keil - * 2002 Wolfgang Mües - * 2001 Frode Isaksen - * 2001 Kai Germaschewski - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ISDNHDLC_H__ -#define __ISDNHDLC_H__ - -struct isdnhdlc_vars { - int bit_shift; - int hdlc_bits1; - int data_bits; - int ffbit_shift; /* encoding only */ - int state; - int dstpos; - - u16 crc; - - u8 cbin; - u8 shift_reg; - u8 ffvalue; - - /* set if transferring data */ - u32 data_received:1; - /* set if D channel (send idle instead of flags) */ - u32 dchannel:1; - /* set if 56K adaptation */ - u32 do_adapt56:1; - /* set if in closing phase (need to send CRC + flag) */ - u32 do_closing:1; - /* set if data is bitreverse */ - u32 do_bitreverse:1; -}; - -/* Feature Flags */ -#define HDLC_56KBIT 0x01 -#define HDLC_DCHANNEL 0x02 -#define HDLC_BITREVERSE 0x04 - -/* - The return value from isdnhdlc_decode is - the frame length, 0 if no complete frame was decoded, - or a negative error number -*/ -#define HDLC_FRAMING_ERROR 1 -#define HDLC_CRC_ERROR 2 -#define HDLC_LENGTH_ERROR 3 - -extern void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, u32 features); - -extern int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, - int slen, int *count, u8 *dst, int dsize); - -extern void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, u32 features); - -extern int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, - u16 slen, int *count, u8 *dst, int dsize); - -#endif /* __ISDNHDLC_H__ */ diff --git a/trunk/include/linux/mISDNhw.h b/trunk/include/linux/mISDNhw.h index 4af841408fb5..7f9831da847f 100644 --- a/trunk/include/linux/mISDNhw.h +++ b/trunk/include/linux/mISDNhw.h @@ -168,7 +168,6 @@ struct bchannel { extern int mISDN_initdchannel(struct dchannel *, int, void *); extern int mISDN_initbchannel(struct bchannel *, int); extern int mISDN_freedchannel(struct dchannel *); -extern void mISDN_clear_bchannel(struct bchannel *); extern int mISDN_freebchannel(struct bchannel *); extern void queue_ch_frame(struct mISDNchannel *, u_int, int, struct sk_buff *); diff --git a/trunk/include/linux/mISDNif.h b/trunk/include/linux/mISDNif.h index 536ca12442ca..45100b39a7cf 100644 --- a/trunk/include/linux/mISDNif.h +++ b/trunk/include/linux/mISDNif.h @@ -37,7 +37,7 @@ */ #define MISDN_MAJOR_VERSION 1 #define MISDN_MINOR_VERSION 1 -#define MISDN_RELEASE 21 +#define MISDN_RELEASE 20 /* primitives for information exchange * generell format @@ -153,18 +153,6 @@ #define HFC_VOL_CHANGE_RX 0x2602 #define HFC_SPL_LOOP_ON 0x2603 #define HFC_SPL_LOOP_OFF 0x2604 -/* for T30 FAX and analog modem */ -#define HW_MOD_FRM 0x4000 -#define HW_MOD_FRH 0x4001 -#define HW_MOD_FTM 0x4002 -#define HW_MOD_FTH 0x4003 -#define HW_MOD_FTS 0x4004 -#define HW_MOD_CONNECT 0x4010 -#define HW_MOD_OK 0x4011 -#define HW_MOD_NOCARR 0x4012 -#define HW_MOD_FCERROR 0x4013 -#define HW_MOD_READY 0x4014 -#define HW_MOD_LASTDATA 0x4015 /* DSP_TONE_PATT_ON parameter */ #define TONE_OFF 0x0000 @@ -236,8 +224,6 @@ #define ISDN_P_B_L2DTMF 0x24 #define ISDN_P_B_L2DSP 0x25 #define ISDN_P_B_L2DSPHDLC 0x26 -#define ISDN_P_B_T30_FAX 0x27 -#define ISDN_P_B_MODEM_ASYNC 0x28 #define OPTION_L2_PMX 1 #define OPTION_L2_PTP 2 diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 36f8f245fa4c..52928ad90570 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -1293,7 +1293,7 @@ static void ieee80211_rfkill_poll(struct wiphy *wiphy) } #ifdef CONFIG_NL80211_TESTMODE -int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) +static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) { struct ieee80211_local *local = wiphy_priv(wiphy);