⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hisax_fcpcipnp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Driver for AVM Fritz!PCI, Fritz!PCI v2, Fritz!PnP ISDN cards * * Author       Kai Germaschewski * Copyright    2001 by Kai Germaschewski  <kai.germaschewski@gmx.de> *              2001 by Karsten Keil       <keil@isdn4linux.de> *  * based upon Karsten Keil's original avm_pci.c driver * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * * Thanks to Wizard Computersysteme GmbH, Bremervoerde and *           SoHaNet Technology GmbH, Berlin * for supporting the development of this driver *//* TODO: * * o POWER PC * o clean up debugging * o tx_skb at PH_DEACTIVATE time */#include <linux/module.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/isapnp.h>#include <linux/kmod.h>#include <linux/slab.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include <linux/delay.h>#include <asm/io.h>#include "hisax_fcpcipnp.h"// debugging cruft#define __debug_variable debug#include "hisax_debug.h"#ifdef CONFIG_HISAX_DEBUGstatic int debug = 0;/* static int hdlcfifosize = 32; */module_param(debug, int, 0);/* module_param(hdlcfifosize, int, 0); */#endifMODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");static struct pci_device_id fcpci_ids[] = {	{ .vendor      = PCI_VENDOR_ID_AVM,	  .device      = PCI_DEVICE_ID_AVM_A1,	  .subvendor   = PCI_ANY_ID,	  .subdevice   = PCI_ANY_ID,	  .driver_data = (unsigned long) "Fritz!Card PCI",	},	{ .vendor      = PCI_VENDOR_ID_AVM,	  .device      = PCI_DEVICE_ID_AVM_A1_V2,	  .subvendor   = PCI_ANY_ID,	  .subdevice   = PCI_ANY_ID,	  .driver_data = (unsigned long) "Fritz!Card PCI v2" },	{}};MODULE_DEVICE_TABLE(pci, fcpci_ids);#ifdef __ISAPNP__static struct pnp_device_id fcpnp_ids[] __devinitdata = {	{ 		.id		= "AVM0900",		.driver_data	= (unsigned long) "Fritz!Card PnP",	},};MODULE_DEVICE_TABLE(isapnp, fcpnp_ids);#endifstatic int protocol = 2;       /* EURO-ISDN Default */module_param(protocol, int, 0);MODULE_LICENSE("GPL");// ----------------------------------------------------------------------#define  AVM_INDEX              0x04#define  AVM_DATA               0x10#define	 AVM_IDX_HDLC_1		0x00#define	 AVM_IDX_HDLC_2		0x01#define	 AVM_IDX_ISAC_FIFO	0x02#define	 AVM_IDX_ISAC_REG_LOW	0x04#define	 AVM_IDX_ISAC_REG_HIGH	0x06#define  AVM_STATUS0            0x02#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            0x03#define  AVM_STATUS1_ENA_IOM	0x80#define  HDLC_FIFO		0x0#define  HDLC_STATUS		0x4#define  HDLC_CTRL		0x4#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	0xff00#define  HDLC_CMD_XRS		0x80#define  HDLC_CMD_XME		0x01#define  HDLC_CMD_RRS		0x20#define  HDLC_CMD_XML_MASK	0xff00#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_ISACSX_INDEX       0x04#define  AVM_ISACSX_DATA        0x08// ----------------------------------------------------------------------// Fritz!PCIstatic unsigned char fcpci_read_isac(struct isac *isac, unsigned char offset){	struct fritz_adapter *adapter = isac->priv;	unsigned char idx = (offset > 0x2f) ? 		AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;	unsigned char val;	unsigned long flags;	spin_lock_irqsave(&adapter->hw_lock, flags);	outb(idx, adapter->io + AVM_INDEX);	val = inb(adapter->io + AVM_DATA + (offset & 0xf)); 	spin_unlock_irqrestore(&adapter->hw_lock, flags);	DBG(0x1000, " port %#x, value %#x",	    offset, val);	return val;}static void fcpci_write_isac(struct isac *isac, unsigned char offset,			     unsigned char value){	struct fritz_adapter *adapter = isac->priv;	unsigned char idx = (offset > 0x2f) ? 		AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;	unsigned long flags;	DBG(0x1000, " port %#x, value %#x",	    offset, value);	spin_lock_irqsave(&adapter->hw_lock, flags);	outb(idx, adapter->io + AVM_INDEX);	outb(value, adapter->io + AVM_DATA + (offset & 0xf)); 	spin_unlock_irqrestore(&adapter->hw_lock, flags);}static void fcpci_read_isac_fifo(struct isac *isac, unsigned char * data, 				 int size){	struct fritz_adapter *adapter = isac->priv;	unsigned long flags;	spin_lock_irqsave(&adapter->hw_lock, flags);	outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);	insb(adapter->io + AVM_DATA, data, size); 	spin_unlock_irqrestore(&adapter->hw_lock, flags);}static void fcpci_write_isac_fifo(struct isac *isac, unsigned char * data, 				  int size){	struct fritz_adapter *adapter = isac->priv;	unsigned long flags;	spin_lock_irqsave(&adapter->hw_lock, flags);	outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);	outsb(adapter->io + AVM_DATA, data, size); 	spin_unlock_irqrestore(&adapter->hw_lock, flags);}static u32 fcpci_read_hdlc_status(struct fritz_adapter *adapter, int nr){	u32 val;	int idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;	unsigned long flags;	spin_lock_irqsave(&adapter->hw_lock, flags);	outl(idx, adapter->io + AVM_INDEX);	val = inl(adapter->io + AVM_DATA + HDLC_STATUS);	spin_unlock_irqrestore(&adapter->hw_lock, flags);	return val;}static void __fcpci_write_ctrl(struct fritz_bcs *bcs, int which){	struct fritz_adapter *adapter = bcs->adapter;	int idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;	DBG(0x40, "hdlc %c wr%x ctrl %x",	    'A' + bcs->channel, which, bcs->ctrl.ctrl);	outl(idx, adapter->io + AVM_INDEX);	outl(bcs->ctrl.ctrl, adapter->io + AVM_DATA + HDLC_CTRL);}static void fcpci_write_ctrl(struct fritz_bcs *bcs, int which){	struct fritz_adapter *adapter = bcs->adapter;	unsigned long flags;	spin_lock_irqsave(&adapter->hw_lock, flags);	__fcpci_write_ctrl(bcs, which);	spin_unlock_irqrestore(&adapter->hw_lock, flags);}// ----------------------------------------------------------------------// Fritz!PCI v2static unsigned char fcpci2_read_isac(struct isac *isac, unsigned char offset){	struct fritz_adapter *adapter = isac->priv;	unsigned char val;	unsigned long flags;	spin_lock_irqsave(&adapter->hw_lock, flags);	outl(offset, adapter->io + AVM_ISACSX_INDEX);	val = inl(adapter->io + AVM_ISACSX_DATA); 	spin_unlock_irqrestore(&adapter->hw_lock, flags);	DBG(0x1000, " port %#x, value %#x",	    offset, val);	return val;}static void fcpci2_write_isac(struct isac *isac, unsigned char offset, 			      unsigned char value){	struct fritz_adapter *adapter = isac->priv;	unsigned long flags;	DBG(0x1000, " port %#x, value %#x",	    offset, value);	spin_lock_irqsave(&adapter->hw_lock, flags);	outl(offset, adapter->io + AVM_ISACSX_INDEX);	outl(value, adapter->io + AVM_ISACSX_DATA); 	spin_unlock_irqrestore(&adapter->hw_lock, flags);}static void fcpci2_read_isac_fifo(struct isac *isac, unsigned char * data, 				  int size){	struct fritz_adapter *adapter = isac->priv;	int i;	unsigned long flags;	spin_lock_irqsave(&adapter->hw_lock, flags);	outl(0, adapter->io + AVM_ISACSX_INDEX);	for (i = 0; i < size; i++)		data[i] = inl(adapter->io + AVM_ISACSX_DATA); 	spin_unlock_irqrestore(&adapter->hw_lock, flags);}static void fcpci2_write_isac_fifo(struct isac *isac, unsigned char * data, 				   int size){	struct fritz_adapter *adapter = isac->priv;	int i;	unsigned long flags;	spin_lock_irqsave(&adapter->hw_lock, flags);	outl(0, adapter->io + AVM_ISACSX_INDEX);	for (i = 0; i < size; i++)		outl(data[i], adapter->io + AVM_ISACSX_DATA); 	spin_unlock_irqrestore(&adapter->hw_lock, flags);}static u32 fcpci2_read_hdlc_status(struct fritz_adapter *adapter, int nr){	int offset = nr ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;	return inl(adapter->io + offset);}static void fcpci2_write_ctrl(struct fritz_bcs *bcs, int which){	struct fritz_adapter *adapter = bcs->adapter;	int offset = bcs->channel ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;	DBG(0x40, "hdlc %c wr%x ctrl %x",	    'A' + bcs->channel, which, bcs->ctrl.ctrl);	outl(bcs->ctrl.ctrl, adapter->io + offset);}// ----------------------------------------------------------------------// Fritz!PnP (ISAC access as for Fritz!PCI)static u32 fcpnp_read_hdlc_status(struct fritz_adapter *adapter, int nr){	unsigned char idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;	u32 val;	unsigned long flags;	spin_lock_irqsave(&adapter->hw_lock, flags);	outb(idx, adapter->io + AVM_INDEX);	val = inb(adapter->io + AVM_DATA + HDLC_STATUS);	if (val & HDLC_INT_RPR)		val |= inb(adapter->io + AVM_DATA + HDLC_STATUS + 1) << 8;	spin_unlock_irqrestore(&adapter->hw_lock, flags);	return val;}static void __fcpnp_write_ctrl(struct fritz_bcs *bcs, int which){	struct fritz_adapter *adapter = bcs->adapter;	unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;	DBG(0x40, "hdlc %c wr%x ctrl %x",	    'A' + bcs->channel, which, bcs->ctrl.ctrl);	outb(idx, adapter->io + AVM_INDEX);	if (which & 4)		outb(bcs->ctrl.sr.mode, 		     adapter->io + AVM_DATA + HDLC_STATUS + 2);	if (which & 2)		outb(bcs->ctrl.sr.xml, 		     adapter->io + AVM_DATA + HDLC_STATUS + 1);	if (which & 1)		outb(bcs->ctrl.sr.cmd,		     adapter->io + AVM_DATA + HDLC_STATUS + 0);}static void fcpnp_write_ctrl(struct fritz_bcs *bcs, int which){	struct fritz_adapter *adapter = bcs->adapter;	unsigned long flags;	spin_lock_irqsave(&adapter->hw_lock, flags);	__fcpnp_write_ctrl(bcs, which);	spin_unlock_irqrestore(&adapter->hw_lock, flags);}// ----------------------------------------------------------------------static inline void B_L1L2(struct fritz_bcs *bcs, int pr, void *arg){	struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if;	DBG(2, "pr %#x", pr);	ifc->l1l2(ifc, pr, arg);}static void hdlc_fill_fifo(struct fritz_bcs *bcs){	struct fritz_adapter *adapter = bcs->adapter;	struct sk_buff *skb = bcs->tx_skb;	int count;	unsigned long flags;	unsigned char *p;	DBG(0x40, "hdlc_fill_fifo");	if (skb->len == 0)		BUG();	bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME;	if (bcs->tx_skb->len > bcs->fifo_size) {		count = bcs->fifo_size;	} else {		count = bcs->tx_skb->len;		if (bcs->mode != L1_MODE_TRANS)			bcs->ctrl.sr.cmd |= HDLC_CMD_XME;	}	DBG(0x40, "hdlc_fill_fifo %d/%d", count, bcs->tx_skb->len);	p = bcs->tx_skb->data;	skb_pull(bcs->tx_skb, count);	bcs->tx_cnt += count;	bcs->ctrl.sr.xml = ((count == bcs->fifo_size) ? 0 : count);	switch (adapter->type) {	case AVM_FRITZ_PCI:		spin_lock_irqsave(&adapter->hw_lock, flags);		// sets the correct AVM_INDEX, too		__fcpci_write_ctrl(bcs, 3);		outsl(adapter->io + AVM_DATA + HDLC_FIFO,		      p, (count + 3) / 4);		spin_unlock_irqrestore(&adapter->hw_lock, flags);		break;	case AVM_FRITZ_PCIV2:		fcpci2_write_ctrl(bcs, 3);		outsl(adapter->io + 		      (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),		      p, (count + 3) / 4);		break;	case AVM_FRITZ_PNP:		spin_lock_irqsave(&adapter->hw_lock, flags);		// sets the correct AVM_INDEX, too		__fcpnp_write_ctrl(bcs, 3);		outsb(adapter->io + AVM_DATA, p, count);		spin_unlock_irqrestore(&adapter->hw_lock, flags);		break;	}}static inline void hdlc_empty_fifo(struct fritz_bcs *bcs, int count){	struct fritz_adapter *adapter = bcs->adapter;	unsigned char *p;	unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;	DBG(0x10, "hdlc_empty_fifo %d", count);	if (bcs->rcvidx + count > HSCX_BUFMAX) {		DBG(0x10, "hdlc_empty_fifo: incoming packet too large");		return;	}	p = bcs->rcvbuf + bcs->rcvidx;	bcs->rcvidx += count;	switch (adapter->type) {	case AVM_FRITZ_PCI:		spin_lock(&adapter->hw_lock);		outl(idx, adapter->io + AVM_INDEX);		insl(adapter->io + AVM_DATA + HDLC_FIFO, 		     p, (count + 3) / 4);		spin_unlock(&adapter->hw_lock);		break;	case AVM_FRITZ_PCIV2:		insl(adapter->io + 		     (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),		     p, (count + 3) / 4);		break;	case AVM_FRITZ_PNP:		spin_lock(&adapter->hw_lock);		outb(idx, adapter->io + AVM_INDEX);		insb(adapter->io + AVM_DATA, p, count);		spin_unlock(&adapter->hw_lock);		break;	}}static inline void hdlc_rpr_irq(struct fritz_bcs *bcs, u32 stat){	struct fritz_adapter *adapter = bcs->adapter;	struct sk_buff *skb;	int len;	if (stat & HDLC_STAT_RDO) {		DBG(0x10, "RDO");		bcs->ctrl.sr.xml = 0;		bcs->ctrl.sr.cmd |= HDLC_CMD_RRS;		adapter->write_ctrl(bcs, 1);		bcs->ctrl.sr.cmd &= ~HDLC_CMD_RRS;		adapter->write_ctrl(bcs, 1);		bcs->rcvidx = 0;		return;	}	len = (stat & HDLC_STAT_RML_MASK) >> 8;	if (len == 0)		len = bcs->fifo_size;	hdlc_empty_fifo(bcs, len);	if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {		if (((stat & HDLC_STAT_CRCVFRRAB)== HDLC_STAT_CRCVFR) ||		    (bcs->mode == L1_MODE_TRANS)) {			skb = dev_alloc_skb(bcs->rcvidx);			if (!skb) {				printk(KERN_WARNING "HDLC: receive out of memory\n");			} else {				memcpy(skb_put(skb, bcs->rcvidx), bcs->rcvbuf,				       bcs->rcvidx);				DBG_SKB(1, skb);				B_L1L2(bcs, PH_DATA | INDICATION, skb);			}			bcs->rcvidx = 0;		} else {			DBG(0x10, "ch%d invalid frame %#x",			    bcs->channel, stat);			bcs->rcvidx = 0;		}	}}static inline void hdlc_xdu_irq(struct fritz_bcs *bcs){	struct fritz_adapter *adapter = bcs->adapter;	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -