hisax_hfcpci.c

来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 1,647 行 · 第 1/3 页

C
1,647
字号
/* * Driver for HFC PCI based cards * * Author       Kai Germaschewski * Copyright    2002 by Kai Germaschewski  <kai.germaschewski@gmx.de> *              2000 by Karsten Keil       <keil@isdn4linux.de> *              2000 by Werner Cornelius   <werner@isdn4linux.de> *  * based upon Werner Cornelius's original hfc_pci.c driver * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */// XXX timer3#include <linux/version.h>#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 <asm/delay.h>#include "hisax_hfcpci.h"// debugging cruft#define __debug_variable debug#include "hisax_debug.h"#ifdef CONFIG_HISAX_DEBUGstatic int debug = 0;MODULE_PARM(debug, "i");#endifMODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Werner Cornelius <werner@isdn4linux.de>");MODULE_DESCRIPTION("HFC PCI ISDN driver");#define ID(ven, dev, name)                     \        { vendor:      PCI_VENDOR_ID_##ven,    \	  device:      PCI_DEVICE_ID_##dev,    \	  subvendor:   PCI_ANY_ID,             \	  subdevice:   PCI_ANY_ID,             \	  class:       0,                      \          class_mask:  0,                      \	  driver_data: (unsigned long) name }static struct pci_device_id hfcpci_ids[] __devinitdata = {	ID(CCD,     CCD_2BD0,         "CCD/Billion/Asuscom 2BD0"),	ID(CCD,     CCD_B000,         "Billion B000"),	ID(CCD,     CCD_B006,         "Billion B006"),	ID(CCD,     CCD_B007,         "Billion B007"),	ID(CCD,     CCD_B008,         "Billion B008"),	ID(CCD,     CCD_B009,         "Billion B009"),	ID(CCD,     CCD_B00A,         "Billion B00A"),	ID(CCD,     CCD_B00B,         "Billion B00B"),	ID(CCD,     CCD_B00C,         "Billion B00C"),	ID(CCD,     CCD_B100,         "Seyeon"),	ID(ABOCOM,  ABOCOM_2BD1,      "Abocom/Magitek"),	ID(ASUSTEK, ASUSTEK_0675,     "Asuscom/Askey"),	ID(BERKOM,  BERKOM_T_CONCEPT, "German Telekom T-Concept"),	ID(BERKOM,  BERKOM_A1T,       "German Telekom A1T"),	ID(ANIGMA,  ANIGMA_MC145575,  "Motorola MC145575"),	ID(ZOLTRIX, ZOLTRIX_2BD0,     "Zoltrix 2BD0"),	ID(DIGI,    DIGI_DF_M_IOM2_E, "Digi DataFire Micro V IOM2 (Europe)"),	ID(DIGI,    DIGI_DF_M_E,      "Digi DataFire Micro V (Europe)"),	ID(DIGI,    DIGI_DF_M_IOM2_A, "Digi DataFire Micro V IOM2 (America)"),	ID(DIGI,    DIGI_DF_M_A,      "Digi DataFire Micro V (America)"),	{ } };MODULE_DEVICE_TABLE(pci, hfcpci_ids);#undef IDstatic int protocol = 2;       /* EURO-ISDN Default */MODULE_PARM(protocol, "i");// ----------------------------------------------------------------------//#define DBG_WARN      0x0001#define DBG_INFO      0x0002#define DBG_IRQ       0x0010#define DBG_L1M       0x0020#define DBG_PR        0x0040#define DBG_D_XMIT    0x0100#define DBG_D_RECV    0x0200#define DBG_B_XMIT    0x1000#define DBG_B_RECV    0x2000/* memory window base address offset (in config space) */#define HFCPCI_MWBA      0x80/* GCI/IOM bus monitor registers */#define HCFPCI_C_I       0x08#define HFCPCI_TRxR      0x0C#define HFCPCI_MON1_D    0x28#define HFCPCI_MON2_D    0x2C/* GCI/IOM bus timeslot registers */#define HFCPCI_B1_SSL    0x80#define HFCPCI_B2_SSL    0x84#define HFCPCI_AUX1_SSL  0x88#define HFCPCI_AUX2_SSL  0x8C#define HFCPCI_B1_RSL    0x90#define HFCPCI_B2_RSL    0x94#define HFCPCI_AUX1_RSL  0x98#define HFCPCI_AUX2_RSL  0x9C/* GCI/IOM bus data registers */#define HFCPCI_B1_D      0xA0#define HFCPCI_B2_D      0xA4#define HFCPCI_AUX1_D    0xA8#define HFCPCI_AUX2_D    0xAC/* GCI/IOM bus configuration registers */#define HFCPCI_MST_EMOD  0xB4#define HFCPCI_MST_MODE	 0xB8#define HFCPCI_CONNECT 	 0xBC/* Interrupt and status registers */#define HFCPCI_FIFO_EN   0x44#define HFCPCI_TRM       0x48#define HFCPCI_B_MODE    0x4C#define HFCPCI_CHIP_ID   0x58#define HFCPCI_CIRM  	 0x60#define HFCPCI_CTMT	 0x64#define HFCPCI_INT_M1  	 0x68#define HFCPCI_INT_M2  	 0x6C#define HFCPCI_INT_S1  	 0x78#define HFCPCI_INT_S2  	 0x7C#define HFCPCI_STATUS  	 0x70/* S/T section registers */#define HFCPCI_STATES  	 0xC0#define HFCPCI_SCTRL  	 0xC4#define HFCPCI_SCTRL_E   0xC8#define HFCPCI_SCTRL_R   0xCC#define HFCPCI_SQ  	 0xD0#define HFCPCI_CLKDEL  	 0xDC#define HFCPCI_B1_REC    0xF0#define HFCPCI_B1_SEND   0xF0#define HFCPCI_B2_REC    0xF4#define HFCPCI_B2_SEND   0xF4#define HFCPCI_D_REC     0xF8#define HFCPCI_D_SEND    0xF8#define HFCPCI_E_REC     0xFC/* bits in status register (READ) */#define HFCPCI_PCI_PROC   0x02#define HFCPCI_NBUSY	  0x04 #define HFCPCI_TIMER_ELAP 0x10#define HFCPCI_STATINT	  0x20#define HFCPCI_FRAMEINT	  0x40#define HFCPCI_ANYINT	  0x80/* bits in CTMT (Write) */#define HFCPCI_CLTIMER    0x80#define HFCPCI_TIM3_125   0x04#define HFCPCI_TIM25      0x10#define HFCPCI_TIM50      0x14#define HFCPCI_TIM400     0x18#define HFCPCI_TIM800     0x1C#define HFCPCI_AUTO_TIMER 0x20#define HFCPCI_TRANSB2    0x02#define HFCPCI_TRANSB1    0x01/* bits in CIRM (Write) */#define HFCPCI_AUX_MSK    0x07#define HFCPCI_RESET  	  0x08#define HFCPCI_B1_REV     0x40#define HFCPCI_B2_REV     0x80/* bits in INT_M1 and INT_S1 */#define HFCPCI_INTS_B1TRANS  0x01#define HFCPCI_INTS_B2TRANS  0x02#define HFCPCI_INTS_DTRANS   0x04#define HFCPCI_INTS_B1REC    0x08#define HFCPCI_INTS_B2REC    0x10#define HFCPCI_INTS_DREC     0x20#define HFCPCI_INTS_L1STATE  0x40#define HFCPCI_INTS_TIMER    0x80/* bits in INT_M2 */#define HFCPCI_PROC_TRANS    0x01#define HFCPCI_GCI_I_CHG     0x02#define HFCPCI_GCI_MON_REC   0x04#define HFCPCI_IRQ_ENABLE    0x08#define HFCPCI_PMESEL        0x80/* bits in STATES */#define HFCPCI_STATE_MSK     0x0F#define HFCPCI_LOAD_STATE    0x10#define HFCPCI_ACTIVATE	     0x20#define HFCPCI_DO_ACTION     0x40#define HFCPCI_NT_G2_G3      0x80/* bits in HFCD_MST_MODE */#define HFCPCI_MASTER	     0x01#define HFCPCI_SLAVE         0x00/* remaining bits are for codecs control *//* bits in HFCD_SCTRL */#define SCTRL_B1_ENA	     0x01#define SCTRL_B2_ENA	     0x02#define SCTRL_MODE_TE        0x00#define SCTRL_MODE_NT        0x04#define SCTRL_LOW_PRIO	     0x08#define SCTRL_SQ_ENA	     0x10#define SCTRL_TEST	     0x20#define SCTRL_NONE_CAP	     0x40#define SCTRL_PWR_DOWN	     0x80/* bits in SCTRL_E  */#define HFCPCI_AUTO_AWAKE    0x01#define HFCPCI_DBIT_1        0x04#define HFCPCI_IGNORE_COL    0x08#define HFCPCI_CHG_B1_B2     0x80/* bits in FIFO_EN register */#define HFCPCI_FIFOEN_B1     0x03#define HFCPCI_FIFOEN_B2     0x0C#define HFCPCI_FIFOEN_DTX    0x10#define HFCPCI_FIFOEN_DRX    0x20#define HFCPCI_FIFOEN_B1TX   0x01#define HFCPCI_FIFOEN_B1RX   0x02#define HFCPCI_FIFOEN_B2TX   0x04#define HFCPCI_FIFOEN_B2RX   0x08/* * thresholds for transparent B-channel mode * change mask and threshold simultaneously */#define HFCPCI_BTRANS_THRESHOLD 128#define HFCPCI_BTRANS_THRESMASK 0x00#define CLKDEL_TE	0x0e	/* CLKDEL in TE mode */#define CLKDEL_NT	0x6c	/* CLKDEL in NT mode */#define MAX_D_FRAMES 0x10#define MAX_B_FRAMES 0x20#define B_FIFO_START 0x0200#define B_FIFO_END   0x2000#define B_FIFO_SIZE  (B_FIFO_END - B_FIFO_START)#define D_FIFO_START 0x0000#define D_FIFO_END   0x0200#define D_FIFO_SIZE  (D_FIFO_END - D_FIFO_START)// ----------------------------------------------------------------------// push messages to the upper layersstatic inline void D_L1L2(struct hfcpci_adapter *adapter, int pr, void *arg){	struct hisax_if *ifc = (struct hisax_if *) &adapter->d_if;	DBG(DBG_PR, "pr %#x", pr);	ifc->l1l2(ifc, pr, arg);}static inline void B_L1L2(struct hfcpci_bcs *bcs, int pr, void *arg){	struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if;	DBG(DBG_PR, "pr %#x", pr);	ifc->l1l2(ifc, pr, arg);}// ----------------------------------------------------------------------// MMIOstatic inline voidhfcpci_writeb(struct hfcpci_adapter *adapter, u8 b, unsigned char offset){	writeb(b, adapter->mmio + offset);}static inline u8hfcpci_readb(struct hfcpci_adapter *adapter, unsigned char offset){	return readb(adapter->mmio + offset);}// ----------------------------------------------------------------------// magic to define the various F/Z counter accesses#define DECL_B_F(r, f)                                                      \static inline u8                                                            \get_b_##r##_##f (struct hfcpci_bcs *bcs)                                    \{                                                                           \	u16 off = bcs->channel ? OFF_B2_##r##_##f : OFF_B1_##r##_##f;       \                                                                            \	return *(bcs->adapter->fifo + off);                                 \}                                                                           \                                                                            \static inline void                                                          \set_b_##r##_##f (struct hfcpci_bcs *bcs, u8 f)                              \{                                                                           \	u16 off = bcs->channel ? OFF_B2_##r##_##f : OFF_B1_##r##_##f;       \                                                                            \	*(bcs->adapter->fifo + off) = f;                                    \}#define OFF_B1_rx_f1 0x6080#define OFF_B2_rx_f1 0x6180#define OFF_B1_rx_f2 0x6081#define OFF_B2_rx_f2 0x6181#define OFF_B1_tx_f1 0x2080#define OFF_B2_tx_f1 0x2180#define OFF_B1_tx_f2 0x2081#define OFF_B2_tx_f2 0x2181DECL_B_F(rx, f1)DECL_B_F(rx, f2)DECL_B_F(tx, f1)DECL_B_F(tx, f2)#undef DECL_B_F#define DECL_B_Z(r, z)                                                      \static inline u16                                                           \get_b_##r##_##z (struct hfcpci_bcs *bcs, u8 f)                              \{                                                                           \	u16 off = bcs->channel ? OFF_B2_##r##_##z : OFF_B1_##r##_##z;       \                                                                            \	return le16_to_cpu(*((u16 *) (bcs->adapter->fifo + off + f * 4)));  \}                                                                           \                                                                            \static inline void                                                          \set_b_##r##_##z(struct hfcpci_bcs *bcs, u8 f, u16 z)                        \{                                                                           \	u16 off = bcs->channel ? OFF_B2_##r##_##z : OFF_B1_##r##_##z;       \                                                                            \	*((u16 *) (bcs->adapter->fifo + off + f * 4)) = cpu_to_le16(z);     \}#define OFF_B1_rx_z1 0x6000#define OFF_B2_rx_z1 0x6100#define OFF_B1_rx_z2 0x6002#define OFF_B2_rx_z2 0x6102#define OFF_B1_tx_z1 0x2000#define OFF_B2_tx_z1 0x2100#define OFF_B1_tx_z2 0x2002#define OFF_B2_tx_z2 0x2102DECL_B_Z(rx, z1)DECL_B_Z(rx, z2)DECL_B_Z(tx, z1)DECL_B_Z(tx, z2)#undef DECL_B_Z#define DECL_D_F(r, f)                                                      \static inline u8                                                            \get_d_##r##_##f (struct hfcpci_adapter *adapter)                            \{                                                                           \	u16 off = OFF_D_##r##_##f;                                          \                                                                            \	return *(adapter->fifo + off) & 0xf;                                \}                                                                           \                                                                            \static inline void                                                          \set_d_##r##_##f (struct hfcpci_adapter *adapter, u8 f)                      \{                                                                           \	u16 off = OFF_D_##r##_##f;                                          \                                                                            \	*(adapter->fifo + off) = f | 0x10;                                  \}#define OFF_D_rx_f1 0x60a0#define OFF_D_rx_f2 0x60a1#define OFF_D_tx_f1 0x20a0#define OFF_D_tx_f2 0x20a1DECL_D_F(rx, f1)DECL_D_F(rx, f2)DECL_D_F(tx, f1)DECL_D_F(tx, f2)#undef DECL_D_F#define DECL_D_Z(r, z)                                                      \static inline u16                                                           \get_d_##r##_##z (struct hfcpci_adapter *adapter, u8 f)                      \{                                                                           \	u16 off = OFF_D_##r##_##z;                                          \                                                                            \	return le16_to_cpu(*((u16 *) (adapter->fifo + off + (f | 0x10) * 4)));\}                                                                           \                                                                            \static inline void                                                          \set_d_##r##_##z(struct hfcpci_adapter *adapter, u8 f, u16 z)                \{                                                                           \	u16 off = OFF_D_##r##_##z;                                          \                                                                            \	*((u16 *) (adapter->fifo + off + (f | 0x10) * 4)) = cpu_to_le16(z); \}#define OFF_D_rx_z1 0x6080#define OFF_D_rx_z2 0x6082#define OFF_D_tx_z1 0x2080#define OFF_D_tx_z2 0x2082DECL_D_Z(rx, z1)DECL_D_Z(rx, z2)DECL_D_Z(tx, z1)DECL_D_Z(tx, z2)#undef DECL_B_Z// ----------------------------------------------------------------------// fill b / d fifosstatic inline voidhfcpci_fill_d_fifo(struct hfcpci_adapter *adapter){	u8 f1, f2;	u16 z1, z2;	int cnt, fcnt;	char *fifo_adr = adapter->fifo;	struct sk_buff *tx_skb = adapter->tx_skb;		f1 = get_d_tx_f1(adapter);	f2 = get_d_tx_f2(adapter);	DBG(DBG_D_XMIT, "f1 %#x f2 %#x", f1, f2);	fcnt = f1 - f2;	if (fcnt < 0)		fcnt += MAX_D_FRAMES;		if (fcnt) {		printk("BUG\n");		return;	}	z1 = get_d_tx_z1(adapter, f1);	z2 = get_d_tx_z2(adapter, f1); //XXX	DBG(DBG_D_XMIT, "z1 %#x z2 %#x", z1, z2);	cnt = z2 - z1;	if (cnt <= 0)		cnt += D_FIFO_SIZE;	if (tx_skb->len > cnt) {		printk("BUG\n");		return;	}	cnt = tx_skb->len;	if (z1 + cnt <= D_FIFO_END) {		memcpy(fifo_adr + z1, tx_skb->data, cnt);	} else {		memcpy(fifo_adr + z1, tx_skb->data, D_FIFO_END - z1);		memcpy(fifo_adr + D_FIFO_START, 		       tx_skb->data + (D_FIFO_END - z1), 		       cnt - (D_FIFO_END - z1));	}	z1 += cnt;	if (z1 >= D_FIFO_END)		z1 -= D_FIFO_SIZE;	f1 = (f1 + 1) & (MAX_D_FRAMES - 1);	mb();	set_d_tx_z1(adapter, f1, z1);	mb();	set_d_tx_f1(adapter, f1);}static inline voidhfcpci_fill_b_fifo_hdlc(struct hfcpci_bcs *bcs){	u8 f1, f2;	u16 z1, z2;	int cnt, fcnt;	char *fifo_adr = bcs->adapter->fifo + (bcs->channel ? 0x2000 : 0x0000);	struct sk_buff *tx_skb = bcs->tx_skb;		f1 = get_b_tx_f1(bcs);	f2 = get_b_tx_f2(bcs);	DBG(DBG_B_XMIT, "f1 %#x f2 %#x", f1, f2);	fcnt = f1 - f2;	if (fcnt < 0)		fcnt += MAX_B_FRAMES;		if (fcnt) {		printk("BUG\n");		return;	}	z1 = get_b_tx_z1(bcs, f1);	z2 = get_b_tx_z2(bcs, f1); //XXX	DBG(DBG_B_XMIT, "z1 %#x z2 %#x", z1, z2);	cnt = z2 - z1;	if (cnt <= 0)		cnt += B_FIFO_SIZE;	if (tx_skb->len > cnt) {		printk("BUG\n");		return;	}	cnt = tx_skb->len;	if (z1 + cnt <= B_FIFO_END) {		memcpy(fifo_adr + z1, tx_skb->data, cnt);	} else {		memcpy(fifo_adr + z1, tx_skb->data, B_FIFO_END - z1);		memcpy(fifo_adr + B_FIFO_START,		       tx_skb->data + (B_FIFO_END - z1), 		       cnt - (B_FIFO_END - z1));	}	z1 += cnt;	if (z1 >= B_FIFO_END)		z1 -= B_FIFO_SIZE;	f1 = (f1 + 1) & (MAX_B_FRAMES - 1);	mb();	set_b_tx_z1(bcs, f1, z1);	mb();	set_b_tx_f1(bcs, f1);}static inline voidhfcpci_fill_b_fifo_trans(struct hfcpci_bcs *bcs){	int cnt;	char *fifo_adr = bcs->adapter->fifo + (bcs->channel ? 0x2000 : 0x0000);	struct sk_buff *tx_skb = bcs->tx_skb;	u8 f1, f2;	u16 z1, z2;	f1 = get_b_tx_f1(bcs);

⌨️ 快捷键说明

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