📄 pci.c
字号:
setup_fixed_memory_alloc( dev ); for( t=0; t<dev->bar_count; t++ ) { if( fixed_memory_alloc( dev, t ) ) { bar = &dev->bar[t]; bar->fixed = TRUE; /* Insert at front of list */ pptr = bar->io ? &bus->io_largest_ptr : &bus->mem_largest_ptr; 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_space( freeio_start+pci_io_offset, freeio_end+pci_io_offset, freemem_start, freemem_end ); if( rc != OK ) return rc; /* Alloc I/O address space */ rc = alloc_space( 0,0, 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_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 boolfixed_memory_alloc( t_pci_cfg_dev *dev, UINT32 bar_index ){ /* Determine whether this BAR has fixed memory mapping requirements */ UINT32 i; UINT32 pos; pos = dev->bar[bar_index].pos; for( i=0; i<bar_reqs_count; i++ ) { if( KNOWN_BAR( dev, pos, bar_reqs[i] ) ) { return TRUE; } } return FALSE;}/************************************************************************ * setup_fixed_memory_alloc ************************************************************************/static voidsetup_fixed_memory_alloc( t_pci_cfg_dev *dev ){ UINT32 i, t; /* Find all BAR requests for device */ for( i=0; i<bar_reqs_count; i++ ) { if( KNOWN_DEV( dev, bar_reqs[i] ) ) { /* Found a BAR request. * Now find BAR location in device data. */ for( t=0; (t < dev->bar_count) && (dev->bar[t].pos != bar_reqs[i].bar.pos); t++ ) { ; } if( t == dev->bar_count ) { /* Didn't find BAR (device did not report it). * Increase bar count so BAR may be setup. */ dev->bar_count++; } /* Copy fixed memory allocation requirements from requirements * array to the BAR in question. */ memcpy( &dev->bar[t], &bar_reqs[i].bar, sizeof(t_pci_bar) ); } }}/************************************************************************ * config_dev ************************************************************************/static UINT32config_dev( t_pci_cfg_dev *dev, /* Device data */ UINT32 memlimit, /* Max valid mem address */ UINT32 iolimit ) /* Max valid io address */{ UINT32 data; UINT32 rc; UINT32 i; /* clear COMMAND field - some devices lock their BARs otherwise */ if( dev->bus != PCI_BUS_LOCAL && dev->dev != PCI_IDSEL2DEVNUM(ATLAS_IDSEL_CORE) ) { pci_config_write32( dev->bus, dev->dev, dev->function, PCI_SC, 0); } /* 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 */ if (!dev->alloc_err) { 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; } } /* Setup power management (if available through extended capabilities) */ if( dev->status & PCI_STATUS_CAP_BIT ) { UINT8 cap_ptr, cap_id; /* Determine capability pointer */ rc = pci_config_read8( dev->bus, dev->dev, dev->function, PCI_CAP_PTR, &cap_ptr ); if( rc != OK ) return rc; while( (cap_ptr != 0) && ((cap_ptr & 0x3) == 0) && /* Must be 32 bit aligned */ (cap_ptr >= PCI_FIRST_NON_STANDARD) ) { /* Read capability ID */ rc = pci_config_read8( dev->bus, dev->dev, dev->function, cap_ptr + PCI_EXT_CAP_ID_OFS, &cap_id ); if( rc != OK ) return rc; if( cap_id == PCI_EXT_CAP_ID_PWR_MGMT ) { /* Found power management capability. * Set power state to D0. */ rc = pci_config_write16( dev->bus, dev->dev, dev->function, cap_ptr + PCI_EXT_CAP_PWR_MGMT_STATUS_OFS, PCI_EXT_CAP_PWR_MGMT_STATUS_D0 ); if( rc != OK ) return rc; } /* Next capability */ rc = pci_config_read8( dev->bus, dev->dev, dev->function, cap_ptr + PCI_EXT_CAP_NEXT_PTR_OFS, &cap_ptr ); if( rc != OK ) return rc; } } if( DEV_PPB(dev) ) { t_pci_cfg_bus *bus; /**** PCI-PCI Bridge ****/ /* Secondary latency timer */ rc = pci_config_write8( dev->bus, dev->dev, dev->function, PCI_LATTIM, dev->lat_tim ); if( rc != OK ) return rc; if( sys_platform == PRODUCT_ATLASA_ID && dev->bus == PCI_BUS_LOCAL && dev->dev == PCI_IDSEL2DEVNUM(ATLAS_IDSEL_21150) && !arch_pci_system_slot() ) { rc = pci_config_write32( dev->bus, dev->dev, dev->function, PCI_IO, 0x0000FFF0 ); if( rc != OK ) return rc; rc = pci_config_write32( dev->bus, dev->dev, dev->function, PCI_MEM, 0x0000FFF0 ); if( rc != OK ) return rc; rc = pci_config_write32( dev->bus, dev->dev, dev->function, PCI_PREFMEM, 0x0000FFF0 ); return rc; } /* Secondary bus data */ bus = &bus_data[dev->bus + 1]; /* 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))>>16 ); if( rc != OK ) return rc; } /* 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; if (dev->alloc_err) data = 0; rc = pci_config_write32( dev->bus, dev->dev, dev->function, PCI_SC, data ); return rc;} /************************************************************************ * alloc_space ************************************************************************/static UINT32alloc_space( UINT32 red_start, /* redpage, 0 -> IO space, !=0 -> memory space */ UINT32 red_end, UINT32 mem_start, UINT32 mem_end ){ UINT32 i; t_pci_cfg_bus *bus; t_pci_bar *bar; t_pci_bar *firstconfbar; UINT32 firstconfmem; for( i=0; i < bus_count; i++ ) { bus = &bus_data[i]; if( red_start == 0 ) { 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 */ firstconfbar = bar; firstconfmem = mem_start; for( ;bar; bar= bar->next ) { if (bar->start == 0x00000001) continue; /* Alignment requirement for BAR */ mem_start = align( mem_start, bar->size ); if (mem_start == red_start) mem_start = align( red_end, bar->size ); if( mem_start + bar->size > mem_end ) { /* PCI ressource allocation trouble. * Something has to be removed, so we remove the * biggest configurable and start over again. */ t_pci_cfg_dev *dev; int d, t; for( d=0; d<dev_count; d++ ) { dev = &dev_data[d]; if (firstconfbar < &dev->bar[0]) continue; if (firstconfbar >= &dev->bar[dev->bar_count]) continue; for( t=0; t<dev->bar_count; t++ ) { dev->bar[t].start = 0x00000001; } dev->alloc_err = TRUE; break; } pci_alloc_err = TRUE; /* start over again */ bar = firstconfbar; mem_start = firstconfmem; firstconfbar = bar->next; } else { bar->start = mem_start; mem_start += bar->size; } } } return OK;}/************************************************************************ * align ************************************************************************/static UINT32align( UINT32 addr, /* Address to be aligned */ UINT32 alignment ) /* Alignment requirement */{ return (addr + alignment - 1) & ~(alignment - 1);}/************************************************************************ * 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 + -