⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ixp425pci.c

📁 ixp425 bsp for vxworks
💻 C
📖 第 1 页 / 共 2 页
字号:
* devices' BAR registers** RETURNS - N/A*/ LOCAL voidsysPciDeviceBarsWrite (){    UINT32 i,j;    for (i=1; i<nDevices; i++)      {        if (devices[i].error)	{            continue;	}	/*Write the BARs in PCI device i*/        for (j=0; devices[i].bar[j].size; j++) 	{ 	               pciConfigOutLong (devices[i].bus,			      devices[i].device,			      devices[i].func,			      PCI_CFG_BASE_ADDRESS_0 + (4*j),			      devices[i].bar[j].address);        } 	        pciConfigOutLong (devices[i].bus,			  devices[i].device,			  devices[i].func,			  PCI_CFG_DEV_INT_LINE,			  devices[i].irq);        pciConfigOutWord (devices[i].bus,			  devices[i].device,			  devices[i].func,			  PCI_CFG_COMMAND, 			  INITIAL_PCI_CMD);	    }}/*  * PCI controller config registers are accessed through these functions * i.e. these allow us to set up our own BARs etc. */LOCAL void crpRead (UINT32 offset, 	 UINT32* data){    UINT32 key;    key = intLock ();    REG_WRITE (PCI_CSR_BASE, PCI_CRP_OFFSET, offset);    REG_READ (PCI_CSR_BASE, PCI_CRP_RDATA_OFFSET, *data);    intUnlock (key);}LOCAL void crpWrite (UINT32 offset, 	  UINT32 data){    UINT32 key;    key = intLock ();    /*The CRP address register bit 16 indicates that we want to do a write */    REG_WRITE (PCI_CSR_BASE, PCI_CRP_OFFSET, PCI_CRP_WRITE | offset);    REG_WRITE (PCI_CSR_BASE, PCI_CRP_WDATA_OFFSET, data);    intUnlock (key);}/******************************************************************************** sysPciInit - initialise PCI bridge controller** This function initialises the PCI controller block.** RETURNS: N/A*/void sysPciInit (void){    volatile UINT32 i;    UINT32 regval;     /* Check to see if we are host, if we are PCI host we       assert reset signals and provide the clock    */    if (sysPciIsHost ())    {	sysPciGpioClockDisable();	/*Configure reset and clock gpio signals*/	sysPciGpioConfig (); 	/* assert PCI reset */	   	sysPciResetAssert ();		/* PCI spec says that we must assert reset for a minimum of 1 ms	 * we don't have any usable timers at this stage in the	 * system boot, so we busy loop for 	 * approximately twice the required minimum delay time.	 */		sysMicroDelay(PCI_MIN_RESET_ASSERT_USEC);#ifdef IXP425_PCI_GPIO_CLOCK_ON	    	/*configure PCI clock output from GPIO pin*/	sysPciGpioClockConfig (PciClock33);	/*enable the PCI clock output from GPIO pin*/	sysPciGpioClockEnable ();#endif	    	/* Disable all PCI Controller interrupts*/	REG_WRITE (PCI_CSR_BASE, PCI_INTEN_OFFSET, 0);	    	    	/*Wait at least 100us to satisfy "minimum reset assertion time from clock stable"*/	sysMicroDelay(PCI_SETTLE_USEC);		/* Negate PCI reset, i.e. take the bus out of reset*/	sysPciResetDeassert ();			/* wait a few usecs to settle the device and PCI bus */	sysMicroDelay(PCI_SETTLE_USEC);				/*Initialise interrupt callback list*/	for (i = 0; i < PCI_IRQ_LINES; i++)	{	    dllInit (&pciIntList[i]);	}	/*Initialise callback list*/	dllInit (&pciCallbackList);	/*setup BARs in controller */	crpWrite (PCI_CFG_BASE_ADDRESS_0, IXP425_PCI_BAR_0_DEFAULT);		crpWrite (PCI_CFG_BASE_ADDRESS_1, IXP425_PCI_BAR_1_DEFAULT);	crpWrite (PCI_CFG_BASE_ADDRESS_2, IXP425_PCI_BAR_2_DEFAULT);	crpWrite (PCI_CFG_BASE_ADDRESS_3, IXP425_PCI_BAR_3_DEFAULT);	crpWrite (PCI_CFG_BASE_ADDRESS_4, IXP425_PCI_BAR_4_DEFAULT);	crpWrite (PCI_CFG_BASE_ADDRESS_5, IXP425_PCI_BAR_5_DEFAULT);	/*Setup PCI-AHB and AHB-PCI address mappings*/	REG_WRITE (PCI_CSR_BASE, PCI_AHBMEMBASE_OFFSET, 		   IXP425_PCI_AHBMEMBASE_DEFAULT);	REG_WRITE (PCI_CSR_BASE,PCI_AHBIOBASE_OFFSET, 		   IXP425_PCI_AHBIOBASE_DEFAULT);	REG_WRITE (PCI_CSR_BASE,PCI_PCIMEMBASE_OFFSET, 		   IXP425_PCI_PCIMEMBASE_DEFAULT);	    }     else     {	/*if we are not the PCI bus host, we must not assert reset	  or drive the clock, and the GPIO's used for INTA#..INTD#	  when in host mode must not be claimed/configured as they	  may be used by another driver.*/	   	/* We must allow ourselves to be configured by a bus	 * master out on the PCI bus, to do this we must set	 * BAR4 to permit access to the CSRs and set the	 * Subsystem ID register	     	 * Set CSR BAR4: i.e. set base address of CSRs from PCI,	 * CSR Base Address Mask Register will setup 128 byte window.	 */		crpWrite (PCI_CFG_BASE_ADDRESS_4, IXP425_PCI_BAR_4_DEFAULT);	    }    /*Clear error bits in ISR, write 1 to clear*/    REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET , PCI_ISR_PSE | PCI_ISR_PFE 		| PCI_ISR_PPE |  PCI_ISR_AHBE );        /*reset the AHB doorbell*/    sysAhbDoorbellReset ();        /*Enable interrupts in the controller*/    REG_WRITE (PCI_CSR_BASE, PCI_INTEN_OFFSET,  	       PCI_INTEN_PSE | PCI_INTEN_PFE 	       | PCI_INTEN_PPE | PCI_INTEN_AHBE	       | PCI_INTEN_ADB | PCI_INTEN_PDB);    /*set the subsystem vendor and device ids*/    crpWrite (PCI_CFG_SUB_VENDOR_ID, IXP425_PCI_SUB_VENDOR_SYSTEM);    /*     * Set Initialise Complete in PCI Control Register: allow IXP425 to     * respond to PCI configuration cycles.     */        REG_READ (PCI_CSR_BASE, PCI_CSR_OFFSET, regval);    /*This line sets up byte lane swapping between little-endian PCI      and the big-endian AHB bus, specifies that initialisation is      complete and therefore enables the controller to respond to      transactions and also specifies that the AHB bus is operating in      big endian mode.*/    regval |= PCI_CSR_IC | PCI_CSR_ABE;#if (defined(IXP425_PCI_ENABLE_BYTE_ROUTING) || defined(VXWORKS_DATA_COHERENT))    /* Causes data byte swapping between PCI & AHB */    regval  |= PCI_CSR_PDS | PCI_CSR_ADS;#else     regval  &=   ~PCI_CSR_PDS ;         /* Force off PDS */    regval  &=   ~PCI_CSR_ADS ;         /* Force off ADS */#endif    REG_WRITE (PCI_CSR_BASE, PCI_CSR_OFFSET, regval);    /*Set up PCI Bus interface in our PCI configuration registers     * i.e. not the PCI controller configuration registers*/    /*enable memory access and bus mastering*/    crpWrite (PCI_CFG_COMMAND, PCI_CFG_CMD_MAE | PCI_CFG_CMD_BME);    pciLibInitStatus=OK;#ifdef INCLUDE_PCI_DMA    pciDmaInit();#endif    return;}/******************************************************************************** sysPciAssignAddrs - Scan PCI bus and automatically assign PCI addresses** This function scans the PCI bus to see what other devices are there. It then* sorts the BARs that it finds and assigns them addresses. It enables PCI transactions* as defined by INITIAL_PCI_CMD.** This function only has an effect if this processor is the PCI central function.** RETURNS: N/A*/voidsysPciAssignAddrs (void){    UINT32 bus, dev, func;    UINT16 data16;    UINT32 data32;       UINT8  intPin;    if (!sysPciIsHost ())    {        return;    }    /* Assign first device to ourselves */    devices[0].bus    = 0;    devices[0].device = 0;    devices[0].func   = 0;    crpRead (PCI_CFG_VENDOR_ID, &data32);    devices[0].vendor_id = data32 & IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK;    devices[0].device_id = data32 >> 16;    devices[0].error     = FALSE;    devices[0].bar[NO_BAR].size = 0;           /*dummy - required*/    nDevices = 1;    nMBars  = 0;    nIOBars = 0;    for (bus = 0; bus < IXP425_PCI_MAX_BUS; bus++ )     {        for (dev = 0; dev < IXP425_PCI_MAX_DEV; dev++ ) 	{	    for(func = 0; func < IXP425_PCI_MAX_FUNC; func++)	    {		/*Check whether a device is present*/		if (pciDeviceExists (bus, dev, func)!=TRUE)		{			    /*Clear error bits in ISR, write 1 to clear*/		    REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET , PCI_ISR_PSE 			       | PCI_ISR_PFE | PCI_ISR_PPE |  PCI_ISR_AHBE );		    continue;		}			/*A device is present, add an entry to the array*/		devices[nDevices].bus    = bus;		devices[nDevices].device = dev;		devices[nDevices].func   = func;				pciConfigInWord (bus, dev, func, PCI_CFG_VENDOR_ID, &data16);				devices[nDevices].vendor_id = data16;				pciConfigInWord (bus, dev, func, PCI_CFG_DEVICE_ID, &data16);		devices[nDevices].device_id = data16;				/*The device is functioning correctly, set error to FALSE*/		devices[nDevices].error = FALSE;		/*Figure out what BARs are on this device*/		sysPciBarInfoGet (nDevices, bus, dev, func);		/*Figure out what INTX# line the card uses*/		pciConfigInByte(bus, dev, func, PCI_CFG_DEV_INT_PIN, &intPin);				/*assign the appropriate irq line*/		if (intPin > PCI_IRQ_LINES)		{		    devices[nDevices].error = TRUE;		} 		else if (intPin != 0)		{		    /*This device uses an interrupt line*/		    devices[nDevices].irq = ixp425PciIntTranslate[dev][intPin-1];		}		nDevices++;	    } /* end for func*/	} /* end for dev */    } /* end for bus */        /* Sort BARs and set       devices[].bar[].address variables to appropriate values.*/    sortBars (memBars, nMBars);    calcBars (memBars, nMBars, IXP425_PCI_BAR_MEM_BASE);    sortBars (ioBars, nIOBars);    calcBars (ioBars, nIOBars, IXP425_PCI_BAR_IO_BASE);     /*write the BARs to the PCI devices*/    sysPciDeviceBarsWrite();    /*Clear error bits in ISR, write 1 to clear*/    REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET , PCI_ISR_PSE 	       | PCI_ISR_PFE | PCI_ISR_PPE |  PCI_ISR_AHBE );}#ifndef IXP425_PCI_SIMPLE_MAPPING/******************************************************************************** sysPciMappingAdd - configure the AHB membase register ** This function configures the next available slot in the PCI controller's AHBMEMBASE* to permit  a device on the PCI bus to access the specified SDRAM address. * This function is only available when IXP425_PCI_SIMPLE_MAPPING* is not defined, as it is the mechanism for creating dynamic (non-simple) mappings.** RETURNS: OK or ERROR if all mappings have already been used*/STATUSsysPciMappingAdd(UINT32 sdramAddress, 		 UINT32 size){    UINT32 ahbMemBaseReg;    UINT32 topEight;    UINT32 i;    if(size > MAPPING_SIZE)    {	return ERROR;    }    REG_READ (PCI_CSR_BASE, PCI_AHBMEMBASE_OFFSET, ahbMemBaseReg);    /* check whether a mapping already exists that covers the address     * and size:     * foreach mapping     * if  (base <= address) and (base+Mapping size >= address+size) then this is the mapping      *  that covers the address     */    for(i=0;i<nextPccMap;i++)    {	topEight = (ahbMemBaseReg << (i*8)) &  IXP425_PCI_TOP_BYTE_OF_LONG_MASK;	if ((topEight <= sdramAddress) && 	    ((topEight + MAPPING_SIZE) >= (sdramAddress + size)))	{	    break;	}    }    if(i<nextPccMap)    {	/*mapping exists, no need to do anything*/	return OK;    }        /*create new mapping*/    if(nextPccMap > MAX_PCC_MAP)    {	return ERROR;    }        /*get the top 8 bits of the sdram address*/    sdramAddress = sdramAddress &  IXP425_PCI_TOP_BYTE_OF_LONG_MASK;    /*blank the byte we are about to write*/    ahbMemBaseReg = ahbMemBaseReg & (~ ( IXP425_PCI_TOP_BYTE_OF_LONG_MASK >> (nextPccMap*8)));        ahbMemBaseReg = ahbMemBaseReg | (sdramAddress >> (nextPccMap*8));    REG_WRITE (PCI_CSR_BASE, PCI_AHBMEMBASE_OFFSET, ahbMemBaseReg);    nextPccMap++;    return OK;}#endif/******************************************************************************** sysPhysToPci - translate a physical address to a PCI address** This function converts a physical address to a PCI address.* It tells a PCI device what PCI address it needs to read/write* in order to access the physical address specified*** RETURNS: the PCI adddress*/void * sysPhysToPci (void *physAddr){    UINT32 topEight;    UINT32 ahbBase=0;    UINT32 ahbMemBaseReg;    void *pciAddr;    UINT32 pciBarValue=0;    UINT32 i;    /*figure out which of the regions defined by AHBMEMBASE covers physAddr*/    REG_READ (PCI_CSR_BASE, PCI_AHBMEMBASE_OFFSET, ahbMemBaseReg);     /*     * foreach mapping     * if  base <= address and base+Mapping size => address+size then this mapping      * covers the address     */    for(i=0;i<nextPccMap;i++)    {	topEight = (ahbMemBaseReg << (i*8)) &  IXP425_PCI_TOP_BYTE_OF_LONG_MASK;	if ((topEight <= (UINT32)physAddr) && 	    ((topEight + MAPPING_SIZE) >= (UINT32)physAddr))	{	    ahbBase = topEight;	    break;	}    }        if (i == nextPccMap)    {	/*no AHB base covering the specified physical address was found*/	return NULL;    }    /*the PCC bar corresponding to this AHB membase is specified by minindex*/    crpRead (PCI_CFG_BASE_ADDRESS_0 + 4*i, &pciBarValue);    /*we're only interested in the top eight bits of the BAR - these      specify the address, the rest is status info*/    pciBarValue = pciBarValue &  IXP425_PCI_TOP_BYTE_OF_LONG_MASK;        /*therefore the PCI address needed to access this AHB address is      the PCI BAR plus (the physical addres minus the AHB base)*/    pciAddr = (void*) (pciBarValue + ((UINT32)physAddr - ahbBase));    return pciAddr;}/******************************************************************************** sysPciToPhys - translate a PCI address to a physical address** This function tells the caller what Physical address they need to generate* on the AHB bus in order to access the specified PCI address on the PCI bus* There is the facility for more complex mappings of PCI space using the* pci_pcimembasereg, but we do not use them as we can access 128MB of the PCI* address space which is sufficient, so this function assumes that the* pcimembasereg is set to zero. ** RETURNS: the physical adddress*/void * sysPciToPhys (void *pciAddr){    UINT32 pciMemBaseReg;    REG_READ (PCI_CSR_BASE, PCI_PCIMEMBASE_OFFSET, pciMemBaseReg);    if( pciMemBaseReg != 0)    {	return NULL;    }    return (void*)((UINT32)pciAddr + CPU_PCI_MEM_ADRS);    } 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -