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

📄 pci.c

📁 MIPS YAMON, a famous monitor inc. source, make file and PDF manuals.
💻 C
📖 第 1 页 / 共 3 页
字号:
                return TRUE;	    }	}    }    return FALSE;}/************************************************************************ * *                          pci_display *  Description : *  ------------- * *  Display devices detected during autodetect and display the  *  autoconfiguration data (memory space and IO space allocations) * *  Return values : *  --------------- * *  None * ************************************************************************/voidpci_display(void){    t_pci_cfg_dev *dev;    t_pci_bar     *bar;    UINT32	  i, t;    char	  msg[200];    UINT32	  freq_kHz;    char	  *known_vendor, *known_device;    UINT8	  slotnum;    /* Determine bus frequency */    SYSCON_read(        SYSCON_BOARD_PCI_FREQ_KHZ_ID,	(void *)&freq_kHz,	sizeof(UINT32) );    strcpy( msg , "PCI bus frequency = " );    pci_busfreq_string( &msg[strlen(msg)], freq_kHz );    if( SHELL_PUTS( msg ) ) return;        if( SHELL_PUTS( "\n\nPCI devices:\n" ) ) return;    sprintf( msg, "Bus count = %d, Device count = %d\n",	          bus_count, dev_count );    if( SHELL_PUTS( msg ) ) return;    for( i=0; i<dev_count; i++ )    {	if( SHELL_PUTC( '\n' ) )		return;        dev = &dev_data[i];	SEARCH_KNOWN( dev, t )        if( t != known_devs_count )	{	    known_vendor = known_devs[t].vendor;	    known_device = known_devs[t].device;	}	else	{	    known_vendor = NULL;	    known_device = NULL;	}	sprintf( msg, "Bus = 0x%02x, Dev = 0x%02x", dev->bus, dev->dev );        if(SHELL_PUTS( msg ) ) return;	if( (dev->bus == PCI_BUS_LOCAL) && 	    arch_pci_slot( dev->dev, &slotnum ) )	{	    sprintf( msg, " (PCI slot %hd)", slotnum );	    if(SHELL_PUTS( msg )) return;	}	sprintf( msg, ", Function = 0x%02x", dev->function );        if(SHELL_PUTS( msg ) ) return;	if( dev->alloc_err )	{	    if(SHELL_PUTS( "  (NOT CONFIGURED)" ) ) return;	}	sprintf( msg, "\nVendor Id = 0x%04x", dev->vendorid );        if(SHELL_PUTS( msg ) ) return;	if( known_vendor )	{	    sprintf( msg, " (%s), Dev ID = 0x%04x (%s)\n", 		     known_vendor, dev->devid, known_device );	}		     		      	else	{	    sprintf( msg, ", Dev ID = 0x%04x\n", dev->devid );	}        if(SHELL_PUTS( msg )) return;	sprintf( msg, " Min Gnt = 0x%02x, Max Lat = 0x%02x, Lat Tim = 0x%02x\n",		 dev->min_gnt, dev->max_lat, dev->lat_tim );         if( SHELL_PUTS( msg ) ) return;		sprintf( msg, " Int Pin = " );	switch( dev->intpin )	{	  case PCI_MMII_INTPIN_A :	    strcat( msg, "A" ); break;	  case PCI_MMII_INTPIN_B :	    strcat( msg, "B" ); break;	  case PCI_MMII_INTPIN_C :	    strcat( msg, "C" ); break;	  case PCI_MMII_INTPIN_D :	    strcat( msg, "D" ); break;	  default :	    strcat( msg, "None" ); break;	}        if( SHELL_PUTS( msg ) ) return;	if( dev->intline == PCI_MMII_INTLINE_NONE )	{	    strcpy( msg, ", Int Line = None\n" );	}	else	{	    sprintf( msg, ", Int Line = 0x%02x\n", dev->intline );	}        if( SHELL_PUTS( msg ) ) return;	sprintf( msg, " BAR count = 0x%02x\n", dev->bar_count );	if( SHELL_PUTS( msg ) ) return;	for( t=0; t<dev->bar_count; t++ )	{	    bar = &dev->bar[t];	    if(SHELL_PUTS( ( bar->io == 1 ) ? "  IO: " : "  MEM:" )) return;	    sprintf( msg, " Pos = 0x%02x", bar->pos );	    if( SHELL_PUTS( msg ) ) return;	    if (!dev->alloc_err)	    {		sprintf( msg, ", Base(CPU/PCI) = 0x%08x/0x%08x",		     bar->start + (bar->io ? pci_io_offset : pci_mem_offset),		     bar->start );		if( SHELL_PUTS( msg ) ) return;	    }	    sprintf( msg, ", Size = 0x%08x\n", bar->size );	    if( SHELL_PUTS( msg ) ) return;	}    }}/************************************************************************ * *                          pci_busfreq_string *  Description : *  ------------- * *  Format string containing PCI bus freqency in format xx.yy MHz * *  Return values : *  --------------- * *  None * ************************************************************************/voidpci_busfreq_string(    char   *msg,    UINT32 freq_kHz ){    UINT32 freq_MHz = freq_kHz/1000;    sprintf( msg, "%d MHz", freq_MHz );        /* Calc remaining kHz */    freq_kHz -= freq_MHz*1000;        if( freq_kHz )    {        /* Adjust accuracy (e.g. 33330 kHz => 33.33 MHz, not 33.330 MHz) */        while( (freq_kHz % 10) == 0 )            freq_kHz /= 10;	sprintf( &msg[strlen(msg)-4], ".%d MHz", freq_kHz );    }}/************************************************************************ * *                          pci_check_range *  Description : *  ------------- * *  Validate PCI memory range * *  Return values : *  --------------- * *  OK    	    : Range OK *  ERROR_PCI_RANGE : Range not OK * ************************************************************************/UINT32pci_check_range(     UINT32 addr,			/* Start of range		*/    UINT32 size,			/* Size of range		*/    UINT32 *mask )			/* Mask corresponding to range	*/{    UINT32 n;    /* Calc mask for bank size register ('1' at all don't care positions) */    *mask = size-1;    /* Check that address is naturally aligned */    if( addr != (addr & ~(*mask)) )        return ERROR_PCI_RANGE;    return OK;}/************************************************************************ *  Implementation : Static functions ************************************************************************//************************************************************************ *                          detect_devices ************************************************************************/static UINT32detect_devices(     UINT32 maxbus,    UINT32 maxdev ){    UINT32 bus, dev, func;    UINT32 rc;        dev_count = 0;    bus_count = 1;	/* The local bus */    for( bus = 0; (bus < bus_count) && (bus < maxbus); bus++ )    {        for( dev = 0; dev <= 31; dev++ )        {	    /* Read function 0 */	    rc = query_dev( bus, dev, 0, &dev_data[dev_count], maxbus );	    if( rc == OK )	    {	        /* Found device */	        dev_count++;		if( dev_count == maxdev )		    return OK;	        if( dev_data[dev_count-1].multi )		{		    /* Multi function device */		    for( func = 1; func < PCI_MAX_FUNC; func++ )		    {		        rc = query_dev( bus, dev, func, &dev_data[dev_count], maxbus );			if( rc == OK )			    dev_count++;			if( dev_count == maxdev )			    return OK;		    }		}	    }	}    }    return OK;}/************************************************************************ *                          query_dev ************************************************************************/static UINT32query_dev(     UINT32        bus,                  /* Bus number                   */    UINT32        devnum,		/* Device number		*/    UINT32	  function,		/* Device function		*/    t_pci_cfg_dev *dev,			/* Device data			*/    UINT32	  maxbus ){    UINT32    data;    t_pci_bar *bar;    UINT32    pci_bar_max;    UINT32    rc;    UINT32    i;    UINT8     type;    /* Read configuration data common to all PCI devices */    rc = pci_config_read32( bus, devnum, function, PCI_ID, &data );    if( rc != OK ) return rc;    if(data == 0xffffffff) return ERROR_PCI_ABORT;        dev->devid    = (data & PCI_ID_DEVID_MSK)    >> PCI_ID_DEVID_SHF;    dev->vendorid = (data & PCI_ID_VENDORID_MSK) >> PCI_ID_VENDORID_SHF;        rc = pci_config_read32( bus, devnum, function, PCI_SC, &data );    if( rc != OK ) return rc;    dev->status  = (data & PCI_SC_STATUS_MSK)  >> PCI_SC_STATUS_SHF;    rc = pci_config_read32( bus, devnum, function, PCI_BHLC, &data );    if( rc != OK ) return rc;    dev->ht    = (data & PCI_BHLC_HT_MSK)    >> PCI_BHLC_HT_SHF;    if( dev->ht > PCI_HEADERTYPE_MAX )    {        /* Unknown header type, ignore device */        return ERROR_PCI_ABORT;    }    dev->multi = arch_pci_multi( dev, data );    rc = pci_config_read32( bus, devnum, function, PCI_MMII, &data );    if( rc != OK ) return rc;    dev->intpin  = (data & PCI_MMII_INTPIN_MSK) >> PCI_MMII_INTPIN_SHF;    /* max_lat and min_gnt actually only valid for header type 0 dev */    dev->max_lat = (data & PCI_MMII_MAXLAT_MSK) >> PCI_MMII_MAXLAT_SHF;    dev->min_gnt = (data & PCI_MMII_MINGNT_MSK) >> PCI_MMII_MINGNT_SHF;    /* Read BARs */    dev->bar_count = 0;    pci_bar_max = DEV_PPB(dev) ? PCI_BAR_MAX_PPB : PCI_BAR_MAX;    for(i = PCI_BAR_MIN; i <= pci_bar_max; i+= sizeof(UINT32) )    {	rc = pci_config_write32( bus, devnum, function, i, 0xFFFFFFFF );        if( rc != OK )            return rc;	rc = pci_config_read32( bus, devnum, function, i, &data );        if( rc != OK )             return rc;	    	if( data != 0 )	{	    bar = &dev->bar[dev->bar_count];			    bar->pos = i;		    bar->io  = (data & PCI_BAR_IO_MSK) >> PCI_BAR_IO_SHF;	    if(bar->io)	    {	        bar->size  = data & (1 + (~data | ~PCI_BAR_IOSIZE_MSK));		dev->bar_count++;	    }	    else	    {		type = (data & PCI_BAR_TYPE_MSK) >> PCI_BAR_TYPE_SHF;		if( type == PCI_BAR_TYPE_64 )		{		    /*  64 bit addressing. Ignore bar and increase		     *  loop counter since bar field is 2 words 		     */			 		    i += sizeof(UINT32);		}		else if( type != PCI_BAR_TYPE_RSVD )		{	            bar->size  = data & (1 + (~data | ~PCI_BAR_MEMSIZE_MSK));		    bar->prefetch = (data & PCI_BAR_PREFETCH_MSK) >> 		   	             PCI_BAR_PREFETCH_SHF;		    dev->bar_count++;		}	    }        }    }    dev->bus      = bus;    dev->dev      = devnum;    dev->function = function;    if( DEV_PPB(dev) )    {        /* PCI-PCI Bridge */	if( sys_platform == PRODUCT_ATLASA_ID && 	    bus == PCI_BUS_LOCAL &&	    devnum == PCI_IDSEL2DEVNUM(ATLAS_IDSEL_21150) &&	    !arch_pci_system_slot() )	{	    /* The CompactPCI bridge on Atlas is NOT connected to back plane */	    bus_count++;	    return OK;	}	/* Configure bus numbers */	data = (bus         << PCI_SSSP_PBN_SHF)    |	       (bus_count++ << PCI_SSSP_SECBN_SHF ) |	       ((maxbus-1)  << PCI_SSSP_SUBBN_SHF);        rc = pci_config_write32( bus, devnum, function, PCI_SSSP, data );        if( rc != OK ) return rc;	    	if( bus == PCI_BUS_LOCAL &&	    devnum == PCI_IDSEL2DEVNUM(ATLAS_IDSEL_21150) &&	    arch_pci_system_slot() )	{   	    /* Enable backplane clocks (TBD : Use #define for 0x68) */	    rc = pci_config_write32( bus, devnum, function, 0x68, 0 ); 	    if( rc != OK ) return rc;	    	    /* Pause for a while to allow target devices on PCI 	     * backplane to boot.	     * This is necessary when interfacing to the RIO	     * board, which uses an i960 as PCI South bridge since	     * the i960 needs to boot.	     */	    DISP_STR( "PCI WAIT" );	    sys_wait_ms( 1000 );	    DISP_STR( "PCI" );	}    }    /* Everything OK */    return OK;}/************************************************************************ *                          config_system ************************************************************************/static UINT32config_system(     UINT32 freemem_start,		/* First valid mem address	*/    UINT32 freemem_end, 		/* First non valid mem address	*/    UINT32 freeio_start,		/* First valid IO address	*/    UINT32 freeio_end,			/* First non valid IO address	*/    UINT32 maxbus ){    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];	for( t=0; t<dev->bar_count; t++ )        {		    if( !fixed_memory_alloc( dev, t ) )	    {	        /* Normal configurable BAR */	        bar        = &dev->bar[t];	        bar->fixed = FALSE;	        /* Insert in ordered linked list */	        pptr = bar->io ?		           &bus->io_largest_ptr :		           &bus->mem_largest_ptr;                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];        /* Fixed BARs */

⌨️ 快捷键说明

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