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

📄 pci.c

📁 eCos1.31版
💻 C
📖 第 1 页 / 共 2 页
字号:
        // 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;                }            }        }    }    return false;}cyg_boolcyg_pci_find_device( cyg_uint16 vendor, cyg_uint16 device,                     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_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)            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 = false;    // Check that device is inactive.    if ((dev_info->command & CYG_PCI_CFG_COMMAND_ACTIVE) != 0)        return false;    for (bar = 0; bar < CYG_PCI_MAX_BAR; bar++) {        flags = dev_info->base_size[bar];        // No reason to scan beyond first inactive BAR.        if (0 == flags)            break;        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);        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)        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);    // Ensure the region fits within the 1MB IO space    if (aligned_addr+size > 1024*1024)        return false;    // 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);}#endif // ifdef CYG_PCI_PRESENT//-----------------------------------------------------------------------------// end of pci.c

⌨️ 快捷键说明

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