📄 mot82xxpci.c
字号:
pciIntEnabled|=DMA_INT_ENABLED; /* Enable Interrupts */ m8260IntEnable(INUM_PCI); }/**************************************************************** * * pciDmaTransfer - This function sets up a direct DMA transfer using * the PCI Bridge. * * STATUS pciDmaTransfer * ( * char* source, * char* destination, * UINT32 bytes, * UINT32 dmaRegNum * ) * * RETURNS : OK or ERROR * */STATUS pciDmaTransfer ( char* source, char* destination, UINT32 bytes, UINT32 dmaRegNum ) { volatile UINT32 statusReg; if (((UINT32)source & PCI_DMA_SOURCE_MASK)!=(UINT32)source) { printf("Source address not 32 byte aligned\n"); return(ERROR); } if (((UINT32)destination & PCI_DMA_DEST_MASK)!=(UINT32)destination) { printf("Destination address not 32 byte aligned\n"); return(ERROR); } if(((UINT32)bytes & PCI_DMA_MAX_BYTE_COUNT_MASK)!=bytes) { printf("Byte Count too large\n"); return(ERROR); } taskLock(); statusReg = PCI_IN_LONG ((int)PCI_DMASR(immrVal,dmaRegNum)); while ((statusReg & DMASR_CB)==DMASR_CB) statusReg = PCI_IN_LONG ((int)PCI_DMASR(immrVal,dmaRegNum)); sysPciOutLong ( PCI_DMASAR (immrVal,dmaRegNum),( (UINT32)source & PCI_DMA_SOURCE_MASK ) ); sysPciOutLong ( PCI_DMADAR (immrVal,dmaRegNum),( (UINT32)destination & PCI_DMA_DEST_MASK ) ); sysPciOutLong ( PCI_DMABCR (immrVal,dmaRegNum),( bytes & PCI_DMA_MAX_BYTE_COUNT_MASK ) ); statusReg = PCI_IN_LONG ((int)PCI_DMAMR(immrVal,dmaRegNum)); sysPciOutLong ( PCI_DMAMR (immrVal,dmaRegNum),((statusReg & DMAMR_CS_MASK)|DMAMR_CTM_DIRECT)); sysPciOutLong ( PCI_DMAMR (immrVal,dmaRegNum),statusReg | DMAMR_EOTIE | DMAMR_CS | DMAMR_CTM_DIRECT); taskUnlock(); return(OK); }/**************************************************************************** * * pciDmaHandler - This function is called from the pciMultiInterrupt handler * and handles the interrupts for the each DMA channel * * RETURNS : NONE */LOCAL void pciDmaHandler() { volatile UINT32 loop; for (loop=0;loop<NO_OF_DMA_CHANNELS;loop++) { /* Check DMA channel status register */ if ( ( PCI_IN_LONG( (int)PCI_DMASR(immrVal,loop) ) & 0x83) !=0 ) /* Call DMA Handler */ {# ifdef PCI_DMA_DEBUG logMsg("PCI DMA %x\n",loop,0,0,0,0,0);# endif /* PCI_DMA_DEBUG */ if (_func_pciDmaUserHandler[loop]!=NULL) _func_pciDmaUserHandler[loop](); sysPciOutLong(PCI_DMASR(immrVal,loop),0x00000083); } } }#endif /* INCLUDE_PCI_DMA *//**************************************************************************** * * pciMultiInterruptHandler - This function is called from the m8260IntrCtl * and it calls the specific interrupt handler for * interrupt. * * RETURNS : NONE */LOCAL void pciMultiInterruptHandler() { /* Check PCI Error/DMA/Message FIFO interrupt */ /* If to be handled go to handler, otherwise clear interrupt */ if ( (PCI_ESR_INT_SET != 0) && ( (pciIntEnabled | PCI_ERROR_INT_ENABLED ) != 0) ) /* Call PCI Error Handler */ pciErrorHandler();#ifdef INCLUDE_PCI_DMA if ( ( pciIntEnabled | DMA_INT_ENABLED ) != 0 ) pciDmaHandler();#endif /* INCLUDE_PCI_DMA */ /* TBD PCI MESSAGE HANDLING */ /* if ((MESSAGE_SR_INT_SET!=0) && (pciIntEnabled|MESSAGE_INT_ENABLED!=0)) */ /* Call Message FIFO Handler */ /* pciMessageHandler();*/}/**************************************************************************** * * pciErrorHandler - This function is called from pciMultiInterrupt handler * and handles the interrupt for PCI Errors * * RETURNS : NONE */LOCAL void pciErrorHandler() { volatile int esrRegVal; /* Check which Errors are set */ esrRegVal = PCI_IN_LONG( (int)PCI_ESR(INTERNAL_MEM_MAP_ADDR) ); if ( (esrRegVal & PCIERR_MSK_NMI)!=0) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error NMI\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.nmi++; } if ( (esrRegVal & PCIERR_MSK_IRA) != 0) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error IRA\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.ira++; } if ( (esrRegVal & PCIERR_MSK_I2O_IPQO) != 0) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error I2O_IPQO\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.i2o_ipqo++; } if ( (esrRegVal & PCIERR_MSK_I2O_OFQO ) != 0) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error I2O_OFQO\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.i2o_ofqo++; } if ( ( esrRegVal & PCIERR_MSK_PERR_WR ) != 0) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error Parity Error on write\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.perr_wr++; } if ( ( esrRegVal & PCIERR_MSK_PERR_RD )!=0) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error Parity Error on read\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.perr_rd++; } if ( ( esrRegVal & PCIERR_MSK_SERR ) != 0) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error SERR\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.serr++; } if ( ( esrRegVal & PCIERR_MSK_TAR_ABT ) != 0 ) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.tar_abt++; } if (( esrRegVal&PCIERR_MSK_NO_RSP)!=0) { # ifdef PCI_MULTI_DEBUG logMsg("PCI Error no response\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.no_rsp++; } if ( ( esrRegVal & PCIERR_MSK_DATA_PAR_RD ) != 0 ) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error data parity error on read\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.datapar_rd++; } if ( ( esrRegVal & PCIERR_MSK_DATA_PAR_WR ) != 0 ) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error data parity error on write\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.datapar_wr++; } if ( ( esrRegVal & PCIERR_MSK_ADDR_PAR ) != 0) {# ifdef PCI_MULTI_DEBUG logMsg("PCI Error address parity error\n",0,0,0,0,0,0);# endif /* PCI_MULTI_DEBUG */ pciErrorCount.addrpar++; } sysPciOutLong ( (UINT32*)PCI_ESR(INTERNAL_MEM_MAP_ADDR), 0xfff ); esrRegVal = PCI_IN_LONG ( (int)PCI_ESR( INTERNAL_MEM_MAP_ADDR ) ); }/**************************************************************************** * * pciMessageHandler - This function is called from the pciMultiInterrupt * handler and handles the interrupts for the messages. * It's not implemented at the momemt * * RETURNS : NONE */void pciMessageHandler(){ /* Clear reg for now TBD */ }#ifdef INCLUDE_SHOW_ROUTINES/**************************************************************************** * * pciErrorShow - This function can be called by the user and displays the * number and type of errors detected by the PCI bridge. * * RETURNS : NONE */void pciErrorShow () { printf("PCI Error Statistics\n"); printf("--------------------\n"); printf("Number of NMI Errors %d\n",pciErrorCount.nmi); printf("Number of IRA Errors %d\n",pciErrorCount.ira); printf("Number of I2O_IPQO Errors %d\n",pciErrorCount.i2o_ipqo); printf("Number of I2O_OFQO Errors %d\n",pciErrorCount.i2o_ofqo); printf("Number of Parity Write Errors %d\n",pciErrorCount.perr_wr); printf("Number of Parity Read Errors %d\n",pciErrorCount.perr_rd); printf("Number of SERR Errors %d\n",pciErrorCount.serr); printf("Number of Target Abort Errors %d\n",pciErrorCount.tar_abt); printf("Number of No Response Errors %d\n",pciErrorCount.no_rsp); printf("Number of Data Parity Read Errors %d\n",pciErrorCount.datapar_rd); printf("Number of Data Parity Write Errors %d\n",pciErrorCount.datapar_wr); printf("Number of Address Parity Errors %d\n",pciErrorCount.addrpar); }#endif /* INCLUDE_SHOW_ROUTINES */#ifdef PCI_BRIDGE_READ_ERRATA_WORKAROUND/************************************************************************** * * pciBridgeIdmaInit - This is called to initialize IDMA2 for the PCI * errata fix. * It Initialises the IDMA. It can be called one time * only. For any IDMA transfer used in the code * after this initialization only the source ptr * has to be changed. The dest ptr in this case * is conveniently positioned in the DPRAM and not * in the external memory in order to reduce the * access latency */void pciBridgeIdmaInit() { char *pramBuf = (char *)m82xxDpramAlignedMalloc(0x100,0x100); char *dpramBuf = (char *)m82xxDpramAlignedMalloc(0x40,0x40); char *bdBuf = (char *)m82xxDpramAlignedMalloc(0x40,0x40); /* * init bds */ idmaBd = (BD_DMA*)bdBuf; idmaBd->dstptr = (UINT32)dpramBuf; /* Destination for the idma is a one empty word location is DPRAM */ /* * init idma */ *(VUINT16*)IDMA2_BASE = (UINT16)((UINT32)pramBuf & 0xffff); pIdmaParam = (IDMA_PARAM *)pramBuf; pIdmaParam->ibase = (UINT16)((UINT32)bdBuf & 0xffff); pIdmaParam->ibdptr = (UINT16)((UINT32)bdBuf & 0xffff); pIdmaParam->dcm = DCM_DUAL_ADDR | DCM_TRANS_BUF_128 | DCM_MEM_MEM | DCM_DINC | DCM_SINC; pIdmaParam->dpr_buf = (UINT16)((UINT32)dpramBuf & 0xffff); /* DPR_BUF=64x2(DMA_WRAP)-32 */ pIdmaParam->ss_max = 0x0060; /* Steady state value from peripheral to memory 96 bytes */ pIdmaParam->sts = 0x0060; /*Transfers from peripheral is 96 bytes*/ pIdmaParam->dts = 0x0060; /*Transfer to memory is 96 bytes (60x) bursts*/ }/************************************************************** * * pciBridgeRegisterReadLong - Reads from PCI Bridge using IDMA * * UINT32 pciBridgeRegisterReadLong(int src) * * IMPUT : location to read * RETURN : 32 bit value at location * */UINT32 pciBridgeRegisterReadLong(int src) { volatile int key; UINT32 value; if ((src >= CPU_PCI_MEM_ADRS) && (src < CPU_PCI_IO_ADRS)) { key = intLock(); /* Need to make sure only one access at a time */ /* Setup buffer descriptor */ idmaBd->srcptr = (UINT32)src; idmaBd->length = 4; /* Need to set to prevent alignment issues */ /* This needs to be set each time for the valid bit */ idmaBd->cstatus = (IDMABD_INT_ENABLE | IDMABD_WRAP | IDMABD_LAST | IDMABD_DBO_BIG_ENDIAN | IDMABD_SBO_BIG_ENDIAN | IDMABD_VALID | IDMABD_DST_DONE | IDMABD_SRC_LOCAL); while (*((VUINT32*)CPCR_REG) & CPCR_FLG); /* Wait til CPCR available */ /* IDMA2 PAGE/CODE IDMA command start_idma */ *((VUINT32*)CPCR_REG) = IDMA2_PAGE_SUBBLOCK|CPCR_FLG|CPCR_START_IDMA; while (*((VUINT32*)CPCR_REG) & CPCR_FLG); /* Wait til CPCR available */ while (!((*(VUINT8*)IDSR2) & 0x1)); /* Wait for completion of IDMA */ value = sysLong(idmaBd->dstptr); /* Byte Swap */ /*Clear the IDSR2 status bit so each access waits for actual completion*/ *((VUINT8*)IDSR2) = 0x1; intUnlock(key); /* Allow access to idma */ } else { value = sysLong((int)src); /* Byte Swap */ } return (value); }/************************************************************** * * pciBridgeRegisterReadWord - Reads from PCI Bridge using IDMA * * UINT16 pciBridgeRegisterReadWord(int src) * * IMPUT : location to read * RETURN : 16 bit value at location * */UINT16 pciBridgeRegisterReadWord(int src) { volatile int key; UINT16 value; if (((UINT32)src >= CPU_PCI_MEM_ADRS) && ((UINT32)src < CPU_PCI_IO_ADRS)) { key = intLock(); /* Need to make sure only one access at a time */ /* Setup buffer descriptor */ idmaBd->srcptr = (UINT32)src; idmaBd->length = 2; /* Need to set to prevent alignment issues */ /* This needs to be set each time for the valid bit */ idmaBd->cstatus = (IDMABD_INT_ENABLE | IDMABD_WRAP | IDMABD_LAST | IDMABD_DBO_BIG_ENDIAN | IDMABD_SBO_BIG_ENDIAN | IDMABD_VALID | IDMABD_DST_DONE | IDMABD_SRC_LOCAL); while (*((VUINT32*)CPCR_REG) & CPCR_FLG); /* Wait til CPCR available */ /* IDMA2 PAGE/CODE IDMA command start_idma */ *((VUINT32*)CPCR_REG) = IDMA2_PAGE_SUBBLOCK|CPCR_FLG|CPCR_START_IDMA; while (*((VUINT32*)CPCR_REG) & CPCR_FLG); /* Wait til CPCR available */ while (!((*(VUINT8*)IDSR2) & 0x1)); /* Wait for completion of IDMA */ value = sysWord(idmaBd->dstptr); /* Byte Swap */ /*Clear the IDSR2 status bit so each access waits for actual completion*/ *((VUINT8*)IDSR2) = 0x1; intUnlock(key); /* Allow access to idma */ } else { value = sysWord((int)src); /* Byte Swap */ } return (value);}/************************************************************** * * pciBridgeRegisterReadByte - Reads from PCI Bridge using IDMA * * UINT8 pciBridgeRegisterReadByte(int src) * * IMPUT : location to read * RETURN : 8 bit value at location * */UINT8 pciBridgeRegisterReadByte(int src) { volatile int key; UINT8 value; if ((src >= CPU_PCI_MEM_ADRS) && (src < CPU_PCI_IO_ADRS)) { key = intLock(); /* Need to make sure only one access at a time */ /* Setup buffer descriptor */ idmaBd->srcptr = (UINT32)src; idmaBd->length = 1; /* Need to set to prevent alignment issues */ /* This needs to be set each time for the valid bit */ idmaBd->cstatus = (IDMABD_INT_ENABLE | IDMABD_WRAP | IDMABD_LAST | IDMABD_DBO_BIG_ENDIAN | IDMABD_SBO_BIG_ENDIAN | IDMABD_VALID | IDMABD_DST_DONE | IDMABD_SRC_LOCAL); while (*((VUINT32*)CPCR_REG) & CPCR_FLG); /* Wait til CPCR available */ /* IDMA2 PAGE/CODE IDMA command start_idma */ *((VUINT32*)CPCR_REG) = IDMA2_PAGE_SUBBLOCK|CPCR_FLG|CPCR_START_IDMA; while (*((VUINT32*)CPCR_REG) & CPCR_FLG); /* Wait til CPCR available */ while (!((*(VUINT8*)IDSR2) & 0x1)); /* Wait for completion of IDMA */ value = sysByte(idmaBd->dstptr); /*Clear the IDSR2 status bit so each access waits for actual completion*/ *((VUINT8*)IDSR2) = 0x1; intUnlock(key); /* Allow access to idma */ } else { value = sysByte((int)src); /* Byte Swap */ } return (value); }#endif /* PCI_BRIDGE_READ_ERRATA_WORKAROUND */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -