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 + -
显示快捷键?