📄 hcd_1161.c
字号:
pstItdMapBuffer->uFrameNumber = INVALID_FRAME_NUMBER; pstItdMapBuffer->pstIsoInDoneHead = 0; pstItdMapBuffer->byActiveTds = 0; } } uIsoTdMapBuffSelector++; if(uIsoTdMapBuffSelector == 1) goto Iso_Done_Queue_Processing; } /* If ATL is complete, process the done-queue list */ if (uData1 & ATL_INT) { if (uData2 & ATL_BUFF_DONE) { /* Copy ATL from HC to HCD */ /* Get the number of total bytes in the ISP1161 ATL */ uAtlByteCount = tstAtlBridge[0].uAtlNodeLength; /* uAtlNodeLength field contains total number of bytes */ fnvIsp1161AtlRead(pbyHcdAtlBuff, uAtlByteCount); /* Now, pbyHcdAtlBuff[] contains the contents read from ISP1161 internal ATL buffer */ if (tstAtlBridge[0].pstHcdTd > 0) { /* tstAtlBridge[0].pstHcdTd is a reserved entry which contains index to */ /* the last PTD in the tstAtlBridge[] */ /* This is the number of Transfer Descriptors in the ATL buffer */ uLastPtd = tstAtlBridge[0].pstHcdTd; /* Last index number of HCD GTD in PTD */ pbyChar = pbyHcdAtlBuff; /* Address of the first HCD PTD buffer */ /* Process PTDs one by one */ for (uAtlIndex = 1; uAtlIndex <= uLastPtd; uAtlIndex++) { /* Get the address of the ED associated with the current PTD */ pstCurrentHcdGtd = (td_t*)(tstAtlBridge[uAtlIndex].pstHcdTd); pstCurrentHcdEd = pstCurrentHcdGtd->ed ; /* Process completion code, and toggle bit */ byData = pbyChar[1]; /* Byte 1 of PTD contains the above bits */ if ((byData & PTD_ACTIVE) == 0) { /* Test if the PTD is still active */ /* Copy completion code to GTD */ uPtdCompletionCode = (__u32) ((byData & PTD_COMPLETION_CODE) >> 4); bytes = (pbyChar[0]+((pbyChar[1]&3)<<8)); /* Get the actual bytes */ if(uPtdCompletionCode == 0x06 && cc6_flag == 0) { cc6_flag = 1; } if(uPtdCompletionCode == 0x05 && cc6_flag == 1) { cc65_count++; cc6_flag = 0;// printk("cc65_count = %d\n",cc65_count); } /* MOCK OHCI IN SOFTWARE */ /* Check if there is any transmission error (pid check fail, data toggle mismatch, crc fail, bitstuffing or dev not responding) and number of retries is not zero then process the PTD else go to transmission error processing */ if(!(--(pstCurrentHcdGtd->retry_count)) || (uPtdCompletionCode != TD_PIDCHECKFAIL && uPtdCompletionCode != TD_CC_DATATOGGLEM && uPtdCompletionCode != TD_CC_CRC && uPtdCompletionCode != TD_CC_BITSTUFFING && uPtdCompletionCode != TD_DEVNOTRESP)) { pstCurrentHcdGtd->hwINFO &= ~HC_GTD_CC; /* Clear the original CC */ pstCurrentHcdGtd->hwINFO |= uPtdCompletionCode << 28; /* Move CC into position */ /* Data Toggle */ /* Copy the data toggle from PTD to ED and TD if there is no error or if under run or over run (for IN transfers), for others it is treated as error and some error handling mechanism should be done */ if (uPtdCompletionCode == TD_CC_NOERROR || ((uPtdCompletionCode == TD_DATAOVERRUN || uPtdCompletionCode == TD_DATAUNDERRUN) && (((pbyChar[5] & PTD_DIR) >> 2) == OHCI_IN))) { /* Get the data toggle bit from PTD in ATL */ uData1 = 0; uData1 = (__u32) ((pbyChar[1] & PTD_TOGGLE) >> 2);#ifndef NO_PTD_B5_5 if(pstCurrentHcdEd->type == PIPE_INTERRUPT && bytes == 0 ) { uData1 = ( (~uData1) & 0x01); }#endif /* NO_PTD_B5_5 */ /* Set the toggle bit same as the PTD in ATL */ pstCurrentHcdGtd->hwINFO &= ~HC_GTD_TLSB; /* Clear the toggle bit */ pstCurrentHcdGtd->hwINFO |= (uData1 << 24); /* Move it into position */ pstCurrentHcdEd->swHeadP &= ~HC_ED_TOGGLE; /* clear the toggle bit in ED */ pstCurrentHcdEd->swHeadP |= (uData1 << 1); /* copy the ptd toggle bit here */ }#ifndef NO_PTD_B5_5 /* If we use Interrupt pipe NAK fix, the PTG will be done with no error for all NKAs * So if it is a NAK, then don't process it */ if(!(pstCurrentHcdEd->type == PIPE_INTERRUPT && uPtdCompletionCode == TD_CC_NOERROR && bytes == 0)) /* This will be treated as a NAK case for interrupt pipe */#endif /* NO_PTD_B5_5 */ { /*******************************/ /* Move TDs to done-queue list */ /*******************************/ pstCurrentHcdEd->hwHeadP = (pstCurrentHcdGtd->hwNextTD); /* Move the TD to the head of done queue */ pstCurrentHcdGtd->hwNextTD = (__u32)pstDoneHead_hcd; pstDoneHead_hcd = pstCurrentHcdGtd; /* Take out the PID token from PTD byte 5 */ byData = (pbyChar[5] & PTD_DIR) >> 2; /* Move data returned from device to the buffer for IN transfer */ /* The data in case of under run as well as over run is valid and we have to copy the data to td buffer */ if ((byData == OHCI_IN) && ((uPtdCompletionCode == TD_CC_NOERROR) || (uPtdCompletionCode == TD_DATAUNDERRUN ) || (uPtdCompletionCode == TD_DATAOVERRUN))) { pbyData = (__u8*) pstCurrentHcdGtd->hwCBP; /* Starting address */ /* Get the actual number of transferred bytes */ uTotal = ((__u32) (pbyChar[1] & PTD_ACTUAL_BYTES98)) << 8; /* Bit 9..8 */ uTotal |= (__u32) (pbyChar[0]); /* Bit 7..0 */ for (uIndex = 0; uIndex < uTotal; uIndex++) { pbyData[uIndex] = pbyChar[uIndex + 8]; /* PTD header is 8 byte long */ } /* for (uIndex = 0; uIndex < uTotal; uIndex++) */ } /* if (byData == OHCI_IN) */ /* Update the Current Buffer pointer. if success:: make CBP = 0 to signal that complete TD is success. if underrun/overrun, update it to the received bytes so that the application knows how many bytes are transfered */ if( uPtdCompletionCode == TD_CC_NOERROR) pstCurrentHcdGtd->hwCBP = 0; /* To signal that last byte has been transferred */ else if(byData == OHCI_IN && (uPtdCompletionCode == TD_DATAUNDERRUN || uPtdCompletionCode == TD_DATAOVERRUN) ) { pstCurrentHcdGtd->hwCBP += bytes; } /* If the buffer rounding bit is set, and its an under run case, we treat that as success */ if(uPtdCompletionCode == TD_DATAUNDERRUN && (pstCurrentHcdGtd->hwINFO & TD_R)) uPtdCompletionCode = TD_CC_NOERROR; /* For any error other than success we have to halt the End Point */ if(uPtdCompletionCode != TD_CC_NOERROR) pstCurrentHcdGtd->ed->swHeadP |= HC_ED_HALTED; } } else { /* ERROR_HANDLING_FIX:: */ /* Allt the transmission error cases are handled here. Inverse and copy the toggle bit, copy any data if present, update current buffer pointer and don't put this in done queue so that this td is scheduled for transfer again */ byData = (pbyChar[5] & PTD_DIR) >> 2; if(byData == OHCI_OUT|| (byData == OHCI_IN )) { /* Assuming SETUP tokens does not have this problem */ /* Get the data toggle bit from PTD in ATL */ uData1 = 0; uData1 = (__u32) ((pbyChar[1] & PTD_TOGGLE) >> 2); uData1 = ( (~uData1) & 0x01); /* Inverse the PTD toggle bit */ /* Set the toggle bit same as the PTD in ATL */ pstCurrentHcdGtd->hwINFO &= ~HC_GTD_TLSB; /* Clear the toggle bit */ pstCurrentHcdGtd->hwINFO |= (uData1 << 24); /* Move it into position */ pstCurrentHcdEd->swHeadP &= ~HC_ED_TOGGLE; /* Clear the ED toggle bit */ pstCurrentHcdEd->swHeadP |= (uData1 << 1); /* Move the toggle bit to ED */ /* Copy the received bytes in case of IN Transfer */ if(byData == OHCI_IN) { pbyData = (__u8*) pstCurrentHcdGtd->hwCBP; /* Starting address */ for (uIndex = 0; uIndex < bytes; uIndex++) { pbyData[uIndex] = pbyChar[uIndex + 8]; /* PTD header is 8 byte long */ } /* for (uIndex = 0; uIndex < uTotal; uIndex++) */ } pstCurrentHcdGtd->hwCBP += bytes; /* Update the current buffer pointer */ } } } /* if ((byData & PTD_ACTIVE) == 0) */ byData = pbyChar[1]; /* Byte 1 of PTD contains the PTD active bit */ if ((byData & PTD_ACTIVE)) { /* Test if the PTD is still active */ /* Get the actual number of transferred bytes */ uTotal = 0; uTotal = ((__u32) (pbyChar[1] & PTD_ACTUAL_BYTES98)) << 8; /* Bit 9..8 */ uTotal |= (__u32) (pbyChar[0]); /* Bit 7..0 */ /* Copy completion code to GTD */ uPtdCompletionCode = (__u32) ((byData & PTD_COMPLETION_CODE) >> 4); /* Set the toggle bit same as the PTD in ATL */ uData1 = 0; uData1 = (__u32) ((pbyChar[1] & PTD_TOGGLE) >> 2); /* Byte 1 contains data toggle bit */ pstCurrentHcdGtd->hwINFO &= ~HC_GTD_TLSB; /* Clear the toggle bit */ pstCurrentHcdGtd->hwINFO |= (uData1 << 24); /* Move it into position */ pstCurrentHcdEd->swHeadP &= ~HC_ED_TOGGLE; pstCurrentHcdEd->swHeadP |= (uData1 << 1); /* If the transaction is an IN transaction, and still PTD is active means we have to copy the number of bytes received to the TD buffer and then increment the current buffer pointer */ /* Take out the PID token from PTD byte 5 */ byData = (pbyChar[5] & PTD_DIR) >> 2; if ((byData == OHCI_IN) && (uPtdCompletionCode == 0)) { pbyData = (__u8*) pstCurrentHcdGtd->hwCBP; /* Starting address */ /* Get the actual number of transferred bytes */ uTotal = ((__u32) (pbyChar[1] & PTD_ACTUAL_BYTES98)) << 8; /* Bit 9..8 */ uTotal |= (__u32) (pbyChar[0]); /* Bit 7..0 */ for (uIndex = 0; uIndex < uTotal; uIndex++) { pbyData[uIndex] = pbyChar[uIndex + 8]; /* PTD is 8 byte long */ } /* for (uIndex = 0; uIndex < uTotal; uIndex++) */ } /* if (byData == OHCI_IN) */ pstCurrentHcdGtd->hwCBP += uTotal; /* Advances the pointer to next block */ } /* if ((byData & PTD_ACTIVE) == 1) */ /* Get the address of next HCD PTD buffer */ pbyChar += tstAtlBridge[uAtlIndex].uAtlNodeLength; } /* for */ } /* if (tstAtlBridge[0].pstHcdTd > 0) */ /* Clear the transfer-in-progress status bit */ fnvIsp1161HcorRead(ohci,uHcHcdControl, &uData1); fnvIsp1161HcorWrite(ohci,uHcHcdControl, (__u32) (uData1 & ~OHCI_CTRL_TIP)); } /* if ATL_BUFF_DONE */ /* CLear the ATL interrupt */ fnvIsp1161HcWrite(REG_IRQ, ATL_INT); } /* if (uData1 & ATL_INT) */ /* Process the done-queue list */ dl_done_list( ohci, dl_reverse_done_list(ohci,pstDoneHead_hcd)); pstDoneHead_hcd = 0; if (ohci->ed_rm_list[!frame] != NULL) { dl_del_list (ohci, !frame); } /* Isochronous Transfer Scheduling */ /* Check if Periodic Transfer and Isochronous transfer are enabled */// fnvIsp1161HcorRead(ohci,uHcFmNumber, &uFrameNumber); /* Select the td map buffer that is free, if none go to control tranfer */ uIsoTdMapBuffSelector = 0; if( (aIsoTdMapBuffer[uIsoTdMapBuffSelector].byStatus) && (aIsoTdMapBuffer[++uIsoTdMapBuffSelector].byStatus) ) goto Control_Transfer_Scheduling; /* Initialize variables for list scheduling */ pstItlTdMapBuffer = aIsoTdMapBuffer[uIsoTdMapBuffSelector].aItlTdTreeBridge; aIsoTdMapBuffer[uIsoTdMapBuffSelector].byActiveTds = 0; uHcdEdIndex = (uFrameNumber & 0x0000001F); pstCurrentHcdEd = ohci->ed_isohead; pstDoneHead_hcd = 0; /* Select the td map buffer that is free, if none go to control tranfer */ while( pstCurrentHcdEd != NULL ) { /* Check if this is Isochronous Data Transfer ED and Skip bit is not set for this ED */ if( (pstCurrentHcdEd->type == PIPE_ISOCHRONOUS) && ((pstCurrentHcdEd->hwINFO & OHCI_ED_SKIP) == 0) ) { uPhysicalHead = (pstCurrentHcdEd->hwHeadP); uPhysicalTail = (pstCurrentHcdEd->hwTailP); if( uPhysicalHead != uPhysicalTail ) { /* Find the td that should be sent in the next frame */ pstCurrentHcdGtd = (td_t*)uPhysicalHead; do { pstCurrentHcdGtd = (td_t*)uPhysicalHead; uTdFrameNumber = (pstCurrentHcdGtd->hwINFO & 0xFFFF); /* Compare the td frame number and current frame number */ if(uTdFrameNumber == ((uFrameNumber +1)%0x10000)) { /* Get the pipe handle */ uPipeHandle = pstCurrentHcdGtd->urb->pipe ; pstItlTdMapBuffer[uItlIndex].uPipeHandle = uPipeHandle; pstItlTdMapBuffer[uItlIndex++].pstHcdTd = (__u32)pstCurrentHcdGtd; break; } else { if( (uTdFrameNumber - uFrameNumber) <= 0 || (uTdFrameNumber - uFrameNumber) > 0xF000 ) { pstCurrentHcdGtd->hwINFO &= ~HC_GTD_CC; pstCurrentHcdGtd->hwINFO &= ((TD_CC_NOERROR) << 28); pstCurrentHcdEd->hwHeadP = (pstCurrentHcdGtd->hwNextTD); pstCurrentHcdGtd->hwNextTD = (__u32)pstDoneHead_hcd; pstDoneHead_hcd = pstCurrentHcdGtd; } else { break; } } uPhysicalHead = (pstCurrentHcdEd->hwHeadP); uPhysicalTail = (pstCurrentHcdEd->hwTailP); } while ( uPhysicalHead != uPhysicalTail); } /* uPhysicalHead != uPhysicalTail */ } /* ISO & No Skip */ pstCurrentHcdEd = (ed_t*)pstCurrentHcdEd->hwNextED ; } /* pstCurrentHcdEd != NULL */ /* If there are any ISO Td's to be sent to the TD's */ if(uItlIndex) { pbyHcdItlBuff = ohci->p_itl_buffer; uItlByteCount = 0; /* Offset of the HCD ITL buffer, starting with byte 0 */ uStartPTDByteCount = 0; /* Starting address of a new PTD */ aIsoTdMapBuffer[uIsoTdMapBuffSelector].byActiveTds = uItlIndex; aIsoTdMapBuffer[uIsoTdMapBuffSelector].pstIsoInDoneHead = 0; uLastPtd = uItlIndex; pbyChar = pbyHcdItlBuff; /* Address of the first HCD PTD buffer */ /* Construct the HCD ITL buffer */ for( uItlIndex = 0; uItlIndex < uLastPtd; uItlIndex++){ pstCurrentHcdGtd = (td_t*)(pstItlTdMapBuffer[uItlIndex].pstHcdTd); pstCurrentHcdEd = pstCurrentHcdGtd->ed; /*****************************/ /* PTD byte 0 */ /* Bit 7..0: ActualByte(7:0) */ /*****************************/ pbyHcdItlBuff[uItlByteCount++] = 0; /* Advances to byte 1 */ /************************************/ /* PTD byte 1 */ /* Bit 7..4: Completion code (3:0)) */ /* Bit 3: Active */ /* Bit 2: Toggle */ /* Bit 1..0: ActualByte(9:8) */ /************************************/ pbyHcdItlBuff[uItlByteCount] = 0; /* Clear the current contents */ /* Get the Compilation Code from Iso Ptd */ byData = (__u8)((pstCurrentHcdGtd->hwINFO & HC_GTD_CC) >> 28); pbyHcdItlBuff[uItlByteCount] |= (byData << 4); /* Move into position in PTD */ pbyHcdItlBuff[uItlByteCount++] |= PTD_ACTIVE; /* Set PTD to Active */ /* Toggle bit is always 0 for Isochronous data transfers */ /******************************/ /* PTD byte 2 */ /* Bit 7..0: MaxPackSize(7:0) */ /******************************/ pbyHcdItlBuff[uItlByteCount] = 0; /* Clear the current contents */ uData1 = (__u16) ((pstCurrentHcdEd->hwINFO & HC_ED_MPS) >> 16); pbyHcdItlBuff[uItlByteCount++] = (__u8)(uData1); /*********************************/ /* PTD byte 3 */ /* Bit 7..4: EndpointNumber(3:0) */ /* Bit 3: Last */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -