?? usbehcdutil.c
字號:
** This function is used to calculate the bus time required for the endpoint.** <uSpeed> - Speed of the device.* <uDirection> - Direction of the pipe.* <uPipeType> - Type of the endpoint.* <uDataByteCount> - maximum byte count supported by the pipe.** RETURNS: Calculated bus time in nanoseconds.** ERRNO:* None.** \NOMANUAL*/INT32 usbEhcdCalculateBusTime ( UINT32 uSpeed, /* Speed of the device */ UINT32 uDirection, /* Direction of the pipe */ UINT32 uPipeType, /* type of the pipe */ UINT32 uDataByteCount /* Maximum byte count supported by the pipe */ ) { /* Calculate the bus time for a low speed pipe */ if(USBHST_LOW_SPEED == uSpeed) { /* Calculate the bustime for an IN pipe */ if (USB_EHCD_DIR_IN == uDirection) { return (INT32)(64060+(2*USB_EHCD_HUB_LS_SETUP)+(676.67* floor(3.167+USB_EHCD_BIT_STUFF_TIME(uDataByteCount)))+ USB_EHCD_HOST_DELAY); } /* Calculate the bustime for an OUT pipe */ else { return (INT32)(64107+(2*USB_EHCD_HUB_LS_SETUP)+(667.0* floor(3.167+USB_EHCD_BIT_STUFF_TIME(uDataByteCount)))+ USB_EHCD_HOST_DELAY); } } /* End of if(Speed == USBHST_LOW_SPEED) */ /* Calculate the bus time for a Full speed pipe */ else if(USBHST_FULL_SPEED == uSpeed) { /* Calculate the bus time for a control, bulk or interrupt pipe */ if( USBHST_ISOCHRONOUS_TRANSFER != uPipeType) { return(INT32)(9107 +(83.54 * floor(3.167+ USB_EHCD_BIT_STUFF_TIME(uDataByteCount)))+ USB_EHCD_HOST_DELAY); } /* Calculate the bus time for an isochronous pipe */ else {#if 0 /* Just to recheck BW calculation currently returning 'zero'*/ /* Calculate the bus time for an IN endpoint */ if (USB_EHCD_DIR_IN == uDirection) { return (INT32)(7268+(83.54 * floor(3.167+ USB_EHCD_BIT_STUFF_TIME(uDataByteCount)))+ USB_EHCD_HOST_DELAY); } /* Calculate the bus time for an OUT endpoint */ else { return (INT32)(6265+(83.54 * floor(3.167+USB_EHCD_BIT_STUFF_TIME(uDataByteCount)))+ USB_EHCD_HOST_DELAY); }#endifreturn 1; } /* End of else */ } /* End of else if(Speed == USBHST_FULL_SPEED) */ /* Calculate the bus time for a high speed pipe */ else if(USBHST_HIGH_SPEED == uSpeed) { /* Calculate the bus time for a control, bulk or interrupt pipe */ if(USBHST_ISOCHRONOUS_TRANSFER != uPipeType) { return (INT32)((55 * 8 * 2.083)+(2.083* floor(3.167 + USB_EHCD_BIT_STUFF_TIME(uDataByteCount))) + USB_EHCD_HOST_DELAY); } /* Calculate the bus time for an isochronous pipe */ else { return (INT32)((38 * 8 * 2.083)+(2.083* floor(3.167 + USB_EHCD_BIT_STUFF_TIME(uDataByteCount))) + USB_EHCD_HOST_DELAY); } } /* End of else if(Speed == USBHST_HIGH_SPEED) */ return -1; } /* End of usbEhcdCalculateBusTime() *//***************************************************************************** usbEhcdCheckBandwidth - checks the bandwidth availability** This function is used to check whether bandwidth is available and returns the* list which can hold the endpoint and also the mask value which indicates the* microframes which can hold the endpoint transfers.** <pHCDData> - Pointer to the EHCD_DATA structure.* <uBandwidth > - Bandwidth to be reserved.* <uSpeed> - Speed of the transfer.* <pEndpointDesc> - Pointer to the endpoint descriptor.* <puListIndex> - Pointer which can hold the list index which holds the endpoint* transfers* <puMicroFrameMask> - Pointer to the mask value which can hold the microframes* which can hold the endpoint transfers.* <puStepValue> - Pointer to the step value used for stepping into the* frame list for isochronous transfers.* RETURNS: TRUE if the bandwidth can be accomodated.* FALSE if the bandwidth cannot be accomodated.** ERRNO:* None.** \NOMANUAL*/BOOLEAN usbEhcdCheckBandwidth ( pUSB_EHCD_DATA pHCDData, /* Pointer to the EHCD_DATA structure */ ULONG uBandwidth, /* Bandwidth to be reserved */ UINT32 uSpeed, /* Speed of the transfer */ pUSBHST_ENDPOINT_DESCRIPTOR pEndpointDesc, /* Pointer to the endpoint desc */ UINT32 * puListIndex,/* Pointer to the list index */ UINT32 * puMicroFrameMask, /* Pointer to the microframe mask value */ UINT32 * puStepValue /* Pointer to the step value into the framelist */ ) { /* To hold the index into the periodic frame list */ UINT32 uCount = 0; /* To hold the polling interval */ UINT32 uPollInterval = 0; /* To hold the bandwidth calculated */ UINT32 uCalculatedBandwidth = 0; /* To hold the least occupied bandwidth */ UINT32 uLeastBandwidth = 0; /* To hold the index of the frame which has the least occupied bandwidth */ UINT32 uLeastBwIndex = 0; OS_LOG_MESSAGE_LOW(EHCD,"usbEhcdCheckBandwidth - Entry\n",0,0,0,0); /* Check the validity of the parameters */ if ((NULL == pHCDData) || (0 == uBandwidth) || (NULL == pEndpointDesc) || (USBHST_HIGH_SPEED != uSpeed && USBHST_FULL_SPEED != uSpeed && USBHST_LOW_SPEED != uSpeed) || (NULL == puStepValue) || (NULL == puListIndex) || (NULL == puMicroFrameMask)) { OS_LOG_MESSAGE_HIGH(EHCD,"usbEhcdCheckBandwidth - Invalid parameter\n",0,0,0,0); return FALSE; } /* Return error if the type is not a periodic endpoint type */ if ((USBHST_ISOCHRONOUS_TRANSFER != (pEndpointDesc->bmAttributes & USB_EHCD_ENDPOINT_TYPE_MASK)) && (USBHST_INTERRUPT_TRANSFER != (pEndpointDesc->bmAttributes & USB_EHCD_ENDPOINT_TYPE_MASK))) { OS_LOG_MESSAGE_HIGH(EHCD,"usbEhcdCheckBandwidth - Not a periodic endpoint\n",0,0,0,0); return FALSE; } /* Exclusively access the bandwidth resource */ OS_WAIT_FOR_EVENT(pHCDData->BandwidthEventID,OS_WAIT_INFINITE); if (USBHST_ISOCHRONOUS_TRANSFER == (pEndpointDesc->bmAttributes & USB_EHCD_ENDPOINT_TYPE_MASK)) { UINT32 uMaxBandwidth = 0; /* Starting from the leaf nodes, check whether * supplied bandwidth can be accomodated here */ for (uCount = 0; USB_EHCD_MAX_FRAMELIST_SIZE > uCount; uCount++) { uCalculatedBandwidth = 0; /* Calculate the bandwidth occupied in this frame */ USB_EHCD_CALCULATE_FRAME_BANDWIDTH(pHCDData, uCount, uCalculatedBandwidth); /* Get the maximum bandwidth used in a frame */ if (uCalculatedBandwidth > uMaxBandwidth) { uMaxBandwidth = uCalculatedBandwidth; } } /* End of for () */ /* If there is no bandwidth available, return an error */ if ((USB_EHCD_EIGHTY_PERCENT_BW * USB_EHCD_MAX_MICROFRAME_NUMBER) < (uMaxBandwidth + uBandwidth)) { OS_LOG_MESSAGE_HIGH(EHCD,"usbEhcdCheckBandwidth - Bandwidth not available\n",0,0,0,0); /* Release the bandwidth exclusive access */ OS_RELEASE_EVENT(pHCDData->BandwidthEventID); return FALSE; } } /* Initialize the least bandwidth to be the maximum bandwidth applicable */ uLeastBandwidth = USB_EHCD_EIGHTY_PERCENT_BW * USB_EHCD_MAX_MICROFRAME_NUMBER; /* Starting from the leaf nodes, check whether bandwidth is available */ for (uCount = 0; USB_EHCD_MAX_FRAMELIST_SIZE > uCount; uCount++) { /* initialize the calculated bandwidth to be 0 */ uCalculatedBandwidth = 0; /* Calculate the bandwidth occupied in this frame */ USB_EHCD_CALCULATE_FRAME_BANDWIDTH(pHCDData, uCount, uCalculatedBandwidth); /* If the bandwidth occupied is less than the previous least bandwidth, * this becomes the least bandwidth reserved. */ if (uCalculatedBandwidth < uLeastBandwidth) { uLeastBandwidth = uCalculatedBandwidth; uLeastBwIndex = uCount; } } /* End of for () */ /* If there is no bandwidth available, return an error */ if ((USB_EHCD_EIGHTY_PERCENT_BW * USB_EHCD_MAX_MICROFRAME_NUMBER) < (uLeastBandwidth + uBandwidth)) { OS_LOG_MESSAGE_HIGH(EHCD,"usbEhcdCheckBandwidth - Bandwidth not available\n",0,0,0,0); /* Release the bandwidth exclusive access */ OS_RELEASE_EVENT(pHCDData->BandwidthEventID); return FALSE; } /* Get the polling interval of the endpoint */ uPollInterval = pEndpointDesc->bInterval; /* Check if it is a low or full speed device endpoint */ if (USBHST_HIGH_SPEED != uSpeed) { /* Check if it is an interrupt endpoint */ if (USBHST_INTERRUPT_TRANSFER == (pEndpointDesc->bmAttributes & USB_EHCD_ENDPOINT_TYPE_MASK)) { /* Array holding the start and complete split masks */ UINT32 uSplitMask[USB_EHCD_MAX_INT_SPLIT_MASKS] = { USB_EHCD_SPLIT_MASK_1, USB_EHCD_SPLIT_MASK_2, USB_EHCD_SPLIT_MASK_3, USB_EHCD_SPLIT_MASK_4 }; /* Identify the index of the leaf of the tree, which is to be used*/ *puListIndex = pHCDData->FrameListData[uLeastBwIndex].uNextListIndex; /* 32 is the maximum polling interval which is supported. * So if the polling interval is greater than 32, the endpoint * will be polled every 32 ms. */ if (USB_EHCD_MAX_USB11_INTERRUPT_POLL_INTERVAL > uPollInterval) { /* To hold the number of times the list is to be traversed */ UINT8 uTraversalCount = 0; /* Calculate the traversal count */ USB_EHCD_CALCULATE_TRAVERSAL_COUNT(uPollInterval,uTraversalCount); /* Get the Tree Index */ while (0 < uTraversalCount) { *puListIndex = pHCDData->TreeListData[*puListIndex].uNextListIndex; /* Decrement the traversal count */ uTraversalCount--; }/* End of while */ }/* End of if (EHCD_MAX_USB11_INTERRUPT_POLL_INTERVAL > ...*/ /* Initialize the least bandwidth occupied */ uLeastBandwidth = USB_EHCD_EIGHTY_PERCENT_BW * USB_EHCD_MAX_MICROFRAME_NUMBER; /* Retrieve the mask value which best fits this bandwidth */ for (uCount = 0; USB_EHCD_MAX_INT_SPLIT_MASKS > uCount; uCount++) { /* Initialize the uCalculatedBandwidth = 0 */ uCalculatedBandwidth = 0; /* Calculate the bandwidth with the node element added */ USB_EHCD_CALCULATE_BW_MICROFRAMES(pHCDData, uSplitMask[uCount], uLeastBwIndex, uCalculatedBandwidth); /* If this mask has the least bandwidth occupied, use this */ if (uCalculatedBandwidth < uLeastBandwidth) { uLeastBandwidth = uCalculatedBandwidth; *puMicroFrameMask = uSplitMask[uCount]; } } /* Check if the bandwidth cannot be accomodated */ if (USB_EHCD_EIGHTY_PERCENT_BW * USB_EHCD_MAX_MICROFRAME_NUMBER < (uLeastBandwidth + uBandwidth)) { OS_LOG_MESSAGE_HIGH(EHCD,"usbEhcdCheckBandwidth - No bandwidth \n",0,0,0,0); /* Release the bandwidth exclusive access */ OS_RELEASE_EVENT(pHCDData->BandwidthEventID); return FALSE; } /* Update the step value */ *puStepValue = 0; }/* End of if (USBHST_INTERRUPT_TRANSFER... */ /* The following is for isochronous transfer type */ else { /* Array holding the split masks */ UINT32 uSplitMask[USB_EHCD_MAX_MICROFRAME_NUMBER]; /* Initialize the split mask as per direction */ if (0 == (pEndpointDesc->bEndpointAddress & USB_EHCD_DIR_IN)) { /* Array holding the start split masks for OUT transaction */ uSplitMask[0] = 0x01; /* 00000001 */ uSplitMask[1] = 0x02; /* 00000010 */ uSplitMask[2] = 0x04; /* 00000100 */ uSplitMask[3] = 0x08; /* 00001000 */ uSplitMask[4] = 0x10; /* 00010000 */ uSplitMask[5] = 0x20; /* 00100000 */ uSplitMask[6] = 0x40; /* 01000000 */ uSplitMask[7] = 0x80; /* 10000000 */ } else { /* Array holding the start and complete split masks for IN transaction*/ uSplitMask[0] = USB_EHCD_SPLIT_MASK_1; uSplitMask[1] = USB_EHCD_SPLIT_MASK_2; uSplitMask[2] = USB_EHCD_SPLIT_MASK_3; uSplitMask[3] = USB_EHCD_SPLIT_MASK_4; uSplitMask[4] = 0x00; uSplitMask[5] = 0x00; uSplitMask[6] = 0x00; uSplitMask[7] = 0x00; } /* Initialize the least bandwidth occupied */ uLeastBandwidth = USB_EHCD_EIGHTY_PERCENT_BW * USB_EHCD_MAX_MICROFRAME_NUMBER; /* Retrieve the mask value which best fits this bandwidth */ for (uCount = 0; ((USB_EHCD_MAX_MICROFRAME_NUMBER > uCount) && (0 != uSplitMask[uCount])); uCount++) { /* Initialize the uCalculatedBandwidth = 0 */ uCalculatedBandwidth = 0; /* Calculate the bandwidth with the node element added */ USB_EHCD_CALCULATE_BW_MICROFRAMES(pHCDData, uSplitMask[uCount], uLeastBwIndex, uCalculatedBandwidth); /* If this mask has the least bandwidth occupied, use this */ if (uCalculatedBandwidth < uLeastBandwidth) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -