📄 usbuhcdscheduleqwaitforsignal.c
字号:
for (temptd= niRequest->head; temptd!=niRequest->tail->hNextTd;temptd= temptd->hNextTd) { DMA_INVALIDATE(temptd, sizeof(USB_UHCD_TD)); qhsTd = temptd; if((USB_UHCD_SWAP_DATA(pHCDData->busIndex, qhsTd->dWord1Td) & USBUHCD_TDCS_STS_ACTIVE) == 0 ) { actlen = USBUHCD_TDCS_ACTLEN(USB_UHCD_SWAP_DATA(pHCDData->busIndex, qhsTd->dWord1Td)); maxlen = USBUHCD_TDTOK_MAXLEN(USB_UHCD_SWAP_DATA(pHCDData->busIndex, qhsTd->dWord2Td)); /* update the total length transfered */ if(actlen != 0x7FF ) { if((niRequest->pipe->endPointType == PIPE_CONTROL) && ((temptd == niRequest->tail) || (temptd ==niRequest->head)) ) totlen+=0; /* ignore length for setup and status packet */ else totlen += actlen + 1 ; } if (actlen!= maxlen) { USB_UHCD_LOG_MESSAGE ("Current request is short & \ TD is processed\n"); lastTd = qhsTd; switch(niRequest->pipe->endPointType) { case PIPE_CONTROL: case PIPE_INTERRUPT: case PIPE_BULK: reqWithSp = 1; break; }/* End of switch () */ } /* determine if pipe has halted */ if (USB_UHCD_SWAP_DATA(pHCDData->busIndex, qhsTd->dWord1Td) & USBUHCD_TDCS_STS_STALLED) { USB_UHCD_LOG_MESSAGE ("End point halted\n"); lastTd = qhsTd; reqThatHalted = 1; } } } /* end of for loop */ /* check if there is a short packet on control pipe */ if((niRequest->pipe->endPointType == PIPE_CONTROL) && (reqWithSp ==1 )) { DMA_INVALIDATE(niRequest->tail, sizeof(USB_UHCD_TD)); /* * Check if the tail is still active * Here it cannot be checked against the ACTLENGTH != 0x7FF. * The host controller updates the ACTLENGTH to 0x7FF even on a NAK. * Check against the ACTIVE bit to find out whether the tail is * still active. */ if((USB_UHCD_SWAP_DATA(pHCDData->busIndex, niRequest->tail->dWord1Td) & USBUHCD_TDCS_STS_ACTIVE) != 0 ) { /* OUT token not sent ,schedule OUT token */ if(niRequest->pipe->outTokScheduled == FALSE) { niRequest->qh->dWord1Qh = USBUHCD_END_OF_LIST(pHCDData->busIndex); niRequest->qh->dWord1Qh = USB_UHCD_SWAP_DATA (pHCDData->busIndex, (USB_UHCD_CONVERT_TO_BUS_MEM(pHCDData->busIndex, niRequest->tail))); DMA_FLUSH(niRequest->qh, sizeof(USB_UHCD_QH)); niRequest->pipe->outTokScheduled = TRUE; } /* make niRequest point to the next request */ niRequest = niRequest->next; /* continue with other request that are queued */ continue; } } /* * Check if the the entire pipe must be deleted (or) * the entire request has been processed (or) * if pipe is halted (or) * if a bulk/interrupt req that ended with a Short Packet. */ if (niRequest->qh->markedForDeletion || ((USB_UHCD_SWAP_DATA(pHCDData->busIndex, tailTd->dWord1Td) & USBUHCD_TDCS_STS_ACTIVE ) == 0 )|| reqThatHalted || reqWithSp) { USB_UHCD_LOG_MESSAGE ("pipe is to be deleted or \ processed or halted\n"); /* If the request did not end in a short packet */ if (!reqWithSp) { USB_UHCD_LOG_MESSAGE ("Request didn't end in short packet\n"); /* Fill the status */ usbUhcdFillNonisoStatus ( USB_UHCD_SWAP_DATA(pHCDData->busIndex, tailTd->dWord1Td), &(niRequest->pUrb->nStatus), niRequest->qh->markedForDeletion, reqThatHalted); } /* Normal completion */ else { USB_UHCD_LOG_MESSAGE ("Normal completion\n"); /* fill the status */ usbUhcdFillNonisoStatus ( USB_UHCD_SWAP_DATA(pHCDData->busIndex, qhsTd->dWord1Td), &(niRequest->pUrb->nStatus), niRequest->qh->markedForDeletion, reqThatHalted); } /* Check if pipe is halted pipe for interrupt or bulk */ if (niRequest->pUrb->nStatus == USBHST_STALL_ERROR && (niRequest->pipe->endPointType == PIPE_INTERRUPT || niRequest->pipe->endPointType == PIPE_BULK) ) { USB_UHCD_LOG_MESSAGE ("Pipe is Halted\n"); /* mark qh as halted */ niRequest->qh->halted = 1; } /* If the pipe is halted, manipulate qHead's qTD ptr */ if (niRequest->pUrb->nStatus == USBHST_STALL_ERROR || reqWithSp) { USB_UHCD_LOG_MESSAGE ("Manipulate qHead's qTD\n"); /* * Before updating the link pointers, stop the HC from * accessing the pointers. This is done by setting the bit * saying that this is the last TD in the queue */ niRequest->qh->dWord1Qh = USBUHCD_END_OF_LIST( pHCDData->busIndex); /* * qhsTd not NULL indicates that there are some more TDs to be * processed by HCD. */ if (qhsTd) { USB_UHCD_LOG_MESSAGE ("More TD present\n"); /* Update the data toggle field - Start */ /* Fetch the last data toggle used */ if(lastTd) lastToggle = lastTd->toggle; else lastToggle = qhsTd->toggle; /* * Toggle the data value only if the endpoint is not * halted. If it is halted, reset the data toggle value * to zero. */ if (!niRequest->qh->halted) lastToggle = (lastToggle == 0) ? 1 : 0; else lastToggle = 0; /* Check if pipe is interrupt or bulk */ if (niRequest->pipe->endPointType == PIPE_INTERRUPT || niRequest->pipe->endPointType == PIPE_BULK) { USB_UHCD_LOG_MESSAGE ("Pipe is Interrupt or bulk\n"); /* Fix data toggle for other TDs */ for (td = niRequest->tail->hNextTd; td != NULL; td = td->hNextTd) { if ( lastToggle) td->dWord2Td |= USB_UHCD_SWAP_DATA(pHCDData->busIndex, USBUHCD_TDTOK_DATA_TOGGLE); else td->dWord2Td &= USB_UHCD_SWAP_DATA(pHCDData->busIndex, ~(USBUHCD_TDTOK_DATA_TOGGLE)); DMA_FLUSH(td, sizeof(USB_UHCD_TD)); lastToggle = (lastToggle == 0) ? 1 : 0; } } /* Update the new toggle value for the request */ niRequest->qh->toggle = lastToggle; /* Update the data toggle field - End */ }/* End of if(qhsTd) */ /* Update the Terminate bit of QH */ if (niRequest->tail->hNextTd) { niRequest->qh->dWord1Qh = USB_UHCD_SWAP_DATA (pHCDData->busIndex, (USB_UHCD_CONVERT_FROM_BUS_MEM( pHCDData->busIndex, niRequest->tail->hNextTd))) ; } DMA_FLUSH(niRequest->qh, sizeof(USB_UHCD_QH)); }/* End of if(niRequest->urb->nStatus == 4 || reqWithSp) */ /* Get the actual transfer length */ niRequest->pUrb->uTransferLength = totlen; USER_FLUSH(niRequest->pUrb, sizeof(USBHST_URB)); /* Unlink the qTDs from the qHead */ /* Check if it is the first qTD. ie directly linked to qHead */ if (niRequest->head->hPrevTd == NULL ) { USB_UHCD_LOG_MESSAGE ("First qTD\n"); /* * If the next pointer is valid, update the next pointer's * previous pointer to be NULL and this is the first TD */ if (niRequest->tail->hNextTd) { USB_UHCD_LOG_MESSAGE ("Updating pointers\n"); niRequest->tail->hNextTd->hPrevTd = NULL; } /* Update the QH's TD */ niRequest->qh->td = niRequest->tail->hNextTd; } /* * It is not the 1st QTD linked to the QH * TDs are embedded in the queue. */ else { USB_UHCD_LOG_MESSAGE ("TD are embedded in the queue\n"); /* * Update the previous pointer's next pointer to the * next request's head pointer(ie the current request's tail's * next pointer */ niRequest->head->hPrevTd->hNextTd = niRequest->tail->hNextTd; /* * If the next pointer is valid, update the next * pointer's previous pointer */ if (niRequest->tail->hNextTd) { USB_UHCD_LOG_MESSAGE ("Updating pointers\n"); niRequest->tail->hNextTd->hPrevTd = niRequest->head->hPrevTd; } }/* End of else */ /* free up all qTDs now */ usbUhcdFreeTds (niRequest->head, niRequest->tail); if (niRequest->pipe->outTokScheduled == TRUE) niRequest->pipe->outTokScheduled = FALSE; /* Create a unique name for the callback function */ sprintf(cbName, "u_nCB%d", ncbNum++); /* Create the task for the callback function */ /* cache related changes are yet to be tested */ USER_INVALIDATE(niRequest->pUrb->pTransferBuffer,niRequest->pUrb->uTransferLength); /* Swap the data */ if (niRequest->pUrb->pTransferBuffer != NULL) USB_UHCD_SWAP_BUFDATA( pHCDData->busIndex, niRequest->pUrb->pTransferBuffer, niRequest->pUrb->uTransferLength); OS_CREATE_THREAD(cbName,95, niRequest->pUrb->pfCallback, niRequest->pUrb); /* Update the non isochronous request queue pointers - Start */ /* * Check if the previous pointer is NULL. this means that * this is the head of the request queue. Update the head of the * request queue */ if (niPrevious == NULL) { USB_UHCD_LOG_MESSAGE ("Update head of the request queue\n"); pHCDData->usbUhcdNonIsoRequestQ = niRequest->next; } /* * update the next element pointers of * the non-isochronous request queue. */ else { USB_UHCD_LOG_MESSAGE ("Update the next element \ in non-iso queue\n"); niPrevious->next = niRequest->next; } /* Store the next pointer in a temporary pointer */ niTemporary = niRequest->next; /* Free the request block */ OS_FREE(niRequest); /* * Copy the temporary pointer to the niRequest pointer. This would * be used in the next iteration of the loop */ niRequest = niTemporary; } /* * End of if(niRequest->qh->marked_for_deletion || * (niRequest->tail->dword1.status & 0x80) == 0 || * reqThatHalted || * reqWithSp) */ /* The request is not yet serviced */ else { USB_UHCD_LOG_MESSAGE ("Request is not yet serviced\n"); /* Update the previous pointer */ niPrevious = niRequest; /* * Update the current queue pointer. This would * be used in the next iteration of the loop */ niRequest = niRequest->next; }/* End of else */ }/* End of while(niRequest!=NULL) */ /* Process the non-isochronous transfer request completion - End */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -