📄 usbuhcdschedulequeue.c
字号:
USB_UHCD_SWAP_BUFDATA( uBusIndex, pUrb->pTransferBuffer, pUrb->uTransferLength); /* Call the function to create the TDs required for the transfer */ if (usbUhcdMakeTds ( uBusIndex, &nIreqQ->head, &nIreqQ->tail, pUrb, &(nIreqQ->qh->toggle),targetPipe) == FALSE) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Make TD failed\n",0,0,0,0); return(USBHST_FAILURE); } /* * Generate an interrupt on completion * of transfer indicated by the tail element of the request */ nIreqQ->tail->dWord1Td |=USBUHCD_TDCS_COMPLETE; } /* Check if it is an interrupt transfer request */ else if (targetPipe->endPointType == PIPE_INTERRUPT) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Pipe type Interrupt\n",0,0,0,0); /* Call the function to create the TDs required for the transfer */ USER_FLUSH(pUrb->pTransferBuffer, pUrb->uTransferLength); /* Swap the buffer data */ if ( pUrb->pTransferBuffer != NULL) USB_UHCD_SWAP_BUFDATA( uBusIndex, pUrb->pTransferBuffer, pUrb->uTransferLength); if (usbUhcdMakeTds ( uBusIndex, &nIreqQ->head, &nIreqQ->tail, pUrb, &(nIreqQ->qh->toggle),targetPipe) == FALSE) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Make TD failed\n",0,0,0,0); return(USBHST_FAILURE); } /* Interrupt on completion of tail */ nIreqQ->tail->dWord1Td |=USBUHCD_TDCS_COMPLETE; } /* * Taking the semaphore for exclusive access of the critical * section data */ for (temptd = nIreqQ->head; temptd !=nIreqQ->tail->hNextTd; temptd = temptd->hNextTd) { usbUhcdMakeTDLE(uBusIndex, temptd); DMA_FLUSH(temptd, sizeof(USB_UHCD_TD)); } if(pUrb->pTransferBuffer) USER_INVALIDATE(pUrb->pTransferBuffer, pUrb->uTransferLength); /* Enter the critical section */ usbUhcdEnterCritical(pHCDData); /* Link the creq\ated Request Block to the Non Isochronous Request Queue */ if (pHCDData->usbUhcdNonIsoRequestQ == NULL) { pHCDData->usbUhcdNonIsoRequestQ = nIreqQ; } else { nIreqQ->next = pHCDData->usbUhcdNonIsoRequestQ; pHCDData->usbUhcdNonIsoRequestQ = nIreqQ; } /* Link the list of TDs to the qHead - Start */ /* There is no TD linked to the QH */ if (targetPipe->qh->td == NULL) { OS_LOG_MESSAGE_MEDIUM(UHCD,"No TD linked to QH\n",0,0,0,0); targetPipe->qh->td = nIreqQ->head; targetPipe->qh->tdLast = nIreqQ->tail; dword0 = 0; dword0 &= ~(USBUHCD_LINK_PTR_MASK); dword0 |= ( USBUHCD_LINK_PTR_FMT( ((unsigned) nIreqQ->head) >> 4)); dword0 &= ~(USBUHCD_LINK_TERMINATE); dword0 = USB_UHCD_CONVERT_TO_BUS_MEM( uBusIndex, (PVOID)dword0); dword0 = USB_UHCD_SWAP_DATA( uBusIndex, dword0); targetPipe->qh->dWord1Qh = dword0; DMA_FLUSH(targetPipe->qh, sizeof(USB_UHCD_QH)); } /* There are TDs already linked to the QH */ else { dword0 = 0; OS_LOG_MESSAGE_MEDIUM(UHCD,"TD are linked to QH\n",0,0,0,0); td = targetPipe->qh->tdLast; targetPipe->qh->tdLast = nIreqQ->tail; /* * Update the last element's next pointer to point to * the head of the request created newly */ td->hNextTd = nIreqQ->head; /* * Update the previous element of the head of the request to the * last element which was already present in the queue */ nIreqQ->head->hPrevTd = td; /* Update the HC TD's link pointer */ dword0 &= ~(USBUHCD_LINK_PTR_MASK); dword0 |= USBUHCD_LINK_PTR_FMT( ((unsigned) nIreqQ->head) >> 4); dword0 &= ~(USBUHCD_LINK_TERMINATE); dword0 = USB_UHCD_CONVERT_TO_BUS_MEM( uBusIndex, (PVOID)dword0); dword0 = USB_UHCD_SWAP_DATA( uBusIndex, dword0); td->dWord0Td = dword0; DMA_FLUSH(td, sizeof(USB_UHCD_TD)); /* * The status field indicating a 0 on bit 7 indicates that * the request has been serviced by the Host controller */ /* check if the request has been serviced */ if ((USB_UHCD_SWAP_DATA(uBusIndex, td->dWord1Td) & USBUHCD_TDCS_STS_ACTIVE) == 0) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Request has been serviced\n",0,0,0,0); /* Update the link pointer to point to the newly added element*/ targetPipe->qh->dWord1Qh = td->dWord0Td; DMA_FLUSH(targetPipe->qh, sizeof(USB_UHCD_QH)); } }/* End of else */ /* Link the list of TDs to the qHead - End */ /* * Release the semaphore as the critical section is over. */ usbUhcdLeaveCritical(pHCDData); }/* End of if(purb->pPipe->uPipeType != PIPE_ISOCHRONOUS) */ /* Isochronous transfer request */ else { /* If Isochronous the pUrb->pTransferSpecificData contains * the Isoc packets */ OS_LOG_MESSAGE_MEDIUM(UHCD,"Isochronous transfer\n",0,0,0,0); if(pUrb->pTransferBuffer) USER_FLUSH(pUrb->pTransferBuffer, pUrb->uTransferLength); /* Swap the buffer data */ if ( pUrb->pTransferBuffer != NULL) USB_UHCD_SWAP_BUFDATA( uBusIndex, pUrb->pTransferBuffer, pUrb->uTransferLength); /* Allocate memory for the isochronous request block */ iReqQ = (USB_UHCD_ISO_REQUEST_QUEUE*) \ OS_MALLOC(sizeof (USB_UHCD_ISO_REQUEST_QUEUE)); /* Check if memory allocation is successful */ if (NULL == iReqQ) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Memory allocation Unsuccessful\n",0,0,0,0); return USBHST_FAILURE; } /* Fill the request block with 0s */ OS_MEMSET(iReqQ, 0, sizeof(USB_UHCD_ISO_REQUEST_QUEUE)); iReqQ->next = NULL; /* For Isoc the pUrb->uNumberOfPackets field contains the number * of Isoc Tds to be made */ maxNumOfItd = pUrb->uNumberOfPackets; /* * Only a maximum of 1024 * isochronous TDs can be accomocated in the list */ if (USB_UHCD_PERIODIC_LIST_WINDOW_SIZE < maxNumOfItd) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Window size exceeded \n",0,0,0,0); OS_FREE(iReqQ); return(USBHST_FAILURE); } /* Enter the critical section */ usbUhcdEnterCritical(pHCDData); /* * Get the current HC's frame number * Use it for queueing */ usbUhcdGetFrameNumber(uBusIndex, &frameNum); frameNum = frameNum & 0x3FF; /* Check if the request is to be serviced AS_SOON_AS_POSSIBLE */ if (USBHST_START_ISOCHRONOUS_TRANSFER_ASAP == (pUrb->uTransferFlags & USBHST_START_ISOCHRONOUS_TRANSFER_ASAP)) {#if 0 OS_LOG_MESSAGE_MEDIUM(UHCD,"If request is ASAP\n",0,0,0,0); if (targetPipe->lastIndexAllocated >frameNum) { /* Check for the end conditions */ /* Update the start Index to the next lastIndexAllocated */ startIndex = targetPipe->lastIndexAllocated + 1; } else if (targetPipe->lastIndexAllocated == frameNum) { /* Update the start Index to the next frameNumber */ startIndex = frameNum + USB_UHCD_PERIODIC_LIST_MODIFICATION_MARGIN; } /* Check if there is a rollover */ else if ((targetPipe->uLastStartIndex > targetPipe->lastIndexAllocated) && (frameNum > targetPipe->lastIndexAllocated)) { startIndex = targetPipe->lastIndexAllocated + 1; } else { /* Update the start Index to the next frameNumber */ startIndex = frameNum + USB_UHCD_PERIODIC_LIST_MODIFICATION_MARGIN; }#else BOOLEAN rollover= FALSE; if (targetPipe->uLastStartIndex > targetPipe->lastIndexAllocated) rollover = TRUE; if ( !rollover ) { if ((targetPipe->uLastStartIndex == 0) && (targetPipe->lastIndexAllocated ==0) ) startIndex = frameNum + USB_UHCD_PERIODIC_LIST_MODIFICATION_MARGIN; else if ((frameNum >= targetPipe->uLastStartIndex) && (frameNum <=targetPipe->lastIndexAllocated)) startIndex = targetPipe->lastIndexAllocated + 1; else startIndex = frameNum + USB_UHCD_PERIODIC_LIST_MODIFICATION_MARGIN; } else { if (((frameNum >=targetPipe->uLastStartIndex) && (frameNum <= 1023)) || ( (frameNum <= targetPipe->lastIndexAllocated) )) startIndex = targetPipe->lastIndexAllocated + 1; else startIndex = frameNum + USB_UHCD_PERIODIC_LIST_MODIFICATION_MARGIN; } #endif /* To handle roll over */ if (startIndex > 1023) { startIndex -= 1024; } } /* End of if(purb->uTransferFlags == AS_SOON_AS_POSSIBLE) */ /* The request is to be serviced in the specific frame number */ else { OS_LOG_MESSAGE_MEDIUM(UHCD,"Request is in specific frame no\n",0,0,0,0); /* Update the start Index to the startindex provided by the urb */ startIndex = pUrb->uStartFrame; if (startIndex > 1023) { OS_LOG_MESSAGE_MEDIUM(UHCD," Urb Start Frame greater that 1023",0,0,0,0); OS_FREE(iReqQ); usbUhcdLeaveCritical(pHCDData); return(USBHST_BAD_START_OF_FRAME); } } /* * Check whether the transfer can be supported based on the available * isochronous frame window. * * NOTE: The following algorithm is used for validating whether the * transfer can be supported within the isochronous frame window. * * a) Starting frame number of the new transfer should be greater * than ending frame number for the last queued transfer. * * b) If condition (a) is FALSE, the following condition should be * met. * * Starting frame number of the new transfer is less than the * ending frame number of the last queued transfer. * * (AND) * * Starting frame number of the new transfer is less than the * current SOF (hardware frame number). * * c) If conditions (a) and (b) are not met, the transfer cannot * be supported. * * d) Ending frame number of the transfer is greater than the * the current SOF * * (OR) * * Ending frame number of the transfer is less than the current * SOF * * e) If condition ((a) AND (d)) or ((b) AND (d2)) are met the transfer * can be supported. If not, the transfer cannot be supported. */ /* * Get the current HC's frame number * Use it for queueing */ /*usbUhcdGetFrameNumber(uBusIndex, &frameNum); frameNum = frameNum & 0x3FF;*/ /* Current frame starts after the last allocated index */ currentReqStartFrame = startIndex; /* Add the number of tds to the currentReqStartFrame to get the End frame */ currentReqEndFrame = currentReqStartFrame + maxNumOfItd; /* To handle rounding off */ if (currentReqEndFrame > 1023) { OS_LOG_MESSAGE_MEDIUM(UHCD,"currentReqEndFrame > 1023\n",0,0,0,0); currentReqEndFrame -= 1024; }#if 0 /* Check for the bad SOF */ if (!(((currentReqStartFrame > targetPipe->lastIndexAllocated ) && ((currentReqEndFrame > frameNum)||(currentReqEndFrame < frameNum))) || ((currentReqStartFrame < frameNum ) && (currentReqEndFrame < frameNum))) ) { OS_LOG_MESSAGE_HIGH(UHCD," Bad start of frame condition ",0,0,0,0); OS_FREE(iReqQ); usbUhcdLeaveCritical(pHCDData); return(USBHST_BAD_START_OF_FRAME); }#endif targetPipe->uLastStartIndex = currentReqStartFrame; /* Copy the URB pointer into the isochronous queue element */ iReqQ->pUrb = pUrb; /* Update the starting index of the transfer */ iReqQ->startIndex = startIndex; /* store the pipe */ iReqQ->pipe = targetPipe; /* Update the bandwidth required */ iReqQ->bw = bwReqd; /* The toggle bit is always 0 for isochronous */ toggle = 0; /* Call the function to create the TDs needed for the transfer */ if (usbUhcdMakeIsocTds( uBusIndex, &iReqQ->head, &iReqQ->tail, pUrb, &toggle, targetPipe) == FALSE) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Make TD failed\n",0,0,0,0); /* Free the isoc request */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -