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

📄 pci.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (CYG_PCI_CFG_BAR_SPACE_MEM != (flags & CYG_PCI_CFG_BAR_SPACE_MASK))        return false;    // Check type of memory requested...    mem_type = CYG_PRI_CFG_BAR_MEM_TYPE_MASK & flags;    // We don't handle <1MB devices optimally yet.    if (CYG_PRI_CFG_BAR_MEM_TYPE_1M == mem_type        && (aligned_addr + size) > 1024*1024)        return false;    // Update the resource pointer and return values.    *base = aligned_addr+size;    *assigned_addr = aligned_addr;    dev_info->base_map[bar] = (cyg_uint32)         (aligned_addr+HAL_PCI_PHYSICAL_MEMORY_BASE) & 0xffffffff;    // If a 64bit region, store upper 32 bits in the next bar.    // Note: The CPU is not necessarily able to access the region    // linearly - it may have to do it in segments. Driver must handle that.    if (CYG_PRI_CFG_BAR_MEM_TYPE_64 == mem_type) {        dev_info->base_map[bar+1] = (cyg_uint32)             ((aligned_addr+HAL_PCI_PHYSICAL_MEMORY_BASE) >> 32) & 0xffffffff;    }        return true;}cyg_boolcyg_pci_allocate_memory( cyg_pci_device *dev_info, cyg_uint32 bar,                         CYG_PCI_ADDRESS64 *base){    cyg_uint8 bus = CYG_PCI_DEV_GET_BUS(dev_info->devid);    cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(dev_info->devid);    CYG_PCI_ADDRESS64 assigned_addr;    cyg_bool ret;    // Check that device is inactive.    if ((dev_info->command & CYG_PCI_CFG_COMMAND_ACTIVE) != 0)        return false;    // Allocate memory space for the device.    ret = cyg_pci_allocate_memory_priv(dev_info, bar, base, &assigned_addr);    if (ret) {        // Map the device and update the BAR in the dev_info structure.        cyg_pcihw_write_config_uint32(bus, devfn,                                      CYG_PCI_CFG_BAR_BASE+4*bar,                                       (cyg_uint32)                                       (assigned_addr & 0xffffffff));        cyg_pcihw_read_config_uint32(bus, devfn,                                     CYG_PCI_CFG_BAR_BASE+4*bar,                                      &dev_info->base_address[bar]);        // Handle upper 32 bits if necessary.        if (dev_info->base_size[bar] & CYG_PRI_CFG_BAR_MEM_TYPE_64) {            cyg_pcihw_write_config_uint32(bus, devfn,                                          CYG_PCI_CFG_BAR_BASE+4*(bar+1),                                           (cyg_uint32)                                           ((assigned_addr >> 32)& 0xffffffff));            cyg_pcihw_read_config_uint32(bus, devfn,                                         CYG_PCI_CFG_BAR_BASE+4*(bar+1),                                          &dev_info->base_address[bar+1]);        }    }    return ret;}    cyg_boolcyg_pci_allocate_io_priv( cyg_pci_device *dev_info, cyg_uint32 bar,                           CYG_PCI_ADDRESS32 *base,                           CYG_PCI_ADDRESS32 *assigned_addr){    cyg_uint32 flags, size;    CYG_PCI_ADDRESS32 aligned_addr;    // Get the probed size and flags    flags = dev_info->base_size[bar];    // Decode size    size = (~(flags & CYG_PRI_CFG_BAR_IO_MASK))+1;    // Calculate address we will assign the device.    // This can be made more clever.    // For now, simply align to required size.    aligned_addr = (*base+size-1) & ~(size-1);    // Is the request for IO space?    if (CYG_PCI_CFG_BAR_SPACE_IO != (flags & CYG_PCI_CFG_BAR_SPACE_MASK))        return false;    // Update the resource pointer and return values.    *base = aligned_addr+size;    dev_info->base_map[bar] = aligned_addr+HAL_PCI_PHYSICAL_IO_BASE;    *assigned_addr = aligned_addr;    return true;}cyg_boolcyg_pci_allocate_io( cyg_pci_device *dev_info, cyg_uint32 bar,                      CYG_PCI_ADDRESS32 *base){    cyg_uint8 bus = CYG_PCI_DEV_GET_BUS(dev_info->devid);    cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(dev_info->devid);    CYG_PCI_ADDRESS32 assigned_addr;    cyg_bool ret;        // Check that device is inactive.    if ((dev_info->command & CYG_PCI_CFG_COMMAND_ACTIVE) != 0)        return false;    // Allocate IO space for the device.    ret = cyg_pci_allocate_io_priv(dev_info, bar, base, &assigned_addr);    if (ret) {        // Map the device and update the BAR in the dev_info structure.        cyg_pcihw_write_config_uint32(bus, devfn,                                      CYG_PCI_CFG_BAR_BASE+4*bar,                                       assigned_addr);        cyg_pcihw_read_config_uint32(bus, devfn,                                     CYG_PCI_CFG_BAR_BASE+4*bar,                                      &dev_info->base_address[bar]);    }    return ret;}cyg_boolcyg_pci_translate_interrupt( cyg_pci_device *dev_info,                             CYG_ADDRWORD *vec ){    cyg_uint8 bus = CYG_PCI_DEV_GET_BUS(dev_info->devid);    cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(dev_info->devid);    return cyg_pcihw_translate_interrupt(bus, devfn, vec);}// Initialize devices on a given bus and all subordinate busses.cyg_boolcyg_pci_configure_bus( cyg_uint8 bus,		       cyg_uint8 *next_bus ){    cyg_uint8 devfn, header_type;    cyg_pci_device_id devid;    cyg_pci_device dev_info;    CYG_PCI_ADDRESS64 mem_start, mem_limit, mem_base;    CYG_PCI_ADDRESS32 io_start, io_limit, io_base;    // Scan only this bus for valid devices.    devid = CYG_PCI_DEV_MAKE_ID(bus, 0) | CYG_PCI_NULL_DEVFN;#ifdef CYGPKG_IO_PCI_DEBUG    diag_printf("Configuring bus %d.\n", bus);#endif    while (cyg_pci_find_next(devid, &devid) && bus == CYG_PCI_DEV_GET_BUS(devid)) {        devfn = CYG_PCI_DEV_GET_DEVFN(devid);		// Get the device info	cyg_pci_get_device_info(devid, &dev_info);#ifdef CYGPKG_IO_PCI_DEBUG	diag_printf("\n");	diag_printf("Configuring PCI Bus   : %d\n", bus);	diag_printf("            PCI Device: %d\n", CYG_PCI_DEV_GET_DEV(devfn));	diag_printf("            PCI Func  : %d\n", CYG_PCI_DEV_GET_FN(devfn));	diag_printf("            Vendor Id : 0x%08X\n", dev_info.vendor);	diag_printf("            Device Id : 0x%08X\n", dev_info.device);#endif	header_type = dev_info.header_type & CYG_PCI_CFG_HEADER_TYPE_MASK;	// Check for supported header types.	if (header_type != CYG_PCI_HEADER_NORMAL &&	    header_type != CYG_PCI_HEADER_BRIDGE) {	    CYG_FAIL("Unsupported PCI header type");	    continue;	}	// Only PCI-to-PCI bridges	if (header_type == CYG_PCI_HEADER_BRIDGE &&	    (dev_info.class_rev >> 8) != CYG_PCI_CLASS_BRIDGE_PCI_PCI) {	    CYG_FAIL("Unsupported PCI bridge class");	    continue;	}	// Configure the base registers	if (!cyg_pci_configure_device(&dev_info)) {	    // Apparently out of resources.	    CYG_FAIL("cyg_pci_configure_device failed");	    break;	}		// Activate non-bridge devices.	if (header_type != CYG_PCI_HEADER_BRIDGE) {	    dev_info.command |= (CYG_PCI_CFG_COMMAND_IO 	// enable I/O space		              | CYG_PCI_CFG_COMMAND_MEMORY	// enable memory space		              | CYG_PCI_CFG_COMMAND_MASTER); 	// enable bus master	    cyg_pci_write_config_uint16(dev_info.devid, CYG_PCI_CFG_COMMAND, dev_info.command);	} else {	    //  Bridge Configuration	    // Set up the bus numbers that define the bridge	    dev_info.header.bridge.pri_bus = bus;	    cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_PRI_BUS,					 dev_info.header.bridge.pri_bus);	    dev_info.header.bridge.sec_bus = *next_bus;	    cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_SEC_BUS,					 dev_info.header.bridge.sec_bus);	    // Temporarily set to maximum so config cycles get passed along.	    dev_info.header.bridge.sub_bus = CYG_PCI_MAX_BUS - 1;	    cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_SUB_BUS,					 dev_info.header.bridge.sub_bus);	    // increment bus counter	    *next_bus += 1;	    // To figure the sizes of the memory and I/O windows, save the	    // current base of memory and I/O before configuring the bus	    // or busses on the secondary side of the bridge. After the	    // secondary side is configured, the difference between the	    // current values and saved values will tell the size.	    // For bridges, the memory window must start and end on a 1M	    // boundary and the I/O window must start and end on a 4K	    // boundary. We round up the mem and I/O allocation bases	    // to appropriate boundaries before configuring the secondary	    // bus. Save the pre-rounded values in case no mem or I/O	    // is needed we can recover any space lost due to rounding.	    // round up start of PCI memory space to a 1M boundary	    mem_base = cyg_pci_memory_base;	    cyg_pci_memory_base += 0xfffff;	    cyg_pci_memory_base &= ~0xfffff;	    mem_start = cyg_pci_memory_base;	    // round up start of PCI I/O space to a 4 Kbyte start address	    io_base = cyg_pci_io_base;	    cyg_pci_io_base += 0xfff;	    cyg_pci_io_base &= ~0xfff;	    io_start = cyg_pci_io_base;			    // configure the subordinate PCI bus	    cyg_pci_configure_bus (dev_info.header.bridge.sec_bus, next_bus);				    // set subordinate bus number to last assigned bus number	    dev_info.header.bridge.sub_bus = *next_bus - 1;	    cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_SUB_BUS,					 dev_info.header.bridge.sub_bus);	    // Did sub bus configuration use any I/O?	    if (cyg_pci_io_base > io_start) {		// round up end of bridge's I/O space to a 4K boundary		cyg_pci_io_base += 0xfff;		cyg_pci_io_base &= ~0xfff;		io_limit = cyg_pci_io_base - 0x1000;		// Enable I/O cycles across bridge		dev_info.command |= CYG_PCI_CFG_COMMAND_IO;		// 32 Bit I/O?		if ((dev_info.header.bridge.io_base & 0x0f) == 0x01) {		    // I/O Base Upper 16 Bits Register		    dev_info.header.bridge.io_base_upper16 = io_start >> 16;		    cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_IO_BASE_UPPER16,						 dev_info.header.bridge.io_base_upper16);		    // I/O Limit Upper 16 Bits Register		    dev_info.header.bridge.io_limit_upper16 = io_limit >> 16;		    cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_IO_LIMIT_UPPER16,						 dev_info.header.bridge.io_limit_upper16);		}		// I/O Base Register		dev_info.header.bridge.io_base = (io_start & 0xf000) >> 8;		cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_IO_BASE,					     dev_info.header.bridge.io_base);		// I/O Limit Register		dev_info.header.bridge.io_limit = (io_limit & 0xf000) >> 8;		cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_IO_LIMIT,					     dev_info.header.bridge.io_limit);	    } else {		// No I/O space used on secondary bus.		// Recover any space lost on unnecessary rounding		cyg_pci_io_base = io_base;	    }	    // Did sub bus configuration use any memory?	    if (cyg_pci_memory_base > mem_start) {		// round up end of bridge's PCI memory space to a 1M boundary		cyg_pci_memory_base += 0xfffff;		cyg_pci_memory_base &= ~0xfffff;		mem_limit = cyg_pci_memory_base - 0x100000;		// Enable memory cycles across bridge		dev_info.command |= CYG_PCI_CFG_COMMAND_MEMORY;		// Memory Base Register		dev_info.header.bridge.mem_base = (mem_start >> 16) & 0xfff0;		cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_MEM_BASE,						 dev_info.header.bridge.mem_base);		// Memory Limit Register		dev_info.header.bridge.mem_limit = (mem_limit >> 16) & 0xfff0;		cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_MEM_LIMIT,						 dev_info.header.bridge.mem_limit);		// Prefetchable memory not yet supported across bridges.		// Disable by making limit < base		{		    cyg_uint16 tmp_word;		    tmp_word = 0;		    cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_PREFETCH_LIMIT,						 tmp_word);		    tmp_word = 0xfff0;		    cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_PREFETCH_BASE,						 tmp_word);		}	    } else {		// No memory space used on secondary bus.		// Recover any space lost on unnecessary rounding		cyg_pci_memory_base = mem_base;	    }	    // Setup the bridge command register	    dev_info.command |= CYG_PCI_CFG_COMMAND_MASTER;	    dev_info.command |= CYG_PCI_CFG_COMMAND_SERR;	    cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_COMMAND,					  dev_info.command);	    /* Setup the Bridge Control Register */	    dev_info.header.bridge.control |= CYG_PCI_CFG_BRIDGE_CTL_PARITY;	    dev_info.header.bridge.control |= CYG_PCI_CFG_BRIDGE_CTL_SERR;	    dev_info.header.bridge.control |= CYG_PCI_CFG_BRIDGE_CTL_MASTER;	    cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_BRIDGE_CONTROL,					  dev_info.header.bridge.control);	}    }#ifdef CYGPKG_IO_PCI_DEBUG    diag_printf("Finished configuring bus %d.\n", bus);#endif    return true;}#endif // ifdef CYG_PCI_PRESENT//-----------------------------------------------------------------------------// end of pci.c

⌨️ 快捷键说明

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