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

📄 pci.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 3 页
字号:
        cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_IO_BASE,				     dev_info->header.bridge.io_base);        cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_IO_LIMIT,				     dev_info->header.bridge.io_limit);        cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_SEC_STATUS,				      dev_info->header.bridge.sec_status);        cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_MEM_BASE,				      dev_info->header.bridge.mem_base);        cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_MEM_LIMIT,				      dev_info->header.bridge.mem_limit);        cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_PREFETCH_BASE,				      dev_info->header.bridge.prefetch_base);        cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_PREFETCH_LIMIT,				      dev_info->header.bridge.prefetch_limit);        cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_PREFETCH_BASE_UPPER32,				      dev_info->header.bridge.prefetch_base_upper32);        cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_PREFETCH_LIMIT_UPPER32,				      dev_info->header.bridge.prefetch_limit_upper32);        cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_IO_BASE_UPPER16,				      dev_info->header.bridge.io_base_upper16);        cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_IO_LIMIT_UPPER16,				      dev_info->header.bridge.io_limit_upper16);        cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_BRIDGE_ROM_ADDRESS,				      dev_info->header.bridge.rom_address);        cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_INT_LINE,				     dev_info->header.bridge.int_line);        cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_BRIDGE_CONTROL,				      dev_info->header.bridge.control);        break;    case CYG_PCI_HEADER_CARDBUS_BRIDGE:        CYG_FAIL("PCI device header 'cardbus bridge' support not implemented");        break;    default:        CYG_FAIL("Unknown PCI device header type");        break;    }    // Update values in dev_info.    cyg_pci_get_device_info(devid, dev_info);}//---------------------------------------------------------------------------// Specific device configuration access functionsvoid cyg_pci_read_config_uint8( cyg_pci_device_id devid,                           cyg_uint8 offset, cyg_uint8 *val){    cyg_pcihw_read_config_uint8(CYG_PCI_DEV_GET_BUS(devid),                                CYG_PCI_DEV_GET_DEVFN(devid),                                offset, val);}void cyg_pci_read_config_uint16( cyg_pci_device_id devid,                            cyg_uint8 offset, cyg_uint16 *val){    cyg_pcihw_read_config_uint16(CYG_PCI_DEV_GET_BUS(devid),                                 CYG_PCI_DEV_GET_DEVFN(devid),                                 offset, val);}voidcyg_pci_read_config_uint32( cyg_pci_device_id devid,                            cyg_uint8 offset, cyg_uint32 *val){    cyg_pcihw_read_config_uint32(CYG_PCI_DEV_GET_BUS(devid),                                 CYG_PCI_DEV_GET_DEVFN(devid),                                 offset, val);}// Write functionsvoidcyg_pci_write_config_uint8( cyg_pci_device_id devid,                            cyg_uint8 offset, cyg_uint8 val){    cyg_pcihw_write_config_uint8(CYG_PCI_DEV_GET_BUS(devid),                                 CYG_PCI_DEV_GET_DEVFN(devid),                                 offset, val);}voidcyg_pci_write_config_uint16( cyg_pci_device_id devid,                             cyg_uint8 offset, cyg_uint16 val){    cyg_pcihw_write_config_uint16(CYG_PCI_DEV_GET_BUS(devid),                                  CYG_PCI_DEV_GET_DEVFN(devid),                                  offset, val);}voidcyg_pci_write_config_uint32( cyg_pci_device_id devid,                             cyg_uint8 offset, cyg_uint32 val){    cyg_pcihw_write_config_uint32(CYG_PCI_DEV_GET_BUS(devid),                                  CYG_PCI_DEV_GET_DEVFN(devid),                                  offset, val);}//------------------------------------------------------------------------// Device find functionscyg_boolcyg_pci_find_next( cyg_pci_device_id cur_devid,                    cyg_pci_device_id *next_devid ){    cyg_uint8 bus = CYG_PCI_DEV_GET_BUS(cur_devid);    cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(cur_devid);    cyg_uint8 dev = CYG_PCI_DEV_GET_DEV(devfn);    cyg_uint8 fn = CYG_PCI_DEV_GET_FN(devfn);#ifdef CYGPKG_IO_PCI_DEBUG    diag_printf("cyg_pci_find_next: start[%x] ...\n",(unsigned)cur_devid);#endif    // If this is the initializer, start with 0/0/0    if (CYG_PCI_NULL_DEVID == cur_devid) {        bus = dev = fn = 0;        dev = CYG_PCI_MIN_DEV;    } else if (CYG_PCI_NULL_DEVFN == (cur_devid & CYG_PCI_NULL_DEVFN)) {        dev = fn = 0;        dev = CYG_PCI_MIN_DEV;    } else {        // Otherwise, check multi-function bit of device's first function        cyg_uint8 header;	devfn = CYG_PCI_DEV_MAKE_DEVFN(dev, 0);	cyg_pcihw_read_config_uint8(bus, devfn,				    CYG_PCI_CFG_HEADER_TYPE, &header);	if (header & CYG_PCI_CFG_HEADER_TYPE_MF) {	    // Multi-function device. Increase fn.	    fn++;	    if (fn >= CYG_PCI_MAX_FN) {		fn = 0;		dev++;	    }	} else {	    // Single-function device. Skip to next.	    dev++;	}    }    // Note: Reset iterators in enclosing statement's "next" part.    //       Allows resuming scan with given input values.     for (;bus < CYG_PCI_MAX_BUS; bus++, dev=CYG_PCI_MIN_DEV) {        for (;dev < CYG_PCI_MAX_DEV; dev++, fn=0) {            for (;fn < CYG_PCI_MAX_FN; fn++) {                cyg_uint16 vendor;		if (CYG_PCI_IGNORE_DEVICE(bus, dev, fn))		    continue;                devfn = CYG_PCI_DEV_MAKE_DEVFN(dev, fn);                cyg_pcihw_read_config_uint16(bus, devfn,                                             CYG_PCI_CFG_VENDOR, &vendor);                if (CYG_PCI_VENDOR_UNDEFINED != vendor) {#ifdef CYGPKG_IO_PCI_DEBUG                diag_printf("   Bus: %d, Dev: %d, Fn: %d, Vendor: %x\n", bus, dev, fn, vendor);#endif                    *next_devid = CYG_PCI_DEV_MAKE_ID(bus, devfn);                    return true;                }            }        }    }#ifdef CYGPKG_IO_PCI_DEBUG    diag_printf("nothing.\n");#endif    return false;}//// Scan for a particular device, starting with 'devid'// 'devid' is updated with the next device if found.//         is not changed if no suitable device is found.cyg_boolcyg_pci_find_device( cyg_uint16 vendor, cyg_uint16 device,                     cyg_pci_device_id *devid ){    cyg_pci_device_id new_devid = *devid;#ifdef CYGPKG_IO_PCI_DEBUG    diag_printf("cyg_pci_find_device - vendor: %x, device: %x\n", vendor, device);#endif    // Scan entire bus, check for matches on valid devices.    while (cyg_pci_find_next(new_devid, &new_devid)) {        cyg_uint8 bus = CYG_PCI_DEV_GET_BUS(new_devid);        cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(new_devid);        cyg_uint16 v, d;        // Check that vendor matches.        cyg_pcihw_read_config_uint16(bus, devfn,                                     CYG_PCI_CFG_VENDOR, &v);        cyg_pcihw_read_config_uint16(bus, devfn,                                     CYG_PCI_CFG_DEVICE, &d);#ifdef CYGPKG_IO_PCI_DEBUG        diag_printf("... PCI vendor = %x, device = %x\n", v, d);#endif        if (v != vendor) continue;        // Check that device matches.        if (d == device) {#ifdef CYGPKG_IO_PCI_DEBUG            diag_printf("Found it!\n");#endif            *devid = new_devid;            return true;        }    }    return false;}cyg_boolcyg_pci_find_class( cyg_uint32 dev_class, cyg_pci_device_id *devid ){    // Scan entire bus, check for matches on valid devices.    while (cyg_pci_find_next(*devid, devid)) {        cyg_uint8 bus = CYG_PCI_DEV_GET_BUS(*devid);        cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(*devid);        cyg_uint32 c;        // Check that class code matches.        cyg_pcihw_read_config_uint32(bus, devfn,                                     CYG_PCI_CFG_CLASS_REV, &c);        c >>= 8;        if (c == dev_class)            return true;    }    return false;}cyg_boolcyg_pci_find_matching( cyg_pci_match_func *matchp,                        void * match_callback_data,                       cyg_pci_device_id *devid ){    cyg_pci_device_id new_devid = *devid;#ifdef CYGPKG_IO_PCI_DEBUG    diag_printf("cyg_pci_find_matching - func is at %x\n", (unsigned int)matchp);#endif    // Scan entire bus, check for matches on valid devices.    while (cyg_pci_find_next(new_devid, &new_devid)) {        cyg_uint8 bus = CYG_PCI_DEV_GET_BUS(new_devid);        cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(new_devid);        cyg_uint16 v, d;        cyg_uint32 c;        // Check that vendor, device and class match.        cyg_pcihw_read_config_uint16(bus, devfn,                                     CYG_PCI_CFG_VENDOR, &v);        cyg_pcihw_read_config_uint16(bus, devfn,                                     CYG_PCI_CFG_DEVICE, &d);        cyg_pcihw_read_config_uint32(bus, devfn,                                     CYG_PCI_CFG_CLASS_REV, &c);        c >>= 8;#ifdef CYGPKG_IO_PCI_DEBUG        diag_printf("... PCI vendor = %x, device = %x, class %x\n", v, d, c);#endif        // Check that device matches as the caller desires:        if ( (*matchp)(v, d, c, match_callback_data) ) {            *devid = new_devid;            return true;        }    }    return false;}//------------------------------------------------------------------------// Resource Allocationvoidcyg_pci_set_memory_base(CYG_PCI_ADDRESS64 base){    cyg_pci_memory_base = base;}voidcyg_pci_set_io_base(CYG_PCI_ADDRESS32 base){    cyg_pci_io_base = base;}cyg_boolcyg_pci_configure_device( cyg_pci_device *dev_info ){    int bar;    cyg_uint32 flags;    cyg_bool ret = true;    // If device is already active, just return true as    // cyg_pci_get_device_info has presumably filled in    // the base_map already.    if ((dev_info->command & CYG_PCI_CFG_COMMAND_ACTIVE) != 0)	return true;    if (dev_info->num_bars > 0) {        for (bar = 0; bar < CYG_PCI_MAX_BAR; bar++) {            if (!dev_info->base_address[bar]) {                continue;            }	    flags = dev_info->base_size[bar];	    ret = false;	    if ((flags & CYG_PCI_CFG_BAR_SPACE_MASK) == CYG_PCI_CFG_BAR_SPACE_MEM){		ret |= cyg_pci_allocate_memory(dev_info, bar, 					       &cyg_pci_memory_base);		// If this is a 64bit memory region, skip the next bar		// since it will contain the top 32 bits.		if (flags & CYG_PRI_CFG_BAR_MEM_TYPE_64)		    bar++;	    } else		ret |= cyg_pci_allocate_io(dev_info, bar, &cyg_pci_io_base);	    if (!ret)		return ret;	}    }    cyg_pci_translate_interrupt(dev_info, &dev_info->hal_vector);    return ret;}// This is the function that handles resource allocation. It doesn't// affect the device state.// Should not be called with top32bit-bar of a 64bit pair.inline cyg_boolcyg_pci_allocate_memory_priv( cyg_pci_device *dev_info, cyg_uint32 bar,                              CYG_PCI_ADDRESS64 *base,                               CYG_PCI_ADDRESS64 *assigned_addr){    cyg_uint32 mem_type, flags;    CYG_PCI_ADDRESS64 size, aligned_addr;    // Get the probed size and flags    flags = dev_info->base_size[bar];    // Decode size    size = (CYG_PCI_ADDRESS64) ((~(flags & CYG_PRI_CFG_BAR_MEM_MASK))+1);    // Calculate address we will assign the device.    // This can be made more clever, specifically:    //  1) The lowest 1MB should be reserved for devices with 1M memory type.    //     : Needs to be handled.    //  2) The low 32bit space should be reserved for devices with 32bit type.    //     : With the usual handful of devices it is unlikely that the    //       low 4GB space will become full.    //  3) A bitmap can be used to avoid fragmentation.    //     : Again, unlikely to be necessary.    //    // For now, simply align to required size.    aligned_addr = (*base+size-1) & ~(size-1);    // Is the request for memory space?

⌨️ 快捷键说明

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