| #include "headers.h" |
| |
| INT |
| InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, |
| UINT addr, |
| PVOID buff, |
| INT len) |
| { |
| int retval = 0; |
| USHORT usRetries = 0 ; |
| if(psIntfAdapter == NULL ) |
| { |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Interface Adapter is NULL"); |
| return -EINVAL ; |
| } |
| |
| if(psIntfAdapter->psAdapter->device_removed == TRUE) |
| { |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed"); |
| return -ENODEV; |
| } |
| |
| if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) |
| { |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus"); |
| return -EACCES; |
| } |
| |
| if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) |
| { |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed.."); |
| return -EACCES; |
| } |
| psIntfAdapter->psAdapter->DeviceAccess = TRUE ; |
| do { |
| retval = usb_control_msg(psIntfAdapter->udev, |
| usb_rcvctrlpipe(psIntfAdapter->udev,0), |
| 0x02, |
| 0xC2, |
| (addr & 0xFFFF), |
| ((addr >> 16) & 0xFFFF), |
| buff, |
| len, |
| 5000); |
| |
| usRetries++ ; |
| if(-ENODEV == retval) |
| { |
| psIntfAdapter->psAdapter->device_removed =TRUE; |
| break; |
| } |
| |
| }while((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES ) ); |
| |
| if(retval < 0) |
| { |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval,usRetries); |
| psIntfAdapter->psAdapter->DeviceAccess = FALSE ; |
| return retval; |
| } |
| else |
| { |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval); |
| psIntfAdapter->psAdapter->DeviceAccess = FALSE ; |
| return STATUS_SUCCESS; |
| } |
| } |
| |
| INT |
| InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, |
| UINT addr, |
| PVOID buff, |
| INT len) |
| { |
| int retval = 0; |
| USHORT usRetries = 0 ; |
| |
| if(psIntfAdapter == NULL ) |
| { |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL"); |
| return -EINVAL; |
| } |
| if(psIntfAdapter->psAdapter->device_removed == TRUE) |
| { |
| |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed"); |
| return -ENODEV; |
| } |
| |
| if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) |
| { |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus..."); |
| return -EACCES; |
| } |
| |
| if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) |
| { |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed.."); |
| return -EACCES; |
| } |
| psIntfAdapter->psAdapter->DeviceAccess = TRUE ; |
| do{ |
| retval = usb_control_msg(psIntfAdapter->udev, |
| usb_sndctrlpipe(psIntfAdapter->udev,0), |
| 0x01, |
| 0x42, |
| (addr & 0xFFFF), |
| ((addr >> 16) & 0xFFFF), |
| buff, |
| len, |
| 5000); |
| |
| usRetries++ ; |
| if(-ENODEV == retval) |
| { |
| psIntfAdapter->psAdapter->device_removed = TRUE ; |
| break; |
| } |
| |
| }while((retval < 0) && ( usRetries < MAX_RDM_WRM_RETIRES)); |
| |
| if(retval < 0) |
| { |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries); |
| psIntfAdapter->psAdapter->DeviceAccess = FALSE ; |
| return retval; |
| } |
| else |
| { |
| psIntfAdapter->psAdapter->DeviceAccess = FALSE ; |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval); |
| return STATUS_SUCCESS; |
| |
| } |
| |
| } |
| |
| INT |
| BcmRDM(PVOID arg, |
| UINT addr, |
| PVOID buff, |
| INT len) |
| { |
| return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); |
| } |
| |
| INT |
| BcmWRM(PVOID arg, |
| UINT addr, |
| PVOID buff, |
| INT len) |
| { |
| return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); |
| } |
| |
| |
| |
| INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter) |
| { |
| PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter); |
| INT status = STATUS_SUCCESS ; |
| |
| /* |
| usb_clear_halt - tells device to clear endpoint halt/stall condition |
| @dev: device whose endpoint is halted |
| @pipe: endpoint "pipe" being cleared |
| @ Context: !in_interrupt () |
| |
| usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code. |
| This is used to clear halt conditions for bulk and interrupt endpoints only. |
| Control and isochronous endpoints never halts. |
| |
| Any URBs queued for such an endpoint should normally be unlinked by the driver |
| before clearing the halt condition. |
| |
| */ |
| |
| //Killing all the submitted urbs to different end points. |
| Bcm_kill_all_URBs(psIntfAdapter); |
| |
| |
| //clear the halted/stalled state for every end point |
| status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sIntrIn.int_in_pipe); |
| if(status != STATUS_SUCCESS) |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status); |
| |
| status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkIn.bulk_in_pipe); |
| if(status != STATUS_SUCCESS) |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status); |
| |
| status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkOut.bulk_out_pipe); |
| if(status != STATUS_SUCCESS) |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status); |
| |
| return status ; |
| } |
| |
| |
| VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) |
| { |
| struct urb *tempUrb = NULL; |
| UINT i; |
| |
| /** |
| * usb_kill_urb - cancel a transfer request and wait for it to finish |
| * @urb: pointer to URB describing a previously submitted request, |
| * returns nothing as it is void returned API. |
| * |
| * This routine cancels an in-progress request. It is guaranteed that |
| * upon return all completion handlers will have finished and the URB |
| * will be totally idle and available for reuse |
| |
| * This routine may not be used in an interrupt context (such as a bottom |
| * half or a completion handler), or when holding a spinlock, or in other |
| * situations where the caller can't schedule(). |
| * |
| **/ |
| |
| /* Cancel submitted Interrupt-URB's */ |
| if(psIntfAdapter->psInterruptUrb != NULL) |
| { |
| if(psIntfAdapter->psInterruptUrb->status == -EINPROGRESS) |
| usb_kill_urb(psIntfAdapter->psInterruptUrb); |
| } |
| |
| /* Cancel All submitted TX URB's */ |
| for(i = 0; i < MAXIMUM_USB_TCB; i++) |
| { |
| tempUrb = psIntfAdapter->asUsbTcb[i].urb; |
| if(tempUrb) |
| { |
| if(tempUrb->status == -EINPROGRESS) |
| usb_kill_urb(tempUrb); |
| } |
| } |
| |
| for(i = 0; i < MAXIMUM_USB_RCB; i++) |
| { |
| tempUrb = psIntfAdapter->asUsbRcb[i].urb; |
| if(tempUrb) |
| { |
| if(tempUrb->status == -EINPROGRESS) |
| usb_kill_urb(tempUrb); |
| } |
| } |
| |
| atomic_set(&psIntfAdapter->uNumTcbUsed, 0); |
| atomic_set(&psIntfAdapter->uCurrTcb, 0); |
| |
| atomic_set(&psIntfAdapter->uNumRcbUsed, 0); |
| atomic_set(&psIntfAdapter->uCurrRcb, 0); |
| } |
| |
| VOID putUsbSuspend(struct work_struct *work) |
| { |
| PS_INTERFACE_ADAPTER psIntfAdapter = NULL ; |
| struct usb_interface *intf = NULL ; |
| psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER,usbSuspendWork); |
| intf=psIntfAdapter->interface ; |
| |
| if(psIntfAdapter->bSuspended == FALSE) |
| usb_autopm_put_interface(intf); |
| |
| } |
| |