hfa384x_usb.c

来自「Linux的无线局域网方案是一个Linux设备驱动程序和子系统 一揽子方案的用」· C语言 代码 · 共 2,513 行 · 第 1/5 页

C
2,513
字号
/*----------------------------------------------------------------* hfa384x_corereset** Perform a reset of the hfa38xx MAC core.  We assume that the hw * structure is in its "created" state.  That is, it is initialized* with proper values.  Note that if a reset is done after the * device has been active for awhile, the caller might have to clean * up some leftover cruft in the hw structure.** Arguments:*	hw		device structure*	holdtime	how long (in ms) to hold the reset*	settletime	how long (in ms) to wait after releasing*			the reset** Returns: *	nothing** Side effects:** Call context:*	process ----------------------------------------------------------------*/int hfa384x_corereset( hfa384x_t *hw, int holdtime, int settletime){	struct usb_device	*parent = hw->usb->parent;	int			i;	int 			result = 0;	int			port = -1;#define P2_USB_RT_PORT		(USB_TYPE_CLASS | USB_RECIP_OTHER)#define P2_USB_FEAT_RESET	4#define P2_USB_FEAT_C_RESET	20	DBFENTER;	/* Find the hub port */	for ( i = 0; i < parent->maxchild; i++) {		if (parent->children[i] == hw->usb) {			port = i;			break;		}	}	if (port < 0) return -ENOENT;	/* Set and clear the reset */	usb_control_msg(parent, usb_sndctrlpipe(parent, 0), 		USB_REQ_SET_FEATURE, P2_USB_RT_PORT, P2_USB_FEAT_RESET, 		port+1, NULL, 0, 1*HZ);	wait_ms(holdtime);	usb_control_msg(parent, usb_sndctrlpipe(parent, 0), 		USB_REQ_CLEAR_FEATURE, P2_USB_RT_PORT, P2_USB_FEAT_C_RESET, 		port+1, NULL, 0, 1*HZ);	wait_ms(settletime);	/* Set the device address */	result=usb_set_address(hw->usb);	if (result < 0) {		WLAN_LOG_ERROR1("reset_usbdev: Dev not accepting address, "			"result=%d\n", result);		clear_bit(hw->usb->devnum, &hw->usb->bus->devmap.devicemap);		hw->usb->devnum = -1;		goto done;	}	/* Let the address settle */	wait_ms(20);	/* Assume we're reusing the original descriptor data */		/* Set the configuration. */	WLAN_LOG_DEBUG1(3, "Setting Configuration %d\n", 		hw->usb->config[0].bConfigurationValue);	result=usb_set_configuration(hw->usb, hw->usb->config[0].bConfigurationValue);	if ( result ) {		WLAN_LOG_ERROR1("usb_set_configuration() failed, result=%d.\n",				result);		goto done;	}		/* Let the configuration settle */	wait_ms(20);done:		DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_docmd** Constructs a command CTLX and submits it.** NOTE: Any changes to the 'post-submit' code in this function *       need to be carried over to hfa384x_cbcmd() since the handling*       is virtually identical.** Arguments:*	hw		device structure*	wait		1=wait for completion, 0=async*	cmd		Command in host order*	parm0		Parameter0 in host order*	parm1		Parameter1 in host order*	parm2		Parameter2 in host order*	usercb		user callback for async calls, NULL for wait==1 calls*	usercb_data	user supplied data pointer for async calls, NULL*			for wait==1 calls** Returns: *	0		success*	-EIO		CTLX failure*	-ERESTARTSYS	Awakened on signal*	>0		command indicated error, Status and Resp0-2 are*			in hw structure.** Side effects:*	** Call context:*	process ----------------------------------------------------------------*/int hfa384x_docmd( 	hfa384x_t *hw, 	UINT	wait,	UINT16	p2cmd, 	UINT16	parm0, 	UINT16	parm1, 	UINT16	parm2,	ctlx_usercb_t	usercb,	void	*usercb_data){	int			result = 0;	hfa384x_usbctlx_t	*ctlx;		DBFENTER;	ctlx = kmalloc(sizeof(*ctlx), GFP_ATOMIC);	if ( ctlx == NULL ) {		result = -ENOMEM;		goto done;	}	memset(ctlx, 0, sizeof(*ctlx));	ctlx->state = HFA384x_USBCTLX_START;	/* Initialize the command */	ctlx->outbuf.cmdreq.type = 	host2hfa384x_16(HFA384x_USB_CMDREQ);	ctlx->outbuf.cmdreq.cmd =	host2hfa384x_16(p2cmd);	ctlx->outbuf.cmdreq.parm0 =	host2hfa384x_16(parm0);	ctlx->outbuf.cmdreq.parm1 =	host2hfa384x_16(parm1);	ctlx->outbuf.cmdreq.parm2 =	host2hfa384x_16(parm2);	hw->lastcmd = host2hfa384x_16(p2cmd);	WLAN_LOG_DEBUG4(4, "cmdreq: cmd=0x%04x "		"parm0=0x%04x parm1=0x%04x parm2=0x%04x\n",		p2cmd,		parm0,		parm1,		parm2);	/* Fill the out packet */	FILL_BULK_URB( &(ctlx->outurb), hw->usb,		usb_sndbulkpipe(hw->usb, 2),		&(ctlx->outbuf), ROUNDUP64(sizeof(ctlx->outbuf.cmdreq)),		hfa384x_usbout_callback, hw->usbcontext);	ctlx->outurb.transfer_flags |= USB_ASYNC_UNLINK;	if ( wait ) {		hfa384x_usbctlx_submit_wait(hw, ctlx);	} else {		hfa384x_usbctlx_submit_async(hw, ctlx, usercb, usercb_data);		goto done;	}	/* All of the following is skipped for async calls */	/* On reawakening, check the ctlx status */	switch(ctlx->state) { 	case HFA384x_USBCTLX_COMPLETE:		result = hfa384x2host_16(ctlx->inbuf.cmdresp.status);		result &= HFA384x_STATUS_RESULT;		hw->status = hfa384x2host_16(ctlx->inbuf.cmdresp.status);		hw->resp0 = hfa384x2host_16(ctlx->inbuf.cmdresp.resp0);		hw->resp1 = hfa384x2host_16(ctlx->inbuf.cmdresp.resp1);		hw->resp2 = hfa384x2host_16(ctlx->inbuf.cmdresp.resp2);		WLAN_LOG_DEBUG4(4, "cmdresp:status=0x%04x "			"resp0=0x%04x resp1=0x%04x resp2=0x%04x\n",			hw->status,			hw->resp0,			hw->resp1,			hw->resp2);		break;	case HFA384x_USBCTLX_REQSUBMIT_FAIL:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=REQSUBMIT_FAIL\n");		result = -EIO;		break;	case HFA384x_USBCTLX_REQ_TIMEOUT:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=REQ_TIMEOUT\n");		result = -EIO;		break;	case HFA384x_USBCTLX_REQ_FAILED:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=REQ_FAILED\n");		result = -EIO;		break;	case HFA384x_USBCTLX_RESP_TIMEOUT:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=RESP_TIMEOUT\n");		result = -EIO;		break;	default:		/* The ctlx is still running and probably still in the queue 		 * We were probably awakened by a signal.  Return an error  		 * and DO NOT free the ctlx.  Let the ctlx finish and it will		 * just be leaked.  At least we won't crash that way.		 * TODO: we need a ctlx_cancel function 		 */		result = -ERESTARTSYS;		goto done;		break;	}	kfree(ctlx);done:	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_dorrid** Constructs a read rid CTLX and issues it.** NOTE: Any changes to the 'post-submit' code in this function *       need to be carried over to hfa384x_cbrrid() since the handling*       is virtually identical.** Arguments:*	hw		device structure*	wait		1=wait for completion, 0=async*	rid		Read RID number (host order)*	riddata		Caller supplied buffer that MAC formatted RID.data *			record will be written to for wait==1 calls. Should*			be NULL for wait==0 calls.*	riddatalen	Buffer length for wait==1 calls. Zero for wait==0 calls.*	usercb		user callback for async calls, NULL for wait==1 calls*	usercb_data	user supplied data pointer for async calls, NULL*			for wait==1 calls** Returns: *	0		success*	-EIO		CTLX failure*	-ERESTARTSYS	Awakened on signal*	-ENODATA	riddatalen != macdatalen*	>0		command indicated error, Status and Resp0-2 are*			in hw structure.** Side effects:*	* Call context:*	interrupt (wait==0)*	process (wait==0 || wait==1)----------------------------------------------------------------*/inthfa384x_dorrid(	hfa384x_t *hw, 	UINT	wait,	UINT16	rid,	void	*riddata,	UINT	riddatalen,	ctlx_usercb_t usercb,	void	*usercb_data){	int			result = 0;	hfa384x_usbctlx_t	*ctlx;	UINT			maclen;		DBFENTER;	ctlx = kmalloc(sizeof(*ctlx), GFP_ATOMIC);	if ( ctlx == NULL ) {		result = -ENOMEM;		goto done;	}	memset(ctlx, 0, sizeof(*ctlx));	ctlx->state = HFA384x_USBCTLX_START;	/* Initialize the command */	ctlx->outbuf.rridreq.type =   host2hfa384x_16(HFA384x_USB_RRIDREQ);	ctlx->outbuf.rridreq.frmlen = 		host2hfa384x_16(sizeof(ctlx->outbuf.rridreq.rid));	ctlx->outbuf.rridreq.rid =    host2hfa384x_16(rid);	/* Fill the out packet */	FILL_BULK_URB( &(ctlx->outurb), hw->usb,		usb_sndbulkpipe(hw->usb, 2),		&(ctlx->outbuf), ROUNDUP64(sizeof(ctlx->outbuf.rridreq)),		hfa384x_usbout_callback, hw->usbcontext);	ctlx->outurb.transfer_flags |= USB_ASYNC_UNLINK;	/* Submit the CTLX */	if ( wait ) {		hfa384x_usbctlx_submit_wait(hw, ctlx);	} else {		hfa384x_usbctlx_submit_async(hw, ctlx, usercb, usercb_data);		goto done;	}	/* All of the following is skipped for async calls */	/* On reawakening, check the ctlx status */	switch(ctlx->state) { 	case HFA384x_USBCTLX_COMPLETE:		/* The results are in ctlx->outbuf */		/* Validate the length, note body len calculation in bytes */		maclen = ((hfa384x2host_16(ctlx->inbuf.rridresp.frmlen)-1)*2);		if ( maclen != riddatalen ) {  			WLAN_LOG_WARNING3(__FUNCTION__			": RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n",			rid, riddatalen, maclen);			result = -ENODATA;			break;		}		memcpy( riddata, ctlx->inbuf.rridresp.data, riddatalen);		result = 0;		break;	case HFA384x_USBCTLX_REQSUBMIT_FAIL:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=REQSUBMIT_FAIL\n");		result = -EIO;		break;	case HFA384x_USBCTLX_REQ_TIMEOUT:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=REQ_TIMEOUT\n");		result = -EIO;		break;	case HFA384x_USBCTLX_REQ_FAILED:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=REQ_FAILED\n");		result = -EIO;		break;	case HFA384x_USBCTLX_RESP_TIMEOUT:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=RESP_TIMEOUT\n");		result = -EIO;		break;	default:		/* The ctlx is still running and probably still in the queue 		 * We were probably awakened by a signal.  Return an error  		 * and DO NOT free the ctlx.  Let the ctlx finish and it will		 * just be leaked.  At least we won't crash that way.		 * TODO: we need a ctlx_cancel function 		 */		result = -ERESTARTSYS;		goto done;		break;	}	kfree(ctlx);done:	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_dowrid** Constructs a write rid CTLX and issues it.** NOTE: Any changes to the 'post-submit' code in this function *       need to be carried over to hfa384x_cbwrid() since the handling*       is virtually identical.** Arguments:*	hw		device structure*	wait		1=wait for completion, 0=async*	rid		RID code*	riddata		Data portion of RID formatted for MAC*	riddatalen	Length of the data portion in bytes*	usercb		user callback for async calls, NULL for wait==1 calls*	usercb_data	user supplied data pointer for async calls, NULL** Returns: *	0		success*	-ETIMEDOUT	timed out waiting for register ready or*			command completion*	>0		command indicated error, Status and Resp0-2 are*			in hw structure.** Side effects:*	* Call context:*	interrupt (wait==0)*	process (wait==0 || wait==1)----------------------------------------------------------------*/inthfa384x_dowrid(	hfa384x_t *hw, 	UINT	wait,	UINT16	rid,	void	*riddata,	UINT	riddatalen,	ctlx_usercb_t usercb,	void	*usercb_data){	int			result = 0;	hfa384x_usbctlx_t	*ctlx;		DBFENTER;	ctlx = kmalloc(sizeof(*ctlx), GFP_ATOMIC);	if ( ctlx == NULL ) {		result = -ENOMEM;		goto done;	}	memset(ctlx, 0, sizeof(*ctlx));	ctlx->state = HFA384x_USBCTLX_START;	/* Initialize the command */	ctlx->outbuf.wridreq.type =   host2hfa384x_16(HFA384x_USB_WRIDREQ);	ctlx->outbuf.wridreq.frmlen = host2hfa384x_16(					sizeof(ctlx->outbuf.rridreq.rid) + 					riddatalen);	ctlx->outbuf.wridreq.rid =    host2hfa384x_16(rid);	memcpy(ctlx->outbuf.wridreq.data, riddata, riddatalen);	/* Fill the out packet */	FILL_BULK_URB( &(ctlx->outurb), hw->usb,		usb_sndbulkpipe(hw->usb, 2),		&(ctlx->outbuf), 		ROUNDUP64( sizeof(ctlx->outbuf.wridreq.type) +			sizeof(ctlx->outbuf.wridreq.frmlen) +			sizeof(ctlx->outbuf.wridreq.rid) +			riddatalen),		hfa384x_usbout_callback, 		hw->usbcontext);	ctlx->outurb.transfer_flags |= USB_ASYNC_UNLINK;	/* Submit the CTLX */	if ( wait ) {		hfa384x_usbctlx_submit_wait(hw, ctlx);	} else {		hfa384x_usbctlx_submit_async(hw, ctlx, usercb, usercb_data);		goto done;	}	/* All of the following is skipped for async calls */	/* On reawakening, check the ctlx status */	switch(ctlx->state) { 	case HFA384x_USBCTLX_COMPLETE:		result = hfa384x2host_16(ctlx->inbuf.wridresp.status);		result &= HFA384x_STATUS_RESULT;		hw->status = hfa384x2host_16(ctlx->inbuf.wridresp.status);		hw->resp0 = hfa384x2host_16(ctlx->inbuf.wridresp.resp0);		hw->resp1 = hfa384x2host_16(ctlx->inbuf.wridresp.resp1);		hw->resp2 = hfa384x2host_16(ctlx->inbuf.wridresp.resp2);		break;	case HFA384x_USBCTLX_REQSUBMIT_FAIL:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=REQSUBMIT_FAIL\n");		result = -EIO;		break;	case HFA384x_USBCTLX_REQ_TIMEOUT:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=REQ_TIMEOUT\n");		result = -EIO;		break;	case HFA384x_USBCTLX_REQ_FAILED:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=REQ_FAILED\n");		result = -EIO;		break;	case HFA384x_USBCTLX_RESP_TIMEOUT:		WLAN_LOG_WARNING0(__FUNCTION__":ctlx failure=RESP_TIMEOUT\n");		result = -EIO;		break;	default:		/* The ctlx is still running and probably still in the queue 		 * We were probably awakened by a signal.  Return an error  		 * and DO NOT free the ctlx.  Let the ctlx finish and it will		 * just be leaked.  At least we won't crash that way.		 * TODO: we need a ctlx_cancel function 		 */		result = -ERESTARTSYS;		goto done;		break;	}	kfree(ctlx);done:	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_dormem** Constructs a readmem CTLX and issues it.** NOTE: Any changes to the 'post-submit' code in this function *       need to be carried over to hfa384x_cbrmem() since the handling*       is virtually identical.** Arguments:*	hw		device structure*	wait		1=wait for completion, 0=async*	page		MAC address space page (CMD format)*	offset		MAC address space offset*	data		Ptr to data buffer to receive read*	len		Length of the data to read (max == 2048)*	usercb		user callback for async calls, NULL for wait==1 calls*	usercb_data	user supplied data pointer for async calls, NULL*

⌨️ 快捷键说明

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