📄 hcd_1161.c
字号:
if (uData == YES) uHostConfigData |= HC_RH_DESCRIPTORA_OCPM; /* Set the power on to power good time */ uHostConfigData |= ((POWER_ON_TO_POWER_GOOD_TIME / 2) << 24); /* Divided by 2, then move it into position */ fnvIsp1161HcorWrite(ohci,uHcRhDescriptorA, uHostConfigData); /* Set the global power to all the ports */ uHostConfigData = RH_HS_LPSC; fnvIsp1161HcorWrite(ohci,uHcRhStatus, uHostConfigData); /* Wait till the POWER ON TO POWER GOOD time */ mdelay(POWER_ON_TO_POWER_GOOD_TIME); /* Set the HcRhDescriptorB register (13h) */ uHostConfigData = DEVICE_REMOVABLE; if (PORT_POWER_SWITCHING == YES) uHostConfigData |= 0xFFFF0000; /* Set PPCM bits 31..16 to disable gang-mode power switching */ fnvIsp1161HcorWrite(ohci,uHcRhDescriptorB, uHostConfigData);} /* End of fnvHcRhPower() *//*--------------------------------------------------------------* * 1161 Host Controller Initialization *--------------------------------------------------------------*/int fnuHci1161HostInit(ohci_t *ohci){ struct usb_device *usb_dev; /* 1. ISP1161 Host Controller Extended Registers Initialization */ fnvHcHardwareConfig(ohci, ohci->irq); fnvHcIntEnable(ohci); /* Set the HC ATL buffer length */ fnvIsp1161HcWrite(REG_ITL_BUFLEN, ITL_BUFF_LENGTH); /* Set the HC ATL buffer length */ fnvIsp1161HcWrite(REG_ATL_BUFLEN, ATL_BUFF_LENGTH); /* 2. ISP1161 Host Controller Operational Registers Initialization */ pstDoneHead_hcd = 0; /* Done head */ aIsoTdMapBuffer[0].byStatus = 0; aIsoTdMapBuffer[1].byStatus = 0; aIsoTdMapBuffer[0].uFrameNumber = INVALID_FRAME_NUMBER; aIsoTdMapBuffer[1].uFrameNumber = INVALID_FRAME_NUMBER; fnvHcControlInit(ohci); /* Initialize HcControl register */ ohci->disabled = 0; fnvHcInterruptInit(ohci/*, stHostCallback*/); /* Initialize HcInterruptEnable/Disable registers */ fnvHcFmIntervalInit(ohci); /* Initialize HcFmInterval Register */ fnvHcRhPower(ohci); /* Root hub port power switching mode */ ohci->rh.devnum = 0; /* No root hub yet */ ohci->p_ed_controlhead = NULL; /* Initialize control & bulk list heads */ ohci->p_ed_bulkhead = NULL; /* Allocate data structure for root hub */ usb_dev = usb_alloc_dev ( NULL, ohci->bus) ; if( !usb_dev ) { ohci->disabled = 1; return -ENOMEM; } ohci->bus->root_hub = usb_dev; /* Connect the virtual hub to the usb bus, host stack will do all the enumeration, configuration etc.. */ usb_connect (usb_dev); if(usb_new_device(usb_dev) != 0) { usb_free_dev(usb_dev); ohci->disabled = 1; return -ENODEV; } return 0;} /* End of fnuHci1161HostInit() *//*--------------------------------------------------------------* * 1161 HC Interrupt Functions * *--------------------------------------------------------------*//*--------------------------------------------------------------* * 1161 Host Controller Interrupt function * *--------------------------------------------------------------*/static void fnvHci1161IrqHandler (int irq, void * __ohci, struct pt_regs * r){ ohci_t *ohci = (ohci_t*)__ohci; ULONG uIntStatus; /* Int. status of the HCOR */ ULONG uEnabledHcorIntStatus; /* HcInterruptStatus HCOR anded with HcInterruptEnable */ ULONG uIntExtStatus; /* Int. status of the ISP1161 ext. int register */ ULONG uData1, uData2; ohci->in_isr = 1; fnvIsp1161HcRead(REG_IRQ, &uData1); fnvIsp1161HcRead(REG_IRQ_MASK, &uData2); uIntExtStatus = uData1 & uData2; /* Get the true int. status */ /* uIntExtStatus contains enabled interrupt status bits read from the */ /* ISP1161 HC ext. register REG_IRQ (0x24) */ /* If the IRQ is not from ISP1161 HC, don't do anything. */ if (uIntExtStatus == 0) { /* ISP1161 int. status in HC extended register */ ohci->in_isr = 0; return; } /* Get the enabled HcInterruptStatus HCOR */ fnvIsp1161HcorRead(ohci,uHcInterruptStatus, &uData1); /* Read the HCOR int. status */ fnvIsp1161HcorRead(ohci,uHcInterruptEnable, &uData2); /* Read the HCOR int. enable status */ uIntStatus = uData1 & uData2; /* Get the true int. status */ uEnabledHcorIntStatus = uData1 & uData2; /*******************************/ /* Process SOFITLInt IRQ */ /* SOF and ITL interrupts */ /*******************************/ if (uIntExtStatus & SOF_ITL_INT) { /* SOFITL Int. service */ fnvProcessSofItlInt(ohci); /* Clear SOFITLInt IRQ of REG_IRQ register of ISP1161 ext regsiter */ uData1 = SOF_ITL_INT; fnvIsp1161HcWrite(REG_IRQ, uData1); } /* if SOF_ITL_INT */ /*********************************************/ /* Process ATL_INT */ /* ALT Done */ /*********************************************/ if (uIntExtStatus & ATL_INT) { /* fnvProcessOprInt(pstHostNode); */ /* Clear ATL_INT IRQ */ uData1 = ATL_INT; fnvIsp1161HcWrite(REG_IRQ, uData1); } /* if ATL_INT */ /*********************************************/ /* Process EOT_INT */ /* End of Transfer */ /*********************************************/ if (uIntExtStatus & EOT_INT) { /* fnvProcessOprInt(pstHostNode); */ /* Clear EOT_INT IRQ */ uData1 = EOT_INT; fnvIsp1161HcWrite(REG_IRQ, uData1); } /* if EOT_INT */ /*********************************************/ /* Process OPR_INT */ /* HC operational register HcInterruptStatus */ /*********************************************/ if (uIntExtStatus & OPR_INT) { /*fnvProcessOprInt(pstHostNode, uEnabledHcorIntStatus);*/ /* Clear OPR_INT IRQ */ uData1 = OPR_INT; fnvIsp1161HcWrite(REG_IRQ, uData1); } /* if OPR_INT */ /*********************************************/ /* Process HC_SUSPEND_INT */ /* HC Suspended */ /*********************************************/ if (uIntExtStatus & HC_SUSPEND_INT) { /* fnvProcessOprInt(pstHostNode); */ /* Clear HC_SUSPEND_INT IRQ */ uData1 = HC_SUSPEND_INT; fnvIsp1161HcWrite(REG_IRQ, uData1); } /* if HC_SUSPEND_INT */ /*********************************************/ /* Process HC_RESUME_INT */ /* HC Resume int. */ /*********************************************/ if (uIntExtStatus & HC_RESUME_INT) { /* fnvProcessOprInt(pstHostNode); */ /* Clear HC_RESUME_INT IRQ */ uData1 = HC_RESUME_INT; fnvIsp1161HcWrite(REG_IRQ, uData1); } /* if HC_RESUME_INT */ ohci->in_isr = 0;} /* End of fnvHci1161IrqHandler() */__u8 cc6_flag = 0;__u16 cc65_count = 0;/*--------------------------------------------------------------* * 1161 Host Controller SOF/ITL Interrupt function * *--------------------------------------------------------------*/void fnvProcessSofItlInt(ohci_t * ohci){ __u32 uData1; __u8 byData; __u32 uFrameNumber; /* Frame number of 1161 */ __u8 * pbyHcdAtlBuff; /* HCD ATL buffer address */ ed_t * pstCurrentHcdEd; /* Pointer to the current HCD ED entry in the HCD ED pool */ td_t * pstCurrentHcdGtd; /* Pointer to the current HCD GTD entry in the HCD GTD pool */ __u32 uHcdEdIndex; /* Ed index in Interrupt ed table */ __u32 uAtlIndex; /* ATL buffer td-ptd index */ __u32 uPipeHandle; /* URB pipe handle */ __u32 uAtlByteCount; /* Atl buffer byte counter */ __u32 uLastPtd; /* number of PTD's in the buffer or last ptd */ __u32 uTotal; /* General total bytes variable */ __u32 uIndex; /* General count index */ __u8 * pbyChar; __u32 uStartPTDByteCount; __u8 * pbyData; __u32 uPhysical; __u32 uPtdCompletionCode; /* PTD completion Code */ __u32 uPhysicalHead; /* TD Head pointer of ED */ __u32 uPhysicalTail; /* TD Tail pointer of ED */ __u32 frame ; /* Even or Odd frame */ __u8 * pbyHcdItlBuff; __u32 uItlByteCount; /* ITL buffer byte counter */ isotd_map_buffer_t * pstItdMapBuffer; /* ITL map buffer pointer */ __u32 uTdFrameNumber; /* TD frmae number */ __u8 uIsoTdMapBuffSelector = 0; /* ITL0/1 buffer selector */ __u8 uItlIndex = 0; /* ITL td-ptd index */ td_tree_addr_t * pstItlTdMapBuffer; /* ITL td-ptd map buffer pointer */ __u32 uData2; td_t * pstTd; /* td pointer */ __u16 bytes; /* General no of bytes */ __u8 iso_in_flag = 0; /* Read the current frame number from HCOR uHcRmNumber */ fnvIsp1161HcorRead(ohci,uHcFmNumber, &uFrameNumber); frame = uFrameNumber & 0x1 ; pbyHcdAtlBuff = ohci->p_atl_buffer ; fnvIsp1161HcRead(REG_IRQ, &uData1); fnvIsp1161HcRead(REG_BUFF_STS, &uData2); if( uData1 & SOF_ITL_INT ) { pbyHcdItlBuff = ohci->p_itl_buffer; uIsoTdMapBuffSelector = 0;Iso_Done_Queue_Processing: pstItdMapBuffer = &(aIsoTdMapBuffer[uIsoTdMapBuffSelector]); pstItlTdMapBuffer = pstItdMapBuffer->aItlTdTreeBridge; if(pstItdMapBuffer->byStatus) { if(uFrameNumber == ((pstItdMapBuffer->uFrameNumber + 1)%0x10000)) { /* Read buffer, process & go to done */ if(pstItdMapBuffer->byStatus & 0x02) { /* ISO In ptd's exist */ uItlByteCount = pstItdMapBuffer->uByteCount ;// if( (uData2 & ISOA_BUFF_DONE) || (uData2 & ISOB_BUFF_DONE) ) { fnvIsp1161ItlRead(pbyHcdItlBuff, uItlByteCount); /* Read ITL */ uLastPtd = pstItdMapBuffer->byActiveTds; /* # of ISO TD's under progress */ pbyChar = pbyHcdItlBuff; for( uIndex = 0; uIndex < uLastPtd; uIndex++) { pstCurrentHcdGtd = (td_t*)(pstItlTdMapBuffer[uIndex].pstHcdTd); /* Td in process */ pstCurrentHcdEd = pstCurrentHcdGtd->ed ; if( pstCurrentHcdEd->hwINFO & 0x1000) { /* ISOC in PTD */ /* process completion code */ byData = pbyChar[1]; if( (byData & PTD_ACTIVE) == 0 ) { /* Copy Compeltion code from PTD */ uPtdCompletionCode = (__u32)( (byData & PTD_COMPLETION_CODE) >> 4); /* TODO do the necessary things needed for the ed/td bits */ pstCurrentHcdGtd->hwINFO &= ~HC_GTD_CC; /* Clear the original CC */ pstCurrentHcdGtd->hwINFO |= uPtdCompletionCode << 28; /* Move CC into position */ /* Forget about data toggle bit, as data toggle bit is not important for ISOC trnasfers */ /* Write the CC part of psw for the td */ /* Move data returned from device to the buffer for IN transfer */ /* Take out the PID token from PTD byte 5 */ if( uPtdCompletionCode == TD_CC_NOERROR || uPtdCompletionCode == TD_DATAUNDERRUN ) { pbyData = (__u8*) (pstCurrentHcdGtd->hwCBP+(pstCurrentHcdGtd->hwPSW[0] & 0x0FFF)) ; /* get the actual number of bytes transfered */ uTotal = ((__u32) (pbyChar[1] & PTD_ACTUAL_BYTES98) ) << 8; /* Bit 9..8 */ uTotal |= (__u32)(pbyChar[0]); /* Bit 7..0 */ /* Write the actual amount of data transfered for ISO IN trnasfers, for out it is zero */ pstCurrentHcdGtd->hwPSW[0] = uTotal & 0x07FF; memcpy(pbyData,pbyChar+8,uTotal); pstCurrentHcdGtd->hwCBP = 0; } /* (uPtdCompletionCode == 0 || == 9) */ else { pstCurrentHcdGtd->hwPSW[0] = 0; } pstCurrentHcdGtd->hwPSW[0] |= (uPtdCompletionCode << 12); } /* (byData & PTD_ACTIVE) == 0 */ } /* pstCurrentHcdEd->hwINFO & 0x1000 */ pbyChar += pstItlTdMapBuffer[uIndex].uAtlNodeLength; } /* for( uIndex = 0; uIndex < uLastPtd; uIndex++) */ } /* if( (uData2 & ISOA_BUFF_DONE) || (uData2 & ISOB_BUFF_DONE) ) */ /* move pstInDone queue to the DoneQueue */ pstTd = pstItdMapBuffer->pstIsoInDoneHead; if(pstTd) { while(pstTd->hwNextTD) pstTd = (td_t*)(pstTd->hwNextTD); pstTd->hwNextTD = (__u32)(pstDoneHead_hcd); pstDoneHead_hcd = pstItdMapBuffer->pstIsoInDoneHead; } } /* if(pstItdMapBuffer->byStatus & 0x02) */ pstItdMapBuffer->byStatus = 0; pstItdMapBuffer->uFrameNumber = INVALID_FRAME_NUMBER; pstItdMapBuffer->pstIsoInDoneHead = 0; pstItdMapBuffer->byActiveTds = 0; } else if(uFrameNumber != pstItdMapBuffer->uFrameNumber ) { /* This is a missed frame processing, move pstInDone queue to the DoneQueue */ pstTd = pstItdMapBuffer->pstIsoInDoneHead; if(pstTd) { while(pstTd->hwNextTD) { pstTd = (td_t*)(pstTd->hwNextTD); } pstTd->hwNextTD = (__u32)(pstDoneHead_hcd); pstDoneHead_hcd = pstItdMapBuffer->pstIsoInDoneHead; } pstItdMapBuffer->byStatus = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -