brintos

brintos / linux-shallow public Read only

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