📄 usbohcitransfermanagement.c
字号:
/* Obtain the endpoint transfer type */ uEndpointTransferType = USB_GET_ENDPOINT_TRANSFER_TYPE(pUsbEndpointDescriptor->bmAttributes); /* Obtain the maximum packet size for the endpoint */ uEndpointMaximumPacketSize = OS_UINT16_CPU_TO_LE(pUsbEndpointDescriptor->wMaxPacketSize); /* * Based on the endpoint type, allocate memory for the empty transfer * descriptor. * * The reason for the empty transfer descriptor list is as follows: * * "The host controller stops processing the transfers when the * pointer to the head of the transfer list is same as the pointer * to the tail of the transfer list." * * Assume that one node is added to the transfer list. Since the head * and the tail of the transfer list will point to the same node, the * host controller will not service the transfer. Hence an empty * transfer descriptor is required at the end of the transfer list. */ if (uEndpointTransferType == USB_ISOCHRONOUS_ENDPOINT) { /* Allocate memory for the empty isochronous transfer descriptor */ pEmptyIsochronousTransferDescriptor = usbOhciCreateIsochronousTransferDescriptorList(uHostControllerIndex, 1, pOhciEndpointDescriptor); /* * Check whether the empty isochronous transfer descriptor was created * succesfully */ if (pEmptyIsochronousTransferDescriptor == NULL) { /* Release the memory allocated for the endpoint descritpor */ OHCI_FREE(pOhciEndpointDescriptor->pNonAlignedEndpointDescriptor); /* Return from the function */ /* Debug print */ OS_LOG_MESSAGE_LOW( OHCD, "Exiting the function: usbOhciCreatePipe().\n", 0, 0, 0, 0); return USBHST_INSUFFICIENT_MEMORY; } } else { /* Allocate memory for the empty general transfer descriptor */ pEmptyGeneralTransferDescriptor = usbOhciCreateGeneralTransferDescriptorList(uHostControllerIndex, 1, pOhciEndpointDescriptor); /* * Check whether the empty general transfer descriptor was created * succesfully */ if (pEmptyGeneralTransferDescriptor == NULL) { /* Release the memory allocated for the endpoint descritpor */ OHCI_FREE(pOhciEndpointDescriptor->pNonAlignedEndpointDescriptor); /* Return from the function */ /* Debug print */ OS_LOG_MESSAGE_LOW( OHCD, "Exiting the function: usbOhciCreatePipe().\n", 0, 0, 0, 0); return USBHST_INSUFFICIENT_MEMORY; } } /* Populate the endpoint descriptor (BEGIN) */ /* Obtain the endpoint number */ uEndpointNumber = USB_GET_ENDPOINT_NUMBER(pUsbEndpointDescriptor->bEndpointAddress); /* Obtain the endpoint direction */ uEndpointDirection = USB_GET_ENDPOINT_DIRECTION(pUsbEndpointDescriptor->bEndpointAddress); /* Obtain the endpoint transfer type */ uEndpointTransferType = USB_GET_ENDPOINT_TRANSFER_TYPE(pUsbEndpointDescriptor->bmAttributes); /* Obtain the maximum packet size for the endpoint */ uEndpointMaximumPacketSize = OS_UINT16_CPU_TO_LE(pUsbEndpointDescriptor->wMaxPacketSize); /* * Format the endpoint direction based on the transfer type and the endpoint * direction. This value will be populated in the OHCI endpoint descriptor. */ if (uEndpointTransferType == USB_CONTROL_ENDPOINT) { /* Bidirectional endpoint */ uEndpointDirection = OHCI_BIDIRECTIONAL_ENDPOINT; } else if (uEndpointDirection == USB_IN_ENDPOINT) { /* IN endpoint */ uEndpointDirection = OHCI_IN_ENDPOINT; } else { /* OUT endpoint */ uEndpointDirection = OHCI_OUT_ENDPOINT; } /* Obtain the format of the transfer descriptor */ if (uEndpointTransferType == USB_ISOCHRONOUS_ENDPOINT) { /* Isochronous transfer descriptor */ uTransferDescriptorFormat = OHCI_ISOCHRONOUS_TD_FORMAT; } else { /* * General transfer descriptor for control, bulk or interrupt * transfers */ uTransferDescriptorFormat = OHCI_GENERAL_TD_FORMAT; } /* Populate the OHCI endpoint descriptor */ OHCI_POPULATE_ED_CONTROL_INFO(uHostControllerIndex, pOhciEndpointDescriptor->uControlInformation, uDeviceAddress, uEndpointNumber, uEndpointDirection, uSpeed, uTransferDescriptorFormat, uEndpointMaximumPacketSize); /* * Since no transfers are pending, set the SKIP bit for the OHCI Endpoint * Descriptor. * * Even though the controller will not schedule the transfers if the * TDQueueHead is equal to TDQueueTail, by setting the SKIP bit, the * endpoint descriptor will be totally ignored, i.e. the host controller * will not attempt to check TDQueueHead and TDQueueTail. */ OHCI_SET_ED_SKIP_BIT(uHostControllerIndex, pOhciEndpointDescriptor->uControlInformation); /* * Based on the endpoint type, initialize the pointers to the head * and tail of the transfer descriptor list. */ if (uEndpointTransferType == USB_ISOCHRONOUS_ENDPOINT) { /* * Initialize the pointer to the head of the transfer descriptor * list */ pOhciEndpointDescriptor->TDQueueHead.pIsochronousTDQueueHead = (USB_OHCI_ISOCHRONOUS_TRANSFER_DESCRIPTOR *) (USB_OHCD_SWAP_DATA (uHostControllerIndex, (UINT32)USB_OHCD_CONVERT_TO_BUS_MEM ( uHostControllerIndex, pEmptyIsochronousTransferDescriptor))); /* * Initailize the pointer to the tail of the transfer descriptor * list */ pOhciEndpointDescriptor->TDQueueTail.pIsochronousTDQueueTail = (USB_OHCI_ISOCHRONOUS_TRANSFER_DESCRIPTOR *) (USB_OHCD_SWAP_DATA (uHostControllerIndex, (UINT32)USB_OHCD_CONVERT_TO_BUS_MEM ( uHostControllerIndex, pEmptyIsochronousTransferDescriptor))); /* Copy the TD pointers in the head and tail pointers of the ED. * This is required while traversing the list for adding further TDs */ pOhciEndpointDescriptor->pHCDTDTail = pEmptyIsochronousTransferDescriptor; /* Flush the cache contents to the RAM */ DMA_FLUSH(pOhciEndpointDescriptor, sizeof(USB_OHCI_ENDPOINT_DESCRIPTOR)); /* Invalidate the cache */ DMA_INVALIDATE(pOhciEndpointDescriptor, sizeof(USB_OHCI_ENDPOINT_DESCRIPTOR)); } else { /* * Initialize the pointer to the head of the transfer descriptor * list */ pOhciEndpointDescriptor->TDQueueHead.pGeneralTDQueueHead = (USB_OHCI_GENERAL_TRANSFER_DESCRIPTOR *) (USB_OHCD_SWAP_DATA (uHostControllerIndex, (UINT32)USB_OHCD_CONVERT_TO_BUS_MEM ( uHostControllerIndex, pEmptyGeneralTransferDescriptor))); /* * Initailize the pointer to the tail of the transfer descriptor * list */ pOhciEndpointDescriptor->TDQueueTail.pGeneralTDQueueTail = (USB_OHCI_GENERAL_TRANSFER_DESCRIPTOR *) (USB_OHCD_SWAP_DATA (uHostControllerIndex, (UINT32)USB_OHCD_CONVERT_TO_BUS_MEM (uHostControllerIndex, pEmptyGeneralTransferDescriptor))); /* Copy the TD pointers in the head and tail pointers of the ED. * This is required while traversing the list for adding further TDs */ pOhciEndpointDescriptor->pHCDTDTail = pEmptyGeneralTransferDescriptor; /* Flush the cache contents to the RAM */ DMA_FLUSH(pOhciEndpointDescriptor, sizeof(USB_OHCI_ENDPOINT_DESCRIPTOR)); /* Invalidate the cache */ DMA_INVALIDATE(pOhciEndpointDescriptor, sizeof(USB_OHCI_ENDPOINT_DESCRIPTOR)); } /* Create the synchronization event */ pOhciEndpointDescriptor->synchEvent = OS_CREATE_EVENT(OS_EVENT_SIGNALED); /* Check if the event is created successfully */ if (pOhciEndpointDescriptor->synchEvent == NULL) { OS_LOG_MESSAGE_HIGH( OHCD, "Error creating the synch event: usbOhciCreatePipe().\n", 0, 0, 0, 0); /* Release the memory allocated for the endpoint descritpor */ OHCI_FREE(pOhciEndpointDescriptor->pNonAlignedEndpointDescriptor); return USBHST_INSUFFICIENT_RESOURCE; } /* * Wait for the 'endpoint list access event' before updating the * list. This event is important to prevent simultaneous updation of * the endpoint descriptor list. */ OS_WAIT_FOR_EVENT(pOhciControllerInfo->endpointListAccessEvent, OS_WAIT_INFINITE); /* * Check the transfer type and add the endpoint descriptor to the * corresponding endpoint descriptor list. */ switch (uEndpointTransferType) { case USB_OHCI_CONTROL_TRANSFER: /* * Obtain the pointer to the tail of the control endpoint descriptor * list */ pTempEndpointDescriptor = pOhciControllerInfo->pControlEndpointDescriptorListTail; /* Check whether the current endpoint descriptor list is valid */ if (pTempEndpointDescriptor != NULL) { /* * Append the endpoint descriptor to the tail of the control * endpoint descriptor list. */ pTempEndpointDescriptor->pNextEndpointDescriptor = (USB_OHCI_ENDPOINT_DESCRIPTOR *) (USB_OHCD_SWAP_DATA (uHostControllerIndex, (UINT32)USB_OHCD_CONVERT_TO_BUS_MEM ( uHostControllerIndex, pOhciEndpointDescriptor))); /* Store the pointer in the HCD maintained next pointer. * This would be requried while the ED is being deleted */ pTempEndpointDescriptor->pHCDNextEndpointDescriptor = pOhciEndpointDescriptor; /* Flush the contents of the cache to the RAM */ DMA_FLUSH(pTempEndpointDescriptor, sizeof(USB_OHCI_ENDPOINT_DESCRIPTOR)); /* Invalidate the cache */ DMA_INVALIDATE(pTempEndpointDescriptor, sizeof(USB_OHCI_ENDPOINT_DESCRIPTOR)); } else { USB_OHCI_REG_WRITE(uHostControllerIndex, (uBaseAddress + USB_OHCI_CONTROL_HEAD_ED_REGISTER_OFFSET), ((UINT32)USB_OHCD_CONVERT_TO_BUS_MEM(uHostControllerIndex, pOhciEndpointDescriptor))); } /* * Update the pointer to the tail of the control endpoint descriptor * list */ pOhciControllerInfo->pControlEndpointDescriptorListTail = pOhciEndpointDescriptor; break; case USB_OHCI_BULK_TRANSFER: /* * Obtain the pointer to the tail of the bulk endpoint descriptor * list */ pTempEndpointDescriptor = pOhciControllerInfo->pBulkEndpointDescriptorListTail; /* Check whether the current endpoint descriptor list is valid */ if (pTempEndpointDescriptor != NULL) { /* * Append the endpoint descriptor to the tail of the bulk * endpoint descriptor list. */ pTempEndpointDescriptor->pNextEndpointDescriptor = (USB_OHCI_ENDPOINT_DESCRIPTOR *) (USB_OHCD_SWAP_DATA(uHostControllerIndex, (UINT32)USB_OHCD_CONVERT_TO_BUS_MEM ( uHostControllerIndex, pOhciEndpointDescriptor))); /* Store the pointer in the HCD maintained next pointer. * This would be requried while the ED is being deleted */ pTempEndpointDescriptor->pHCDNextEndpointDescriptor = pOhciEndpointDescriptor; /* Flush the contents of the cache to the RAM */ DMA_FLUSH(pTempEndpointDescriptor, sizeof(USB_OHCI_ENDPOINT_DESCRIPTOR)); /* Invalidate the cache */ DMA_INVALIDATE(pTempEndpointDescriptor, sizeof(USB_OHCI_ENDPOINT_DESCRIPTOR)); } else { /* Program the HcBulkHeadED register */ USB_OHCI_REG_WRITE(uHostControllerIndex , (uBaseAddress + USB_OHCI_BULK_HEAD_ED_REGISTER_OFFSET),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -