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

📄 pci.c

📁 移植到WLIT项目的redboot源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
				      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 DEBUG_PCI    printf("cyg_pci_find_next: start[%x] ...",(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;    } else if (CYG_PCI_NULL_DEVFN == (cur_devid & CYG_PCI_NULL_DEVFN)) {        dev = fn = 0;    } 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=0) {        for (;dev < CYG_PCI_MAX_DEV; dev++, fn=0) {            for (;fn < CYG_PCI_MAX_FN; fn++) {                cyg_uint16 vendor;                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) {                    *next_devid = CYG_PCI_DEV_MAKE_ID(bus, devfn);                    return true;                }            }        }    }#ifdef DEBUG_PCI    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;    // 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);        if (v != vendor) continue;        // Check that device matches.        cyg_pcihw_read_config_uint16(bus, devfn,                                     CYG_PCI_CFG_DEVICE, &d);        if (d == device) {            *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;}//------------------------------------------------------------------------// Resource Allocationstatic CYG_PCI_ADDRESS64 cyg_pci_memory_base = HAL_PCI_ALLOC_BASE_MEMORY;static CYG_PCI_ADDRESS32 cyg_pci_io_base = HAL_PCI_ALLOC_BASE_IO;voidcyg_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 < dev_info->num_bars; bar++) {	    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?    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)

⌨️ 快捷键说明

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