📄 pci.c
字号:
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 + -