📄 usbuhcdscheduleqsupport.c
字号:
INT32 usbUhcdMaxIsoBwLinkedTo ( INT32 index, USB_UHCD_PERIODIC_TABLE * usbUhcdTable ) { /* Retrun the bandwith of the indexed usbUhcdTable */ return(usbUhcdTable[index].bandWidth); }/* End of usbUhcdMaxIsoBwLinkedTo() *//***************************************************************************** usbUhcdFindPosForIntQh - locates point for queueing the interrupt QH** This function is used to locate a suitable point for queueing the * interrupt QH based on the bandwidth required and the poll rate** RETURNS: FALSE if bandwidth cannot be accomodated for the interrupt pipe.** ERRNO:* None.** \NOMANUAL*/BOOLEAN usbUhcdFindPosForIntQh ( INT32 bwReqd, UINT reqPollRate, INT32 *listIndex, USB_UHCD_PERIODIC_TABLE * usbUhcdTable, USB_UHCD_PERIODIC_TREE * usbUhcdTree ) { /* To hold the least periodic bandwidth */ INT32 leastPeriodicBw = 0; /* Temporary variable to hold the bandwidth required */ INT32 bw = 0; /* To hold the index into the leaf of the periodic tree */ UINT i = 0; /* To hold the current polling rate */ UINT currPollRate = 0; /* Determine the Bandwidth taken up by the upper most branch of the tree */ leastPeriodicBw = usbUhcdFindTreeBw (127,usbUhcdTree) + usbUhcdMaxIsoBwLinkedTo (127,usbUhcdTable); /* Start from the first node in the leaf */ *listIndex = 127; OS_LOG_MESSAGE_MEDIUM(UHCD,"Entering usbUhcdFindPosForIntQh()\n",0,0,0,0); /* Determine the least bandwidth occupying branch of the tree */ for (i = 128; i < 255; i++) { /* Determine BW of Branch "i" */ bw = usbUhcdFindTreeBw (i, usbUhcdTree) + usbUhcdMaxIsoBwLinkedTo (i,usbUhcdTable); /* * If bandwidth occupied in this list is the least, * update the variable holding the least periodic bandwidth * Also update the list index. */ if (bw < leastPeriodicBw) { OS_LOG_MESSAGE_MEDIUM(UHCD,"BW occupied is list\n",0,0,0,0); leastPeriodicBw = bw; *listIndex = i; } /* If the lowest possible BW is hit, break out of this loop */ if (leastPeriodicBw == 0) { OS_LOG_MESSAGE_MEDIUM(UHCD,"reached the lowest BW\n",0,0,0,0); break; } }/* End of for() */ /* * If the least periodic BW plus required bandwidth excceeds max available, * QH cannot be accomodated */ if (leastPeriodicBw + bwReqd + USB_UHCD_SAFETY_MARGIN >= USB_UHCD_NINETY_PERCENT_BW) { OS_LOG_MESSAGE_MEDIUM(UHCD,"BW > max Available\n",0,0,0,0); return(FALSE); } /* * In the current list, * determine the node that has the required poll rate */ for (currPollRate = 128; currPollRate > reqPollRate; currPollRate /= 2) { *listIndex = usbUhcdFindLinkForQh (*listIndex); } /* * If the QH's position is other than at the leaf of the tree, * determine whether any path of the tree violates the maximim BW rule */ if (*listIndex < 127) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Check for QH violating\n",0,0,0,0); for (i = 127; i < 255; i++) { /* * If the current branch is linked to the newly found position, * check if BW exceeds what is available. * * Return FALSE if the following conditions are not successful * - Check whether the index specified by list_index pointer * is present in the node containing this leaf index 'i'. * - The bandwidth reserved already in addition to the bandwidth * requested for has exceeded the 90% of the allocation * meant for the periodic transfers. */ if (usbUhcdIsLinked(i, *listIndex) && (usbUhcdFindTreeBw ( i,usbUhcdTree) + usbUhcdMaxIsoBwLinkedTo (i, usbUhcdTable) + bwReqd + USB_UHCD_SAFETY_MARGIN) >= USB_UHCD_NINETY_PERCENT_BW) { OS_LOG_MESSAGE_MEDIUM(UHCD,"BW exceeds available\n",0,0,0,0); return FALSE; } }/* End of for() */ }/* End of if() */ OS_LOG_MESSAGE_MEDIUM(UHCD,"Exiting usbUhcdFindPosForIntQh()\n",0,0,0,0); return(TRUE); }/* End of usbUhcdFindPosForIntQh() *//***************************************************************************** usbUhcdIsLinked - determines if node is linked** This function is used to determine whether 2 nodes of the tree is* the part of the same list or not** RETURNS: FALSE if the nodes are not linked.** ERRNO:* None.** \NOMANUAL*/BOOLEAN usbUhcdIsLinked ( INT32 listIndexOuter, INT32 listIndexInner ) { /* To hold the index value */ INT32 index = 0; OS_LOG_MESSAGE_MEDIUM(UHCD,"Entering usbUhcdIsLinked\n",0,0,0,0); /* * From the outer node, traverse the branch till we reach the inner node * or the tip of the tree is reached */ for (index = listIndexOuter; index != listIndexInner && index >= 0; index = usbUhcdFindLinkForQh (index)); /* if the inner node is hit, return TRUE */ if (index == listIndexInner) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Inner node hit\n",0,0,0,0); return(TRUE); } OS_LOG_MESSAGE_MEDIUM(UHCD,"Exiting usbUhcdIsLinked()\n",0,0,0,0); /* Not hit, return FALSE */ USB_UHCD_LOG_ERROR_MESSAGE("Node is not Linked\n"); return(FALSE); }/* End of usbUhcdIsLinked() *//***************************************************************************** usbUhcdMakeTds - create the TDs needed for a transfer** This routine creates the TDs needed for a transfer.** RETURNS: FALSE if TDs are not created successfully.** ERRNO:* None.* * \NOMANUAL*/BOOLEAN usbUhcdMakeTds ( UINT32 uBusIndex, USB_UHCD_TD **head, USB_UHCD_TD **tail, USBHST_URB *urb, UINT8 *toggle , USB_UHCD_HCD_PIPE *targetPipe ) { /* To hold the pointer to the current TD */ USB_UHCD_TD *currentTd = NULL; /* To hold the pointer to the temporary TD */ USB_UHCD_TD *temp = NULL; /* To hold the number of bytes to be transferred */ UINT bytesTransfered=0; /* Extract the setup packet information */ pUSBHST_SETUP_PACKET pSetupPacket = (pUSBHST_SETUP_PACKET)urb->pTransferSpecificData; /* Call the function to create the 1st TD needed for the transfer */ currentTd = *head = usbUhcdFormEmptyTd ((UINT32)targetPipe); OS_LOG_MESSAGE_MEDIUM(UHCD,"Entering usbUhcdMakeTds()\n",0,0,0,0); /* If unable to create the TD, return FALSE */ if (currentTd == NULL) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Unable to create TD\n",0,0,0,0); return FALSE; } /* * This loop will create that many TDs based on the number of * bytes to be transmitted */ while (bytesTransfered < urb->uTransferLength) { /* Short packet detection is valid only for non Isochronous pipe */ currentTd->dWord1Td |= USBUHCD_TDCS_SHORT; /* Set the buffer pointer of the TD */ currentTd->dWord3Td = USB_UHCD_CONVERT_TO_BUS_MEM (uBusIndex, (urb->pTransferBuffer + bytesTransfered)); /* Set the Maxlength Field of the TD */ /* Check if the bytes to transfer is less than maximum packet size */ if ((urb->uTransferLength - bytesTransfered) < targetPipe->uMaximumPacketSize) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Byte transfer < max \n",0,0,0,0); /* Check if it is a non 0 byte data transfer to be done */ if (urb->uTransferLength-bytesTransfered) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Non zero byte transfer\n",0,0,0,0); /* Update the maximum length of data in the TD */ currentTd->dWord2Td &= ~(USBUHCD_TDTOK_MAXLEN_MASK); currentTd->dWord2Td |= USBUHCD_TDTOK_MAXLEN_FMT( urb->uTransferLength-bytesTransfered - 1 ); } /* A zero byte data transfer */ else { OS_LOG_MESSAGE_MEDIUM(UHCD,"Zero byte transfer\n",0,0,0,0); currentTd->dWord2Td &= ~(USBUHCD_TDTOK_MAXLEN_MASK); currentTd->dWord2Td |= USBUHCD_TDTOK_MAXLEN_FMT(0x7FF); } /* Keep track of the number of bytes transfered */ bytesTransfered += ( urb->uTransferLength-bytesTransfered ); } /* If the bytes to transfer is more than maximum packet size */ else { OS_LOG_MESSAGE_MEDIUM(UHCD,"byte transfer > max\n",0,0,0,0); bytesTransfered += targetPipe->uMaximumPacketSize; } /* Set the toggle bit of the TD for non isochronous TD */ if (targetPipe->endPointType != PIPE_ISOCHRONOUS) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Pipe is not Isochronous -- set toggle bit\n",0,0,0,0); if (*toggle) { currentTd->toggle = 1; currentTd->dWord2Td |= USBUHCD_TDTOK_DATA_TOGGLE; } else { currentTd->toggle = 0; currentTd->dWord2Td &= ~(USBUHCD_TDTOK_DATA_TOGGLE); } *toggle = (*toggle == 0) ? 1 : 0; } /* For isochronous, set toggle to 0, since toggle is not used */ /* Update PID field of the TD */ if (targetPipe->endPointType != PIPE_CONTROL) { currentTd->dWord2Td &= ~(USBUHCD_TDTOK_PID_MASK); if ( targetPipe ->endPointDirection == 1) currentTd->dWord2Td |= USBUHCD_TDTOK_PID_FMT(0x69); else currentTd->dWord2Td |= USBUHCD_TDTOK_PID_FMT(0xE1); } else { currentTd->dWord2Td &=~(USBUHCD_TDTOK_PID_MASK); if (0 != (pSetupPacket->bmRequestType & 0x80)) currentTd->dWord2Td |= USBUHCD_TDTOK_PID_FMT(0x69); else currentTd->dWord2Td |= USBUHCD_TDTOK_PID_FMT(0xE1); } /* Check if more bytes need to be transfered */ if (bytesTransfered < urb->uTransferLength) { OS_LOG_MESSAGE_MEDIUM(UHCD,"More bytes to be transfered\n",0,0,0,0); /* Non-isochronous transfer */ if (targetPipe->endPointType != PIPE_ISOCHRONOUS) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Pipe ! Isochronous\n",0,0,0,0); /* Form a new TD */ currentTd->hNextTd = usbUhcdFormEmptyTd ((UINT32)targetPipe); /* If unable to allocate memory for the TD */ if (currentTd->hNextTd == NULL) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Unable to allocate memoery \n",0,0,0,0); /* Clean up memory allocated for the TD till now */ for (currentTd = *head; currentTd != NULL;) { temp = currentTd->hNextTd; UHCI_FREE((UCHAR*)currentTd - currentTd->offsetForFreeing); currentTd = temp; } /* Return FALSE */ return FALSE; } /* Update the HC TD's link pointer */ currentTd->dWord0Td &=~(USBUHCD_LINK_PTR_MASK); currentTd->dWord0Td |= USBUHCD_LINK_PTR_FMT( ((unsigned) currentTd->hNextTd) >> 4); /* Indicate that this is not the last element in the queue */ currentTd->dWord0Td &= ~(USBUHCD_LINK_TERMINATE); currentTd->dWord0Td = USB_UHCD_CONVERT_TO_BUS_MEM( uBusIndex, (PVOID)currentTd->dWord0Td); /* Store the previous element of the next TD */ currentTd->hNextTd->hPrevTd = currentTd; /* Update the current pointer */ currentTd = currentTd->hNextTd; /* Make the next pointer as NULL */ currentTd->hNextTd = NULL; }/* End of if() */ }/* End of if(bytesTransfered < urb->uTransferBufferLen) */ }/* End of while () */ /* Update the tail pointer so as to make it point to the last TD */ *tail = currentTd; OS_LOG_MESSAGE_MEDIUM(UHCD,"Exiting usbUhcdMakeTds()\n",0,0,0,0); /* Return TRUE */ return(TRUE); }/* End of usbUhcdMakeTds() *//***************************************************************************** usbUhcdMakeIsocTds - create the TDs needed for a transfer** This routine creates the TDs needed for a transfer.** RETURNS: FALSE if TDs are not created successfully.** ERRNO:* None.** \NOMANUAL*/BOOLEAN usbUhcdMakeIsocTds ( UINT32 uBusIndex, USB_UHCD_TD **head, USB_UHCD_TD **tail, USBHST_URB *purb, UINT8 *toggle , USB_UHCD_HCD_PIPE *targetPipe ) { /* To hold the pointer to the current TD */ USB_UHCD_TD *currentTd = NULL; /* To hold the pointer to the temporary TD */ USB_UHCD_TD *temp = NULL; UINT32 numberOfTDs = purb->uNumberOfPackets; /* Pointer to the isoc packets */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -