📄 usbehcdtransfermanagement.c
字号:
{ uSMask <<= uShiftCount; break; } else { uTempMask >>= 1; } uShiftCount++; } /* Update the start split mask */ USB_EHCD_SET_BITFIELD(uBusIndex, QH, pQH->uEndPointCapabilities, uSMask, ENDPOINT_CAPABILITIES_UFRAME_S); /* Update the complete split mask */ USB_EHCD_SET_BITFIELD(uBusIndex, QH, pQH->uEndPointCapabilities, (uUFrameMask & ~uSMask), ENDPOINT_CAPABILITIES_UFRAME_C); } } /* Device is a high speed device */ else { /* If it is a control or bulk pipe, populate the maximum NAK rate */ if ((USBHST_CONTROL_TRANSFER == pHCDPipe->uEndpointType) || (USBHST_BULK_TRANSFER == pHCDPipe->uEndpointType)) { USB_EHCD_SET_BITFIELD(uBusIndex, QH, pQH->uEndPointCharacteristics, pEndpointDesc->bInterval, ENDPOINT_CHARACTERISTICS_RL); } /* * It is a high speed interrupt transfer, update the * mult field(the maximum number of transactions in a microframe */ else { /* * If the endpoint descriptor's mult field is 0, the number of * transactions in a microframe is 1. Because of this, * 1 is added to the number of transactions field. */ USB_EHCD_SET_BITFIELD(uBusIndex, QH, pQH->uEndPointCapabilities, ((((pEndpointDesc->wMaxPacketSize) & USB_EHCD_ENDPOINT_NUMBER_OF_TRANSACTIONS_MASK) >> 11)+ 1), ENDPOINT_CAPABILITIES_MULT ); /* Update the mask value in the QH */ USB_EHCD_SET_BITFIELD(uBusIndex, QH, pQH->uEndPointCapabilities, uUFrameMask, ENDPOINT_CAPABILITIES_UFRAME_S ); }/* End of else */ }/* End of else */ /* Populate the fields of the QH - End */ /* Exclusively access the list */ OS_WAIT_FOR_EVENT(pHCDData->RequestSynchEventID, OS_WAIT_INFINITE); /* Link the Queue head in the list - start */ /* If it is the interrupt endpoint, link it to the periodic schedule */ if (USBHST_INTERRUPT_TRANSFER == pHCDPipe->uEndpointType) { USB_EHCD_ADD_TO_HC_INTERRUPT_SCHEDULE(pHCDData, uListIndex, pQH); } /* * If it is a control or bulk endpoint, * link it to the asynchronous schedule. */ else { USB_EHCD_ADD_TO_HC_ASYNCH_SCHEDULE(pHCDData, pQH); } /* Release the exclusive list access */ OS_RELEASE_EVENT(pHCDData->RequestSynchEventID); /* Link the Queue head in the list - End */ OS_LOG_MESSAGE_LOW(EHCD,"usbEhcdCreatePipe - Exit\n",0,0,0,0); return USBHST_SUCCESS; } /* End of function usbEhcdCreatePipe() *//***************************************************************************** usbEhcdDeletePipe - deletes a pipe created already.** This function is used to delete a pipe specific to an* endpoint.** RETURNS: * USBHST_SUCCESS - Returned if the pipe was deleted successfully* USBHST_INVALID_PARAMETER - Returned if the parameters are* not valid.* ERRNO:* None.** \NOMANUAL*/USBHST_STATUS usbEhcdDeletePipe ( UINT8 uBusIndex, /* Index of the host controller */ UINT32 uPipeHandle /* Handle of the pipe to be deleted */ ) { /* To hold the status of the request */ USBHST_STATUS Status = USBHST_FAILURE; /* To hold the pointer to the EHCD maintained pipe data structure */ pUSB_EHCD_PIPE pHCDPipe = NULL; /* Pointer to the HCD specific data structure */ pUSB_EHCD_DATA pHCDData = NULL; PUCHAR pQHTemp = NULL; /* Temporary queue head pointer */ /* WindView Instrumentation */ USB_HCD_LOG_EVENT( USB_EHCI_WV_TRANSFER, "usbEhcdDeletePipe() starts", USB_EHCD_WV_FILTER); OS_LOG_MESSAGE_LOW(EHCD,"usbEhcdDeletePipe - Entry\n",0,0,0,0); /* Check the validity of the parameters */ if ((g_EHCDControllerCount <= uBusIndex) || (0 == uPipeHandle)) { OS_LOG_MESSAGE_HIGH(EHCD,"usbEhcdDeletePipe - parameters are not valid\n",0,0,0,0); return USBHST_INVALID_PARAMETER; } /* Extract the global data structure */ pHCDData = g_pEHCDData[uBusIndex]; /* Assert if the global pointer is not valid */ OS_ASSERT(NULL != pHCDData); /* Extract the USB_EHCD_PIPE data structure */ pHCDPipe = (pUSB_EHCD_PIPE)uPipeHandle; /* Check if the request is for the Root hub and route it */ if ((pHCDData->RHData.pInterruptPipe == pHCDPipe) || (pHCDData->RHData.pControlPipe == pHCDPipe)) { Status = usbEhcdRHDeletePipe(pHCDData, uPipeHandle); return Status; } /* Check if the endpoint type is valid */ if ((USBHST_CONTROL_TRANSFER != pHCDPipe->uEndpointType) && (USBHST_BULK_TRANSFER != pHCDPipe->uEndpointType) && (USBHST_INTERRUPT_TRANSFER != pHCDPipe->uEndpointType) && (USBHST_ISOCHRONOUS_TRANSFER != pHCDPipe->uEndpointType)) { OS_LOG_MESSAGE_HIGH(EHCD,"EHCD_CreatePipe - Invalid endpoint type\n",0,0,0,0); return USBHST_INVALID_PARAMETER; } /* Exclusively access the list */ OS_WAIT_FOR_EVENT(pHCDData->RequestSynchEventID, OS_WAIT_INFINITE); /* Mark the endpoint for deletion */ pHCDPipe->PipeDeletedFlag = TRUE; /* Check if it is a non-periodic endpoint */ if ((USBHST_CONTROL_TRANSFER == pHCDPipe->uEndpointType) || (USBHST_BULK_TRANSFER == pHCDPipe->uEndpointType)) { /* To hold the pointer to the EHCD maintained pipe data structure */ pUSB_EHCD_PIPE pHCDTempPipe = NULL; /* Search the asychronous list and update the next pointers */ for (pHCDTempPipe = pHCDData->pDefaultPipe; (pHCDPipe != pHCDTempPipe->pNext) && (pHCDData->pDefaultPipe != pHCDTempPipe->pNext); pHCDTempPipe = pHCDTempPipe->pNext); /* Deletion of the default pipe is not through this function. So * the pHCDPipe can never be the same as pHCDData->pDefaultPipe */ /* Update the HCD maintained link pointers */ pHCDTempPipe->pNext = pHCDPipe->pNext; /* If this QH forms the tail, update the tail element */ if (pHCDData->pAsynchTailPipe == pHCDPipe) { pHCDData->pAsynchTailPipe = pHCDTempPipe; } /* Disable the asynchronous schedule */ USB_EHCD_CLR_BIT(pHCDData, USBCMD, ASYNCH_SCHEDULE_ENABLE); /* * If only the asynch schedule enable bit and status bit are * cleared, the schedule can be termed to be disabled. * Wait till both of the bits are cleared. */ while ((USB_EHCD_GET_FIELD(pHCDData, USBCMD, ASYNCH_SCHEDULE_ENABLE) != 0) || (USB_EHCD_GET_FIELD(pHCDData, USBSTS, ASYCHRONOUS_SCHEDULE_STATUS) !=0)) OS_DELAY_MS(1); /* * Update the HC maintained next pointers. This has to be done after * disabling the list. If the host controller is accessing the nextTD * element and when the software also updates it, it will lead to errors. * This is a problem only with asynchronous QHs */ pQHTemp = (PUCHAR) pHCDPipe->pNext->pQH; pQHTemp += USB_EHCD_QH_HEADER_SIZE; USB_EHCD_SET_BITFIELD(uBusIndex, QH, pHCDTempPipe->pQH->uQueueHeadHorizontalLinkPointer, ((unsigned) USB_EHCD_CONVERT_TO_BUS_MEM( uBusIndex, pQHTemp) >> 5), HORIZONTAL_LINK_POINTER); /* * Fetch the address of the host controller accessable region * by adding the offest USB_EHCD_QH_HEADER_SIZE to queue head */ pQHTemp = (PUCHAR) pHCDPipe->pQH; pQHTemp += USB_EHCD_QH_HEADER_SIZE; /* * If the host controller is accessing currently the removed QH, * update the host controller's current accessible QH */ if (USB_EHCD_GET_FIELD(pHCDData, ASYNCLISTADDR, LINK_PTR_LOW) == ((UINT32)USB_EHCD_CONVERT_TO_BUS_MEM( uBusIndex, pQHTemp) >> USB_EHCD_ASYNCHLISTADDR_LINK_PTR_LOW)) { /* * Fetch the address of the host controller accessable region * by adding the offest USB_EHCD_QH_HEADER_SIZE to queue head */ pQHTemp = (PUCHAR) pHCDPipe->pNext->pQH; pQHTemp += USB_EHCD_QH_HEADER_SIZE; USB_EHCD_SET_FIELD(pHCDData, ASYNCLISTADDR, LINK_PTR_LOW, ((UINT32)USB_EHCD_CONVERT_TO_BUS_MEM( uBusIndex, pQHTemp) >> USB_EHCD_ASYNCHLISTADDR_LINK_PTR_LOW)); } /* Enable the asynchronous schedule */ USB_EHCD_SET_BIT(pHCDData, USBCMD, ASYNCH_SCHEDULE_ENABLE); /* Create a synchronisation event*/ if (NULL == (pHCDPipe->DeleteSynchEventID = OS_CREATE_EVENT(OS_EVENT_NON_SIGNALED))) { OS_ASSERT(FALSE); } /* Add to the reclamation list */ USB_EHCD_ADD_TO_ASYNCH_RECLAMATION_LIST(pHCDData, pHCDPipe); /* * If only the asynch schedule enable bit and status bit are * set, the schedule can be termed to be enabled. * Wait till both of the bits are set. Unless otherwise the schedule * is enabled, the async advance doorbell bit cannot be set in USBCMD * register. */ while ((USB_EHCD_GET_FIELD(pHCDData, USBCMD, ASYNCH_SCHEDULE_ENABLE) == 0) || (USB_EHCD_GET_FIELD(pHCDData, USBSTS, ASYCHRONOUS_SCHEDULE_STATUS) ==0)) OS_DELAY_MS(1);#ifndef USB_EHCD_ENABLE_POLLING /* Enable the aynch advance interrupt */ USB_EHCD_SET_BIT_USBINTR_INT_ON_ASYNC_ADVANCE_DOORBELL(pHCDData);#endif /* * Enable an interrupt to be generated * when the Asynchronous list is advanced. */ USB_EHCD_SET_BIT_USBCMD_INT_ON_ASYNC_ADVANCE_DOORBELL(pHCDData); /* * The USBCMD to set asynch advance can be done only when the * schedule is enabled. The lock is released after the USBCMD is * written to prevent any other thread from disabling the schedule. */ OS_RELEASE_EVENT(pHCDData->RequestSynchEventID); /* Wait for event handler task to free the resources */ OS_WAIT_FOR_EVENT(pHCDPipe->DeleteSynchEventID, OS_WAIT_INFINITE); /* Delete the event created */ OS_DESTROY_EVENT(pHCDPipe->DeleteSynchEventID); /* Free the PIPE */ OS_FREE(pHCDPipe); } /* It is a periodic endpoint, */ else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -