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

📄 hisax_isac.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
{	// this also works for isacsx, since	// CMDR(D) register works the same	u_char *ptr;	DBG(DBG_IRQ, "count %d", count);	if ((isac->rcvidx + count) >= MAX_DFRAME_LEN_L1) {		DBG(DBG_WARN, "overrun %d", isac->rcvidx + count);		isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);		isac->rcvidx = 0;		return;	}	ptr = isac->rcvbuf + isac->rcvidx;	isac->rcvidx += count;	isac->read_isac_fifo(isac, ptr, count);	isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);	DBG_PACKET(DBG_RFIFO, ptr, count);}static void isac_fill_fifo(struct isac *isac){	// this also works for isacsx, since	// CMDR(D) register works the same	int count;	unsigned char cmd;	u_char *ptr;	if (!isac->tx_skb)		BUG();	count = isac->tx_skb->len;	if (count <= 0)		BUG();	DBG(DBG_IRQ, "count %d", count);	if (count > 0x20) {		count = 0x20;		cmd = ISAC_CMDR_XTF;	} else {		cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;	}	ptr = isac->tx_skb->data;	skb_pull(isac->tx_skb, count);	isac->tx_cnt += count;	DBG_PACKET(DBG_XFIFO, ptr, count);	isac->write_isac_fifo(isac, ptr, count);	isac->write_isac(isac, ISAC_CMDR, cmd);}static void isac_retransmit(struct isac *isac){	if (!isac->tx_skb) {		DBG(DBG_WARN, "no skb");		return;	}	skb_push(isac->tx_skb, isac->tx_cnt);	isac->tx_cnt = 0;}static inline void isac_cisq_interrupt(struct isac *isac){	unsigned char val;	val = isac->read_isac(isac, ISAC_CIR0);	DBG(DBG_IRQ, "CIR0 %#x", val);	if (val & ISAC_CIR0_CIC0) {		DBG(DBG_IRQ, "CODR0 %#x", (val >> 2) & 0xf);		FsmEvent(&isac->l1m, (val >> 2) & 0xf, NULL);	}	if (val & ISAC_CIR0_CIC1) {		val = isac->read_isac(isac, ISAC_CIR1);		DBG(DBG_WARN, "ISAC CIR1 %#x", val );	}}static inline void isac_rme_interrupt(struct isac *isac){	unsigned char val;	int count;	struct sk_buff *skb;		val = isac->read_isac(isac, ISAC_RSTA);	if ((val & (ISAC_RSTA_RDO | ISAC_RSTA_CRC | ISAC_RSTA_RAB) )	     != ISAC_RSTA_CRC) {		DBG(DBG_WARN, "RSTA %#x, dropped", val);		isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);		goto out;	}	count = isac->read_isac(isac, ISAC_RBCL) & 0x1f;	DBG(DBG_IRQ, "RBCL %#x", count);	if (count == 0)		count = 0x20;	isac_empty_fifo(isac, count);	count = isac->rcvidx;	if (count < 1) {		DBG(DBG_WARN, "count %d < 1", count);		goto out;	}	skb = alloc_skb(count, GFP_ATOMIC);	if (!skb) {		DBG(DBG_WARN, "no memory, dropping\n");		goto out;	}	memcpy(skb_put(skb, count), isac->rcvbuf, count);	DBG_SKB(DBG_RPACKET, skb);	D_L1L2(isac, PH_DATA | INDICATION, skb); out:	isac->rcvidx = 0;}static inline void isac_xpr_interrupt(struct isac *isac){	if (!isac->tx_skb)		return;	if (isac->tx_skb->len > 0) {		isac_fill_fifo(isac);		return;	}	dev_kfree_skb_irq(isac->tx_skb);	isac->tx_cnt = 0;	isac->tx_skb = NULL;	D_L1L2(isac, PH_DATA | CONFIRM, NULL);}static inline void isac_exi_interrupt(struct isac *isac){	unsigned char val;	val = isac->read_isac(isac, ISAC_EXIR);	DBG(2, "EXIR %#x", val);	if (val & ISAC_EXIR_XMR) {		DBG(DBG_WARN, "ISAC XMR");		isac_retransmit(isac);	}	if (val & ISAC_EXIR_XDU) {		DBG(DBG_WARN, "ISAC XDU");		isac_retransmit(isac);	}	if (val & ISAC_EXIR_MOS) {  /* MOS */		DBG(DBG_WARN, "MOS");		val = isac->read_isac(isac, ISAC_MOSR);		DBG(2, "ISAC MOSR %#x", val);	}}void isac_irq(struct isac *isac){	unsigned char val;	val = isac->read_isac(isac, ISAC_ISTA);	DBG(DBG_IRQ, "ISTA %#x", val);	if (val & ISAC_ISTA_EXI) {		DBG(DBG_IRQ, "EXI");		isac_exi_interrupt(isac);	}	if (val & ISAC_ISTA_XPR) {		DBG(DBG_IRQ, "XPR");		isac_xpr_interrupt(isac);	}	if (val & ISAC_ISTA_RME) {		DBG(DBG_IRQ, "RME");		isac_rme_interrupt(isac);	}	if (val & ISAC_ISTA_RPF) {		DBG(DBG_IRQ, "RPF");		isac_empty_fifo(isac, 0x20);	}	if (val & ISAC_ISTA_CISQ) {		DBG(DBG_IRQ, "CISQ");		isac_cisq_interrupt(isac);	}	if (val & ISAC_ISTA_RSC) {		DBG(DBG_WARN, "RSC");	}	if (val & ISAC_ISTA_SIN) {		DBG(DBG_WARN, "SIN");	}	isac->write_isac(isac, ISAC_MASK, 0xff);	isac->write_isac(isac, ISAC_MASK, 0x00);}// ======================================================================static inline void isacsx_cic_interrupt(struct isac *isac){	unsigned char val;	val = isac->read_isac(isac, ISACSX_CIR0);	DBG(DBG_IRQ, "CIR0 %#x", val);	if (val & ISACSX_CIR0_CIC0) {		DBG(DBG_IRQ, "CODR0 %#x", val >> 4);		FsmEvent(&isac->l1m, val >> 4, NULL);	}}static inline void isacsx_rme_interrupt(struct isac *isac){	int count;	struct sk_buff *skb;	unsigned char val;	val = isac->read_isac(isac, ISACSX_RSTAD);	if ((val & (ISACSX_RSTAD_VFR | 		    ISACSX_RSTAD_RDO | 		    ISACSX_RSTAD_CRC | 		    ISACSX_RSTAD_RAB)) 	    != (ISACSX_RSTAD_VFR | ISACSX_RSTAD_CRC)) {		DBG(DBG_WARN, "RSTAD %#x, dropped", val);		isac->write_isac(isac, ISACSX_CMDRD, ISACSX_CMDRD_RMC);		goto out;	}	count = isac->read_isac(isac, ISACSX_RBCLD) & 0x1f;	DBG(DBG_IRQ, "RBCLD %#x", count);	if (count == 0)		count = 0x20;	isac_empty_fifo(isac, count);	// strip trailing status byte	count = isac->rcvidx - 1;	if (count < 1) {		DBG(DBG_WARN, "count %d < 1", count);		goto out;	}	skb = dev_alloc_skb(count);	if (!skb) {		DBG(DBG_WARN, "no memory, dropping");		goto out;	}	memcpy(skb_put(skb, count), isac->rcvbuf, count);	DBG_SKB(DBG_RPACKET, skb);	D_L1L2(isac, PH_DATA | INDICATION, skb); out:	isac->rcvidx = 0;}static inline void isacsx_xpr_interrupt(struct isac *isac){	if (!isac->tx_skb)		return;	if (isac->tx_skb->len > 0) {		isac_fill_fifo(isac);		return;	}	dev_kfree_skb_irq(isac->tx_skb);	isac->tx_skb = NULL;	isac->tx_cnt = 0;	D_L1L2(isac, PH_DATA | CONFIRM, NULL);}static inline void isacsx_icd_interrupt(struct isac *isac){	unsigned char val;	val = isac->read_isac(isac, ISACSX_ISTAD);	DBG(DBG_IRQ, "ISTAD %#x", val);	if (val & ISACSX_ISTAD_XDU) {		DBG(DBG_WARN, "ISTAD XDU");		isac_retransmit(isac);	}	if (val & ISACSX_ISTAD_XMR) {		DBG(DBG_WARN, "ISTAD XMR");		isac_retransmit(isac);	}	if (val & ISACSX_ISTAD_XPR) {		DBG(DBG_IRQ, "ISTAD XPR");		isacsx_xpr_interrupt(isac);	}	if (val & ISACSX_ISTAD_RFO) {		DBG(DBG_WARN, "ISTAD RFO");		isac->write_isac(isac, ISACSX_CMDRD, ISACSX_CMDRD_RMC);	}	if (val & ISACSX_ISTAD_RME) {		DBG(DBG_IRQ, "ISTAD RME");		isacsx_rme_interrupt(isac);	}	if (val & ISACSX_ISTAD_RPF) {		DBG(DBG_IRQ, "ISTAD RPF");		isac_empty_fifo(isac, 0x20);	}}void isacsx_irq(struct isac *isac){	unsigned char val;	val = isac->read_isac(isac, ISACSX_ISTA);	DBG(DBG_IRQ, "ISTA %#x", val);	if (val & ISACSX_ISTA_ICD)		isacsx_icd_interrupt(isac);	if (val & ISACSX_ISTA_CIC)		isacsx_cic_interrupt(isac);}void isac_init(struct isac *isac){	isac->tx_skb = NULL;	isac->l1m.fsm = &l1fsm;	isac->l1m.state = ST_L1_RESET;#ifdef CONFIG_HISAX_DEBUG	isac->l1m.debug = 1;#else	isac->l1m.debug = 0;#endif	isac->l1m.userdata = isac;	isac->l1m.printdebug = l1m_debug;	FsmInitTimer(&isac->l1m, &isac->timer);}void isac_setup(struct isac *isac){	int val, eval;	isac->type = TYPE_ISAC;	isac_version(isac);	ph_command(isac, ISAC_CMD_RES);  	isac->write_isac(isac, ISAC_MASK, 0xff);  	isac->mocr = 0xaa;	if (test_bit(ISAC_IOM1, &isac->flags)) {		/* IOM 1 Mode */		isac->write_isac(isac, ISAC_ADF2, 0x0);		isac->write_isac(isac, ISAC_SPCR, 0xa);		isac->write_isac(isac, ISAC_ADF1, 0x2);		isac->write_isac(isac, ISAC_STCR, 0x70);		isac->write_isac(isac, ISAC_MODE, 0xc9);	} else {		/* IOM 2 Mode */		if (!isac->adf2)			isac->adf2 = 0x80;		isac->write_isac(isac, ISAC_ADF2, isac->adf2);		isac->write_isac(isac, ISAC_SQXR, 0x2f);		isac->write_isac(isac, ISAC_SPCR, 0x00);		isac->write_isac(isac, ISAC_STCR, 0x70);		isac->write_isac(isac, ISAC_MODE, 0xc9);		isac->write_isac(isac, ISAC_TIMR, 0x00);		isac->write_isac(isac, ISAC_ADF1, 0x00);	}	val = isac->read_isac(isac, ISAC_STAR);	DBG(2, "ISAC STAR %x", val);	val = isac->read_isac(isac, ISAC_MODE);	DBG(2, "ISAC MODE %x", val);	val = isac->read_isac(isac, ISAC_ADF2);	DBG(2, "ISAC ADF2 %x", val);	val = isac->read_isac(isac, ISAC_ISTA);	DBG(2, "ISAC ISTA %x", val);	if (val & 0x01) {		eval = isac->read_isac(isac, ISAC_EXIR);		DBG(2, "ISAC EXIR %x", eval);	}	val = isac->read_isac(isac, ISAC_CIR0);	DBG(2, "ISAC CIR0 %x", val);	FsmEvent(&isac->l1m, (val >> 2) & 0xf, NULL);	isac->write_isac(isac, ISAC_MASK, 0x0);	// RESET Receiver and Transmitter	isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_XRES | ISAC_CMDR_RRES);}void isacsx_setup(struct isac *isac){	isac->type = TYPE_ISACSX;	// clear LDD	isac->write_isac(isac, ISACSX_TR_CONF0, 0x00);	// enable transmitter	isac->write_isac(isac, ISACSX_TR_CONF2, 0x00);	// transparent mode 0, RAC, stop/go	isac->write_isac(isac, ISACSX_MODED,    0xc9);	// all HDLC IRQ unmasked	isac->write_isac(isac, ISACSX_MASKD,    0x03);	// unmask ICD, CID IRQs	isac->write_isac(isac, ISACSX_MASK,            			 ~(ISACSX_ISTA_ICD | ISACSX_ISTA_CIC));}void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg){	struct isac *isac = hisax_d_if->priv;	struct sk_buff *skb = arg;	DBG(DBG_PR, "pr %#x", pr);	switch (pr) {	case PH_ACTIVATE | REQUEST:		FsmEvent(&isac->l1m, EV_PH_ACTIVATE_REQ, NULL);		break;	case PH_DEACTIVATE | REQUEST:		FsmEvent(&isac->l1m, EV_PH_DEACTIVATE_REQ, NULL);		break;	case PH_DATA | REQUEST:		DBG(DBG_PR, "PH_DATA REQUEST len %d", skb->len);		DBG_SKB(DBG_XPACKET, skb);		if (isac->l1m.state != ST_L1_F7) {			DBG(1, "L1 wrong state %d\n", isac->l1m.state);			dev_kfree_skb(skb);			break;		}		if (isac->tx_skb)			BUG();		isac->tx_skb = skb;		isac_fill_fifo(isac);		break;	}}static int __init hisax_isac_init(void){	printk(KERN_INFO "hisax_isac: ISAC-S/ISAC-SX ISDN driver v0.1.0\n");	l1fsm.state_count = L1_STATE_COUNT;	l1fsm.event_count = L1_EVENT_COUNT;	l1fsm.strState = strL1State;	l1fsm.strEvent = strL1Event;	return FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList));}static void __exit hisax_isac_exit(void){	FsmFree(&l1fsm);}EXPORT_SYMBOL(isac_init);EXPORT_SYMBOL(isac_d_l2l1);EXPORT_SYMBOL(isacsx_setup);EXPORT_SYMBOL(isacsx_irq);EXPORT_SYMBOL(isac_setup);EXPORT_SYMBOL(isac_irq);module_init(hisax_isac_init);module_exit(hisax_isac_exit);

⌨️ 快捷键说明

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