hisax_hfcpci.c

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

C
1,647
字号
	f2 = get_b_tx_f2(bcs);	if (f1 != f2)		BUG();	z1 = get_b_tx_z1(bcs, f1);	z2 = get_b_tx_z2(bcs, f1);	cnt = z2 - z1;	if (cnt <= 0)		cnt += B_FIFO_SIZE;	if (tx_skb->len > cnt)		BUG();	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;	mb();	set_b_tx_z1(bcs, f1, z1);}static inline voidhfcpci_fill_b_fifo(struct hfcpci_bcs *bcs){	if (!bcs->tx_skb) {		DBG(DBG_WARN, "?");		return;	}		switch (bcs->mode) {	case L1_MODE_TRANS:		hfcpci_fill_b_fifo_trans(bcs);		break;	case L1_MODE_HDLC:		hfcpci_fill_b_fifo_hdlc(bcs);		break;	default:		DBG(DBG_WARN, "?");	}}static void hfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs);static void hfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs);static voidhfcpci_b_mode(struct hfcpci_bcs *bcs, int mode){	struct hfcpci_adapter *adapter = bcs->adapter;		DBG(DBG_B_XMIT, "B%d mode %d --> %d",	    bcs->channel + 1, bcs->mode, mode);	if (bcs->mode == mode)		return;	switch (mode) {	case L1_MODE_NULL:		if (bcs->channel == 0) {			adapter->sctrl &= ~SCTRL_B1_ENA;			adapter->sctrl_r &= ~SCTRL_B1_ENA;			adapter->fifo_en &= ~HFCPCI_FIFOEN_B1;			adapter->int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);		} else {			adapter->sctrl &= ~SCTRL_B2_ENA;			adapter->sctrl_r &= ~SCTRL_B2_ENA;			adapter->fifo_en &= ~HFCPCI_FIFOEN_B2;			adapter->int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);		}		break;	case L1_MODE_TRANS:	case L1_MODE_HDLC:		hfcpci_clear_b_rx_fifo(bcs);		hfcpci_clear_b_tx_fifo(bcs);		if (bcs->channel == 0) {			adapter->sctrl |= SCTRL_B1_ENA;			adapter->sctrl_r |= SCTRL_B1_ENA;			adapter->fifo_en |= HFCPCI_FIFOEN_B1;			adapter->int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);			if (mode == L1_MODE_TRANS)				adapter->ctmt |= 1;			else				adapter->ctmt &= ~1;		} else {			adapter->sctrl |= SCTRL_B2_ENA;			adapter->sctrl_r |= SCTRL_B2_ENA;			adapter->fifo_en |= HFCPCI_FIFOEN_B2;			adapter->int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);			if (mode == L1_MODE_TRANS)				adapter->ctmt |= 2;			else				adapter->ctmt &= ~2;		}		break;	}	hfcpci_writeb(adapter, adapter->int_m1,  HFCPCI_INT_M1);	hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);	hfcpci_writeb(adapter, adapter->sctrl,   HFCPCI_SCTRL);	hfcpci_writeb(adapter, adapter->sctrl_r, HFCPCI_SCTRL_R);	hfcpci_writeb(adapter, adapter->ctmt,    HFCPCI_CTMT);	hfcpci_writeb(adapter, adapter->conn,    HFCPCI_CONNECT);	bcs->mode = mode;}// ----------------------------------------------------------------------// Layer 1 state machinestatic struct Fsm l1fsm;enum {	ST_L1_F0,	ST_L1_F2,	ST_L1_F3,	ST_L1_F4,	ST_L1_F5,	ST_L1_F6,	ST_L1_F7,	ST_L1_F8,};#define L1_STATE_COUNT (ST_L1_F8+1)static char *strL1State[] ={	"ST_L1_F0",	"ST_L1_F2",	"ST_L1_F3",	"ST_L1_F4",	"ST_L1_F5",	"ST_L1_F6",	"ST_L1_F7",	"ST_L1_F8",};enum {	EV_PH_F0,	EV_PH_1,	EV_PH_F2,	EV_PH_F3,	EV_PH_F4,	EV_PH_F5,	EV_PH_F6,	EV_PH_F7,	EV_PH_F8,	EV_PH_ACTIVATE_REQ,	EV_PH_DEACTIVATE_REQ,	EV_TIMER3,};#define L1_EVENT_COUNT (EV_TIMER3 + 1)static char *strL1Event[] ={	"EV_PH_F0",	"EV_PH_1",	"EV_PH_F2",	"EV_PH_F3",	"EV_PH_F4",	"EV_PH_F5",	"EV_PH_F6",	"EV_PH_F7",	"EV_PH_F8",	"EV_PH_ACTIVATE_REQ",	"EV_PH_DEACTIVATE_REQ",	"EV_TIMER3",};static void l1_ignore(struct FsmInst *fi, int event, void *arg){}static void l1_go_f3(struct FsmInst *fi, int event, void *arg){	FsmChangeState(fi, ST_L1_F3);}static void l1_go_f3_deact_ind(struct FsmInst *fi, int event, void *arg){	struct hfcpci_adapter *adapter = fi->userdata;	FsmChangeState(fi, ST_L1_F3);	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);}static void l1_go_f4(struct FsmInst *fi, int event, void *arg){	FsmChangeState(fi, ST_L1_F3);}static void l1_go_f5(struct FsmInst *fi, int event, void *arg){	FsmChangeState(fi, ST_L1_F3);}static void l1_go_f6(struct FsmInst *fi, int event, void *arg){	FsmChangeState(fi, ST_L1_F6);}static void l1_go_f6_deact_ind(struct FsmInst *fi, int event, void *arg){	struct hfcpci_adapter *adapter = fi->userdata;	FsmChangeState(fi, ST_L1_F6);	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);}static void l1_go_f7(struct FsmInst *fi, int event, void *arg){	FsmChangeState(fi, ST_L1_F7);}static void l1_go_f7_act_ind(struct FsmInst *fi, int event, void *arg){	struct hfcpci_adapter *adapter = fi->userdata;	FsmChangeState(fi, ST_L1_F7);	D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL);}static void l1_go_f8(struct FsmInst *fi, int event, void *arg){	FsmChangeState(fi, ST_L1_F8);}static void l1_go_f8_deact_ind(struct FsmInst *fi, int event, void *arg){	struct hfcpci_adapter *adapter = fi->userdata;	FsmChangeState(fi, ST_L1_F8);	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);}static void l1_act_req(struct FsmInst *fi, int event, void *arg){	struct hfcpci_adapter *adapter = fi->userdata;	hfcpci_writeb(adapter, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION, HFCPCI_STATES);}static struct FsmNode L1FnList[] __initdata ={	{ST_L1_F2,            EV_PH_F3,             l1_go_f3},	{ST_L1_F2,            EV_PH_F6,             l1_go_f6},	{ST_L1_F2,            EV_PH_F7,             l1_go_f7_act_ind},	{ST_L1_F3,            EV_PH_F3,             l1_ignore},	{ST_L1_F3,            EV_PH_F4,             l1_go_f4},	{ST_L1_F3,            EV_PH_F5,             l1_go_f5},	{ST_L1_F3,            EV_PH_F6,             l1_go_f6},	{ST_L1_F3,            EV_PH_F7,             l1_go_f7_act_ind},	{ST_L1_F3,            EV_PH_ACTIVATE_REQ,   l1_act_req},	{ST_L1_F4,            EV_PH_F7,             l1_ignore},	{ST_L1_F4,            EV_PH_F3,             l1_go_f3},	{ST_L1_F4,            EV_PH_F5,             l1_go_f5},	{ST_L1_F4,            EV_PH_F6,             l1_go_f6},	{ST_L1_F4,            EV_PH_F7,             l1_go_f7},	{ST_L1_F5,            EV_PH_F7,             l1_ignore},	{ST_L1_F5,            EV_PH_F3,             l1_go_f3},	{ST_L1_F5,            EV_PH_F6,             l1_go_f6},	{ST_L1_F5,            EV_PH_F7,             l1_go_f7},	{ST_L1_F6,            EV_PH_F7,             l1_ignore},	{ST_L1_F6,            EV_PH_F3,             l1_go_f3},	{ST_L1_F6,            EV_PH_F7,             l1_go_f7_act_ind},	{ST_L1_F6,            EV_PH_F8,             l1_go_f8},	{ST_L1_F7,            EV_PH_F7,             l1_ignore},	{ST_L1_F7,            EV_PH_F3,             l1_go_f3_deact_ind},	{ST_L1_F7,            EV_PH_F6,             l1_go_f6_deact_ind},	{ST_L1_F7,            EV_PH_F8,             l1_go_f8_deact_ind},	{ST_L1_F8,            EV_PH_F7,             l1_ignore},	{ST_L1_F8,            EV_PH_F3,             l1_go_f3},	{ST_L1_F8,            EV_PH_F6,             l1_go_f6},	{ST_L1_F8,            EV_PH_F7,             l1_go_f7_act_ind},};static void l1m_debug(struct FsmInst *fi, char *fmt, ...){	va_list args;	char buf[256];		va_start(args, fmt);	vsprintf(buf, fmt, args);	DBG(DBG_L1M, "%s", buf);	va_end(args);}// ----------------------------------------------------------------------// clear FIFOsstatic voidhfcpci_clear_d_rx_fifo(struct hfcpci_adapter *adapter){	u8 fifo_state;	DBG(DBG_D_RECV, "");	fifo_state = adapter->fifo_en & HFCPCI_FIFOEN_DRX;	if (fifo_state) { // enabled		// XXX locking	        adapter->fifo_en &= ~fifo_state;		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);	}		adapter->last_fcnt = 0;	set_d_rx_z1(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1);	set_d_rx_z2(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1);	mb();	set_d_rx_f1(adapter, MAX_D_FRAMES - 1);	set_d_rx_f2(adapter, MAX_D_FRAMES - 1);	mb();		if (fifo_state) {	        adapter->fifo_en |= fifo_state;		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);	}}   static voidhfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs){	struct hfcpci_adapter *adapter = bcs->adapter;	int nr = bcs->channel;	u8 fifo_state;	DBG(DBG_B_RECV, "");	fifo_state = adapter->fifo_en & 		(nr ? HFCPCI_FIFOEN_B2RX : HFCPCI_FIFOEN_B1RX);	if (fifo_state) { // enabled	        adapter->fifo_en &= ~fifo_state;		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);	}		bcs->last_fcnt = 0;	set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);	set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);	mb();	set_b_rx_f1(bcs, MAX_B_FRAMES - 1);	set_b_rx_f2(bcs, MAX_B_FRAMES - 1);	mb();		if (fifo_state) {	        adapter->fifo_en |= fifo_state;		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);	}}   // XXX clear d_tx_fifo?static voidhfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs){	struct hfcpci_adapter *adapter = bcs->adapter;	int nr = bcs->channel;	u8 fifo_state;	fifo_state = adapter->fifo_en & 		(nr ? HFCPCI_FIFOEN_B2TX : HFCPCI_FIFOEN_B1TX);	if (fifo_state) { // enabled	        adapter->fifo_en &= ~fifo_state;		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);	}		bcs->last_fcnt = 0;	set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);	set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);	mb();	set_b_rx_f1(bcs, MAX_B_FRAMES - 1);	set_b_rx_f2(bcs, MAX_B_FRAMES - 1);	mb();		if (fifo_state) {	        adapter->fifo_en |= fifo_state;		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);	}}   // ----------------------------------------------------------------------// receive messages from upper layersstatic voidhfcpci_d_l2l1(struct hisax_if *ifc, int pr, void *arg){	struct hfcpci_adapter *adapter = ifc->priv;	struct sk_buff *skb = arg;	DBG(DBG_PR, "pr %#x", pr);	switch (pr) {	case PH_ACTIVATE | REQUEST:		FsmEvent(&adapter->l1m, EV_PH_ACTIVATE_REQ, NULL);		break;	case PH_DEACTIVATE | REQUEST:		FsmEvent(&adapter->l1m, EV_PH_DEACTIVATE_REQ, NULL);		break;	case PH_DATA | REQUEST:		DBG(DBG_PR, "PH_DATA REQUEST len %d", skb->len);		DBG_SKB(DBG_D_XMIT, skb);		if (adapter->l1m.state != ST_L1_F7) {			DBG(DBG_WARN, "L1 wrong state %d", adapter->l1m.state);			break;		}		if (adapter->tx_skb)			BUG();		adapter->tx_skb = skb;		hfcpci_fill_d_fifo(adapter);		break;	}}static voidhfcpci_b_l2l1(struct hisax_if *ifc, int pr, void *arg){	struct hfcpci_bcs *bcs = ifc->priv;	struct sk_buff *skb = arg;	int mode;	DBG(DBG_PR, "pr %#x", pr);	switch (pr) {	case PH_DATA | REQUEST:		if (bcs->tx_skb)			BUG();				bcs->tx_skb = skb;		DBG_SKB(DBG_B_XMIT, skb);		hfcpci_fill_b_fifo(bcs);		break;	case PH_ACTIVATE | REQUEST:		mode = (int) arg;		DBG(DBG_PR,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);		hfcpci_b_mode(bcs, mode);		B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);		break;	case PH_DEACTIVATE | REQUEST:		DBG(DBG_PR,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);		hfcpci_b_mode(bcs, L1_MODE_NULL);		B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);		break;	}}// ----------------------------------------------------------------------// receive IRQstatic inline voidhfcpci_d_recv_irq(struct hfcpci_adapter *adapter){	struct sk_buff *skb;	char *fifo_adr = adapter->fifo + 0x4000;	char *p;	int cnt, fcnt;	int loop = 5;	u8 f1, f2;	u16 z1, z2;	while (loop-- > 0) {		f1 = get_d_rx_f1(adapter);		f2 = get_d_rx_f2(adapter);		DBG(DBG_D_RECV, "f1 %#x f2 %#x", f1, f2);				fcnt = f1 - f2;		if (fcnt < 0)			fcnt += 16;		if (!fcnt)			return;				if (fcnt < adapter->last_fcnt)			/* overrun */			hfcpci_clear_d_rx_fifo(adapter);			// XXX init last_fcnt		z1 = get_d_rx_z1(adapter, f2);		z2 = get_d_rx_z2(adapter, f2);		DBG(DBG_D_RECV, "z1 %#x z2 %#x", z1, z2);		cnt = z1 - z2;		if (cnt < 0)			cnt += D_FIFO_SIZE;		cnt++;				if (cnt < 4) {			DBG(DBG_WARN, "frame too short");			goto next;		}		if (fifo_adr[z1] != 0) {			DBG(DBG_WARN, "CRC error");			goto next;		}		cnt -= 3;		skb = dev_alloc_skb(cnt);		if (!skb) {			DBG(DBG_WARN, "no mem");			goto next;		}		p = skb_put(skb, cnt);		if (z2 + cnt <= D_FIFO_END) {			memcpy(p, fifo_adr + z2, cnt);		} else {			memcpy(p, fifo_adr + z2, D_FIFO_END - z2);			memcpy(p + (D_FIFO_END - z2), fifo_adr + D_FIFO_START,			       cnt - (D_FIFO_END - z2));		}		DBG_SKB(DBG_D_RECV, skb);		D_L1L2(adapter, PH_DATA | INDICATION, skb);		next:		if (++z1 >= D_FIFO_END)			z1 -= D_FIFO_START;		f2 = (f2 + 1) & (MAX_D_FRAMES - 1);		mb();		set_d_rx_z2(adapter, f2, z1);		mb();		set_d_rx_f2(adapter, f2);				adapter->last_fcnt = fcnt - 1;	}}

⌨️ 快捷键说明

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