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

📄 st5481_d.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Driver for ST5481 USB ISDN modem * * Author       Frode Isaksen * Copyright    2001 by Frode Isaksen      <fisaksen@bewan.com> *              2001 by Kai Germaschewski  <kai.germaschewski@gmx.de> *  * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */#include <linux/init.h>#include <linux/usb.h>#include <linux/slab.h>#include <linux/netdevice.h>#include "st5481.h"static void ph_connect(struct st5481_adapter *adapter);static void ph_disconnect(struct st5481_adapter *adapter);static struct Fsm l1fsm;static char *strL1State[] ={	"ST_L1_F3",	"ST_L1_F4",	"ST_L1_F6",	"ST_L1_F7",	"ST_L1_F8",};static char *strL1Event[] ={	"EV_IND_DP",  	"EV_IND_1",   	"EV_IND_2",   	"EV_IND_3",   	"EV_IND_RSY", 	"EV_IND_5",   	"EV_IND_6",   	"EV_IND_7",   	"EV_IND_AP",  	"EV_IND_9",   	"EV_IND_10",  	"EV_IND_11",  	"EV_IND_AI8",	"EV_IND_AI10",	"EV_IND_AIL",	"EV_IND_DI",  	"EV_PH_ACTIVATE_REQ",	"EV_PH_DEACTIVATE_REQ",	"EV_TIMER3",};static inline void D_L1L2(struct st5481_adapter *adapter, int pr, void *arg){	struct hisax_if *ifc = (struct hisax_if *) &adapter->hisax_d_if;	ifc->l1l2(ifc, pr, arg);}static voidl1_go_f3(struct FsmInst *fi, int event, void *arg){	struct st5481_adapter *adapter = fi->userdata;	if (fi->state == ST_L1_F7)		ph_disconnect(adapter);		FsmChangeState(fi, ST_L1_F3);	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);}static voidl1_go_f6(struct FsmInst *fi, int event, void *arg){	struct st5481_adapter *adapter = fi->userdata;	if (fi->state == ST_L1_F7)		ph_disconnect(adapter);	FsmChangeState(fi, ST_L1_F6);}static voidl1_go_f7(struct FsmInst *fi, int event, void *arg){	struct st5481_adapter *adapter = fi->userdata;	FsmDelTimer(&adapter->timer, 0);	ph_connect(adapter);	FsmChangeState(fi, ST_L1_F7);	D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL);}static voidl1_go_f8(struct FsmInst *fi, int event, void *arg){	struct st5481_adapter *adapter = fi->userdata;	if (fi->state == ST_L1_F7)		ph_disconnect(adapter);	FsmChangeState(fi, ST_L1_F8);}static voidl1_timer3(struct FsmInst *fi, int event, void *arg){	struct st5481_adapter *adapter = fi->userdata;	st5481_ph_command(adapter, ST5481_CMD_DR);	FsmChangeState(fi, ST_L1_F3);	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);}static voidl1_ignore(struct FsmInst *fi, int event, void *arg){}static voidl1_activate(struct FsmInst *fi, int event, void *arg){	struct st5481_adapter *adapter = fi->userdata;	st5481_ph_command(adapter, ST5481_CMD_DR);	st5481_ph_command(adapter, ST5481_CMD_PUP);	FsmRestartTimer(&adapter->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);	st5481_ph_command(adapter, ST5481_CMD_AR8);	FsmChangeState(fi, ST_L1_F4);}static struct FsmNode L1FnList[] __initdata ={	{ST_L1_F3, EV_IND_DP,            l1_ignore},	{ST_L1_F3, EV_IND_AP,            l1_go_f6},	{ST_L1_F3, EV_IND_AI8,           l1_go_f7},	{ST_L1_F3, EV_IND_AI10,          l1_go_f7},	{ST_L1_F3, EV_PH_ACTIVATE_REQ,   l1_activate},	{ST_L1_F4, EV_TIMER3,            l1_timer3},	{ST_L1_F4, EV_IND_DP,            l1_go_f3},	{ST_L1_F4, EV_IND_AP,            l1_go_f6},	{ST_L1_F4, EV_IND_AI8,           l1_go_f7},	{ST_L1_F4, EV_IND_AI10,          l1_go_f7},	{ST_L1_F6, EV_TIMER3,            l1_timer3},	{ST_L1_F6, EV_IND_DP,            l1_go_f3},	{ST_L1_F6, EV_IND_AP,            l1_ignore},	{ST_L1_F6, EV_IND_AI8,           l1_go_f7},	{ST_L1_F6, EV_IND_AI10,          l1_go_f7},	{ST_L1_F7, EV_IND_RSY,           l1_go_f8},	{ST_L1_F7, EV_IND_DP,            l1_go_f3},	{ST_L1_F7, EV_IND_AP,            l1_go_f6},	{ST_L1_F7, EV_IND_AI8,           l1_ignore},	{ST_L1_F7, EV_IND_AI10,          l1_ignore},	{ST_L1_F7, EV_IND_RSY,           l1_go_f8},	{ST_L1_F8, EV_TIMER3,            l1_timer3},	{ST_L1_F8, EV_IND_DP,            l1_go_f3},	{ST_L1_F8, EV_IND_AP,            l1_go_f6},	{ST_L1_F8, EV_IND_AI8,           l1_go_f8},	{ST_L1_F8, EV_IND_AI10,          l1_go_f8},	{ST_L1_F8, EV_IND_RSY,           l1_ignore},};static void l1m_debug(struct FsmInst *fi, char *fmt, ...){	va_list args;	char buf[256];		va_start(args, fmt);	vsprintf(buf, fmt, args);	DBG(8, "%s", buf);	va_end(args);}/* ====================================================================== * D-Channel out *//*  D OUT state machine:  ====================  Transmit short frame (< 16 bytes of encoded data):  L1 FRAME    D_OUT_STATE           USB                  D CHANNEL  --------    -----------           ---                  ---------               FIXME -> [xx..xx]  SHORT_INIT            -> [7Exx..xxC1C27EFF]              SHORT_WAIT_DEN        <> OUT_D_COUNTER=16                                                                END_OF_SHORT          <- DEN_EVENT         -> 7Exx                                                          xxxx                                                           xxxx							  xxxx 							  xxxx							  xxxx							  C1C1 							  7EFF               WAIT_FOR_RESET_IDLE   <- D_UNDERRUN        <- (8ms)                                      IDLE                  <> Reset pipe                Transmit long frame (>= 16 bytes of encoded data):  L1 FRAME    D_OUT_STATE           USB                  D CHANNEL  --------    -----------           ---                  --------- -> [xx...xx] IDLE              WAIT_FOR_STOP         <> OUT_D_COUNTER=0              WAIT_FOR_RESET        <> Reset pipe	      STOP	      INIT_LONG_FRAME       -> [7Exx..xx]              WAIT_DEN              <> OUT_D_COUNTER=16               OUT_NORMAL            <- DEN_EVENT       -> 7Exx              END_OF_FRAME_BUSY     -> [xxxx]             xxxx               END_OF_FRAME_NOT_BUSY -> [xxxx]             xxxx				    -> [xxxx]		  xxxx 				    -> [C1C2]		  xxxx				    -> [7EFF]		  xxxx							  xxxx 							  xxxx                                                           ....							  xxxx							  C1C2							  7EFF	                 	    <- D_UNDERRUN      <- (> 8ms)                                      WAIT_FOR_STOP         <> OUT_D_COUNTER=0              WAIT_FOR_RESET        <> Reset pipe	      STOP*/          static struct Fsm dout_fsm;static char *strDoutState[] ={	"ST_DOUT_NONE",	"ST_DOUT_SHORT_INIT",	"ST_DOUT_SHORT_WAIT_DEN",	"ST_DOUT_LONG_INIT",	"ST_DOUT_LONG_WAIT_DEN",	"ST_DOUT_NORMAL",	"ST_DOUT_WAIT_FOR_UNDERRUN",        "ST_DOUT_WAIT_FOR_NOT_BUSY",	"ST_DOUT_WAIT_FOR_STOP",	"ST_DOUT_WAIT_FOR_RESET",};static char *strDoutEvent[] ={	"EV_DOUT_START_XMIT",	"EV_DOUT_COMPLETE",	"EV_DOUT_DEN",	"EV_DOUT_RESETED",	"EV_DOUT_STOPPED",	"EV_DOUT_COLL",	"EV_DOUT_UNDERRUN",};static void dout_debug(struct FsmInst *fi, char *fmt, ...){	va_list args;	char buf[256];		va_start(args, fmt);	vsprintf(buf, fmt, args);	DBG(0x2, "%s", buf);	va_end(args);}static void dout_stop_event(void *context){	struct st5481_adapter *adapter = context;	FsmEvent(&adapter->d_out.fsm, EV_DOUT_STOPPED, NULL);}/* * Start the transfer of a D channel frame. */static void usb_d_out(struct st5481_adapter *adapter, int buf_nr){	struct st5481_d_out *d_out = &adapter->d_out;	struct urb *urb;	unsigned int num_packets, packet_offset;	int len, buf_size, bytes_sent;	struct sk_buff *skb;	struct usb_iso_packet_descriptor *desc;	if (d_out->fsm.state != ST_DOUT_NORMAL)		return;	if (test_and_set_bit(buf_nr, &d_out->busy)) {		DBG(2, "ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);		return;	}	urb = d_out->urb[buf_nr];	skb = d_out->tx_skb;	buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT;		if (skb) {		len = isdnhdlc_encode(&d_out->hdlc_state,				      skb->data, skb->len, &bytes_sent,				      urb->transfer_buffer, buf_size);		skb_pull(skb,bytes_sent);	} else {		// Send flags or idle		len = isdnhdlc_encode(&d_out->hdlc_state,				      NULL, 0, &bytes_sent,				      urb->transfer_buffer, buf_size);	}		if (len < buf_size) {		FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_UNDERRUN);	}	if (skb && !skb->len) {		d_out->tx_skb = NULL;		D_L1L2(adapter, PH_DATA | CONFIRM, NULL);		dev_kfree_skb_any(skb);	}	// Prepare the URB	urb->transfer_buffer_length = len;	num_packets = 0;	packet_offset = 0;	while (packet_offset < len) {		desc = &urb->iso_frame_desc[num_packets];		desc->offset = packet_offset;		desc->length = SIZE_ISO_PACKETS_D_OUT;		if (len - packet_offset < desc->length)			desc->length = len - packet_offset;		num_packets++;		packet_offset += desc->length;	}	urb->number_of_packets = num_packets;	// Prepare the URB	urb->dev = adapter->usb_dev;	// Need to transmit the next buffer 2ms after the DEN_EVENT	urb->transfer_flags = 0;	urb->start_frame = usb_get_current_frame_number(adapter->usb_dev)+2;	DBG_ISO_PACKET(0x20,urb);	if (usb_submit_urb(urb, GFP_KERNEL) < 0) {		// There is another URB queued up		urb->transfer_flags = URB_ISO_ASAP;		SUBMIT_URB(urb, GFP_KERNEL);	}	}static void fifo_reseted(void *context){	struct st5481_adapter *adapter = context;	FsmEvent(&adapter->d_out.fsm, EV_DOUT_RESETED, NULL);}static void usb_d_out_complete(struct urb *urb, struct pt_regs *regs){	struct st5481_adapter *adapter = urb->context;	struct st5481_d_out *d_out = &adapter->d_out;	int buf_nr;		DBG(2, "");	buf_nr = get_buf_nr(d_out->urb, urb);	test_and_clear_bit(buf_nr, &d_out->busy);	if (unlikely(urb->status < 0)) {		switch (urb->status) {			case -ENOENT:			case -ESHUTDOWN:			case -ECONNRESET:				DBG(1,"urb killed status %d", urb->status);				break;			default: 

⌨️ 快捷键说明

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