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

📄 pci.c

📁 MIPS下的boottloader yamon 的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    t_pci_bar     **pptr;
    t_pci_bar	  *bar;
    t_pci_cfg_dev *dev;
    t_pci_cfg_bus *bus;
    UINT32	  rc;
    UINT32	  i,t;
    UINT8	  slotnum;

    /* Default bus settings */
    for( i=0; i<maxbus; i++ )
    {	 
        bus = &bus_data[i];

        bus->fastb2b	     = TRUE;
	bus->mem_largest_ptr = NULL;
	bus->io_largest_ptr  = NULL;
	bus->prefetch	     = (i == PCI_BUS_LOCAL) ? FALSE : TRUE;
    }

    /*  There are two types of BARs : 
     *
     *  1) Configurable (normal) BARs.
     *  2) Fixed BARS, ie BARs with fixed requirements for memory mapping.
     */

    /* Sort configurable BARs for each bus based on memory requirements */
    for( i=0; i<dev_count; i++ )
    {
        dev = &dev_data[i];
	bus = &bus_data[dev->bus];

	if( !fixed_memory_alloc( dev ) )
	{
	    /* Normal configurable device */

	    for( t=0; t<dev->bar_count; t++ )
            {	
	        bar        = &dev->bar[t];
	        bar->size  = calc_mem( bar->mask );
		bar->fixed = FALSE;

		pptr = bar->io ?
		           &bus->io_largest_ptr :
			   &bus->mem_largest_ptr;

	        /* Insert in ordered linked list */
                while( (*pptr != NULL) && ((*pptr)->size > bar->size) )
	            pptr = &((*pptr)->next);

	        bar->next = *pptr;
	        *pptr     = bar;
	    }
	}
    }

    /* Add fixed BARs to front of list */
    for( i=0; i<dev_count; i++ )
    {
        dev = &dev_data[i];
	bus = &bus_data[dev->bus];

	if( fixed_memory_alloc( dev ) )
	{
	    setup_fixed_memory_alloc( dev );

	    for( t=0; t<dev->bar_count; t++ )
	    {
	        bar = &dev->bar[t];
		
		bar->fixed = TRUE;

		pptr = bar->io ?
		           &bus->io_largest_ptr :
			   &bus->mem_largest_ptr;
			   
	        /* Insert at front of list */
		bar->next = *pptr;
		*pptr     = bar;
	    }
	}
    }

    /* BAR impact on bus prefetch */
    for(i=0; i<dev_count; i++ )
    {
        dev = &dev_data[i];
	bus = &bus_data[dev->bus];

	for(t=0; t<dev->bar_count; t++)
	{
	    bar = &dev->bar[t];

            if(!bar->prefetch)
	        bus->prefetch = FALSE;
	}
    }

    /* Alloc memory address space */
    rc = alloc_mem( FALSE, freemem_start, freemem_end );
    if( rc != OK ) return rc;

    /* Alloc I/O address space    */
    rc = alloc_mem( TRUE, freeio_start, freeio_end );
    if( rc != OK ) return rc;

    /* Device impacts on bus settings and store offsets */
    for( i=0; i<dev_count; i++ )
    {
        dev = &dev_data[i];

	/* Determine device impact on bus fastb2b */
	if( !(dev->status & PCI_SC_STATUS_FBB_BIT))
	{
	    bus_data[dev->bus].fastb2b = FALSE;
	}
    }

    /* Device private settings */
    for( i=0; i<dev_count; i++ )
    {
        dev = &dev_data[i];

	dev->lat_tim = arch_pci_lattim( dev );

        /* Determine interrupt line */
	if( dev->bus == PCI_BUS_LOCAL )
	{
	    /* Is it a PCI slot */
	    if( arch_pci_slot( dev->dev, &slotnum ) )
	    {
	        dev->intline = arch_pci_slot_intline( dev->dev, dev->intpin );
	    }
	    else
	    {
	        SEARCH_KNOWN( dev, t )

	        if( t == known_devs_count )
	            return ERROR_PCI_UNKNOWN_DEVICE;
	        else
                    dev->intline = known_devs[t].intline;
            }
	}
	else
	{
	    dev->intline = arch_pci_remote_intline( dev->intpin );
	}
    }

    return OK;
}

    
/************************************************************************
 *                          fixed_memory_alloc
 ************************************************************************/
static bool
fixed_memory_alloc(
    t_pci_cfg_dev *dev )
{
    /*  Determine whether this function of a device has fixed memory
     *  mapping requirements.
     */

    UINT32 i;

    for( i=0; i<bar_reqs_count; i++ )
    {
        if( KNOWN_DEV( dev, bar_reqs[i] ) )
	{
	    return TRUE;
	}
    }

    return FALSE;
}

/************************************************************************
 *                          setup_fixed_memory_alloc
 ************************************************************************/
static void
setup_fixed_memory_alloc( 
    t_pci_cfg_dev *dev )
{
    /*  Copy fixed memory allocation requirements from requirements 
     *  array to the BAR in question.
     */

    UINT32 i;

    dev->bar_count = 0;

    for( i=0; i<bar_reqs_count; i++ )
    {
        if( KNOWN_DEV( dev, bar_reqs[i] ) )
	{
	    memcpy( &dev->bar[dev->bar_count++],
		    &bar_reqs[i].bar,
		    sizeof(t_pci_bar) );
	}
    }
}


/************************************************************************
 *                          config_dev
 ************************************************************************/
static UINT32
config_dev( 
    t_pci_cfg_dev   *dev,		/* Device data			*/
    UINT32	    memlimit,		/* Max valid mem address	*/
    UINT32	    mem_offset,		/* Offset of PCI memory range	*/
    UINT32	    iolimit,		/* Max valid io address		*/
    UINT32	    io_offset )		/* Offset of PCI IO range	*/
{
    UINT32 data;
    UINT32 rc;
    UINT32 i;

    /* Store offsets */
    dev->mem_offset = mem_offset;
    dev->io_offset  = io_offset;

    /* Setup COMMAND field */

    data = PCI_SC_CMD_IOS_BIT  |
	   PCI_SC_CMD_MS_BIT   |
	   PCI_SC_CMD_BM_BIT   |
	   PCI_SC_CMD_PERR_BIT |
	   PCI_SC_CMD_SERR_BIT;

    if( bus_data[dev->bus].fastb2b )
        data |= PCI_SC_CMD_FBB_BIT;

    rc = pci_config_write32( dev->bus, 
			     dev->dev, 
			     dev->function,
			     PCI_SC,
			     data );
    if( rc != OK ) return rc;
    	  

    /* Setup latency timer field */

    rc = pci_config_write8( dev->bus, 
			    dev->dev, 
			    dev->function,
			    PCI_LATTIM,
			    dev->lat_tim );
    if( rc != OK ) return rc;


    /* Setup Interrupt Line field */

    rc = pci_config_write8( dev->bus, 
			    dev->dev, 
			    dev->function,
			    PCI_INTLINE,
			    dev->intline );
    if( rc != OK ) return rc;


    /* Setup BARs */
    for( i=0; i<dev->bar_count; i++ )
    { 
        t_pci_bar *bar;

        bar = &dev->bar[i];

	rc = pci_config_write32( dev->bus,
		  	         dev->dev,
			         dev->function,
			         bar->pos,
			         bar->start );
        if( rc != OK ) return rc;
    }

    if( DEV_PPB(dev) )
    {
        t_pci_cfg_bus *bus;

        /**** PCI-PCI Bridge ****/

	/* Secondary bus data */
	bus = &bus_data[dev->bus + 1];

	/* Secondary latency timer */
        rc = pci_config_write8( dev->bus, 
				dev->dev, 
				dev->function, 
				PCI_LATTIM, 
				dev->lat_tim );
        if( rc != OK ) return rc;	    

	/* Secondary I/O base and limit (bit 15:12) */
	data =  ((bus->start_io & 0xF000) >> 8) << PCI_IO_BASE_SHF;
	data |= ((iolimit       & 0xF000) >> 8) << PCI_IO_LIMIT_SHF;

        rc = pci_config_write32( dev->bus, dev->dev, dev->function, PCI_IO, data );
        if( rc != OK ) return rc;	    
		
	/* I/O base and limit (bit 31:16) */
	data = ((bus->start_io >> 16) << PCI_UPPERIO_BASE_SHF) |
	       ((iolimit       >> 16) << PCI_UPPERIO_LIMIT_SHF);

        rc = pci_config_write32( dev->bus, dev->dev, dev->function, PCI_UPPERIO, data );
        if( rc != OK ) return rc;	    


        /* Secondary memory base and limit      */
	if( bus->prefetch )
	{
	    /* Disable non-prefetchable memory */
	    data = (0xFFF0 << PCI_MEM_BASE_SHF) |
		   (0x0000 << PCI_MEM_LIMIT_SHF);
	}
	else
	{
	    /* Setup non-prefetchable memory (bit 31:20) */
	    data =  ((bus->start_mem & 0xFFF00000) >> 16) << PCI_MEM_BASE_SHF;
	    data |= ((memlimit       & 0xFFF00000) >> 16) << PCI_MEM_LIMIT_SHF;	
        }
        rc = pci_config_write32( dev->bus, dev->dev, dev->function, PCI_MEM, data );
        if( rc != OK ) return rc;	    


	/* Secondary prefetchable memory base and limit */
	if( bus->prefetch )
	{
	    /* Setup prefetchable memory (bit 31:20) */
	    data =  ((bus->start_mem & 0xFFF00000) >> 16) << PCI_PREFMEM_BASE_SHF;
	    data |= ((memlimit       & 0xFFF00000) >> 16) << PCI_PREFMEM_LIMIT_SHF;	
	}
	else
	{
    	    /* Disable prefetchable memory */
	    data = (0xFFF0 << PCI_PREFMEM_BASE_SHF) |
		   (0x0000 << PCI_PREFMEM_LIMIT_SHF);
	}
        rc = pci_config_write32( dev->bus, dev->dev, dev->function, PCI_PREFMEM, data );
        if( rc != OK ) return rc;	    


	/* Bridge control */

        rc = pci_config_write16( dev->bus, 
			         dev->dev, 
			         dev->function,
			         PCI_BC,
				   PCI_BCII_BC_PERR_BIT |
				   PCI_BCII_BC_SERR_BIT |
				   PCI_BCII_BC_MA_BIT   |
				   (bus->fastb2b ? PCI_BCII_BC_FBB_BIT : 0) );
        if( rc != OK ) return rc;
    }

    return OK;
}	      


/************************************************************************
 *                          calc_mem
 ************************************************************************/
static UINT32 
calc_mem(
    UINT32 mask )
{
    UINT32 memory_required;

    if( mask == 0 )
    {
        memory_required = 0;
    }
    else
    {
        for( memory_required = 1;
	     (mask & 1) == 0;
	     memory_required <<= 1, mask >>= 1 );
    }

    return memory_required;
}


/************************************************************************
 *                          alloc_mem
 ************************************************************************/
static UINT32
alloc_mem(
    bool   io,		/* TRUE -> IO space, FALSE -> memory space	*/
    UINT32 mem_start,
    UINT32 mem_end )
{
    UINT32	  i;
    t_pci_cfg_bus *bus;
    t_pci_bar	  *bar;

    for( i=0; i < bus_count; i++ )
    {
	bus = &bus_data[i];

	if( io )
	{
            mem_start = align( mem_start, PCI_ALIGN_IO );

	    bar = bus->io_largest_ptr;

	    bus->start_io =
	        ( bar && bar->fixed ) ?
		    bar->start :
		    mem_start;
	}
	else
	{
            mem_start = align( mem_start, PCI_ALIGN_MEM );

	    bar = bus->mem_largest_ptr;

	    bus->start_mem =
	        ( bar && bar->fixed ) ?
		    bar->start :
		    mem_start;
	}

	/* First the fixed */
	while( bar && bar->fixed )
	{
	    mem_start = MAX( mem_start, bar->start + bar->size );

	    if( mem_start > mem_end )
	        return ERROR_PCI_MALLOC;

	    bar = bar->next;
	}

	/* Now the configurable */
	while( bar )
	{
	    /* Alignment requirement for BAR */
	    mem_start  =  align( mem_start, bar->size );
	    bar->start =  mem_start;
	    mem_start  += bar->size;
	    if( mem_start > mem_end )
	        return ERROR_PCI_MALLOC;
	    bar =  bar->next;
        }
    }

    return OK;
}


/************************************************************************
 *                          align
 ************************************************************************/
static UINT32
align(
    UINT32    addr,			/* Address to be aligned	*/
    UINT32    alignment )		/* Alignment requirement	*/
{
    UINT32 aligned_addr;    

    aligned_addr = addr & ~(alignment - 1);
    return (aligned_addr == addr) ? 
                aligned_addr : aligned_addr + alignment;
}


/************************************************************************
 *                          error_lookup
 ************************************************************************/
static INT32 
error_lookup( 
    t_sys_error_string *param )
{
    UINT32 index;

    index = SYSERROR_ID( param->syserror );

    if( index < sizeof(error_strings)/sizeof(char*) )
    {
        param->strings[SYSCON_ERRORMSG_IDX] = error_strings[index];
        param->count = 1;
    }
    else
        param->count = 0;

    return OK;
}

⌨️ 快捷键说明

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