📄 pci.c
字号:
//=============================================================================//// pci.c//// PCI library////=============================================================================//####COPYRIGHTBEGIN####// // ------------------------------------------- // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.redhat.com/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations under // the License. // // The Original Code is eCos - Embedded Configurable Operating System, // released September 30, 1998. // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND####//=============================================================================//#####DESCRIPTIONBEGIN####//// Author(s): jskov, from design by nickg// Contributors: jskov// Date: 1999-08-09// Purpose: PCI configuration// Description: // PCI bus support library.// Handles simple resource allocation for devices.// Can configure 64bit devices, but drivers may need special// magic to access all of this memory space - this is platform// specific and the driver must know how to handle it on its own.//####DESCRIPTIONEND####////=============================================================================#include <cyg/io/pci_hw.h>// CYG_PCI_PRESENT only gets defined for targets that provide PCI HAL support.// See pci_hw.h for details.#ifdef CYG_PCI_PRESENT#include <cyg/io/pci.h>#include <cyg/infra/cyg_ass.h>static cyg_bool cyg_pci_lib_initialized = false;voidcyg_pci_init( void ){ if (!cyg_pci_lib_initialized) { // Initialize the PCI bus, preparing it for general access. cyg_pcihw_init(); cyg_pci_lib_initialized = true; }}//---------------------------------------------------------------------------// Common device configuration access functionsvoid cyg_pci_get_device_info ( cyg_pci_device_id devid, cyg_pci_device *dev_info ){ int i; cyg_uint8 bus = CYG_PCI_DEV_GET_BUS(devid); cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(devid); dev_info->devid = devid; cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_VENDOR, &dev_info->vendor); cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_DEVICE, &dev_info->device); cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_COMMAND, &dev_info->command); cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_STATUS, &dev_info->status); cyg_pcihw_read_config_uint32(bus, devfn, CYG_PCI_CFG_CLASS_REV, &dev_info->class_rev); cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_CACHE_LINE_SIZE, &dev_info->cache_line_size); cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_LATENCY_TIMER, &dev_info->latency_timer); cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_HEADER_TYPE, (cyg_uint8*)&dev_info->header_type); cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_BIST, &dev_info->bist); for (i = 0; i < CYG_PCI_MAX_BAR; i++){ cyg_uint32 bar; cyg_pcihw_read_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_BASE + 4*i, &bar); dev_info->base_address[i] = bar; } // If device is disabled, probe BARs for sizes. if ((dev_info->command & CYG_PCI_CFG_COMMAND_ACTIVE) == 0) { for (i = 0; i < CYG_PCI_MAX_BAR; i++){ cyg_uint32 size; cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_BASE + 4*i, 0xffffffff); cyg_pcihw_read_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_BASE + 4*i, &size); dev_info->base_size[i] = size; dev_info->base_map[i] = 0xffffffff; // Check for a 64bit memory region. if (CYG_PCI_CFG_BAR_SPACE_MEM == (size & CYG_PCI_CFG_BAR_SPACE_MASK)) { if (size & CYG_PRI_CFG_BAR_MEM_TYPE_64) { // Clear fields for next BAR - it's the upper 32 bits. i++; dev_info->base_size[i] = 0; dev_info->base_map[i] = 0xffffffff; } } } } else { // Clear the base map so we can recognize an already configured // device. for (i = 0; i < CYG_PCI_MAX_BAR; i++) { dev_info->base_size[i] = 0; } } switch (dev_info->header_type & CYG_PCI_CFG_HEADER_TYPE_MASK) { case CYG_PCI_HEADER_NORMAL: cyg_pcihw_read_config_uint32(bus, devfn, CYG_PCI_CFG_CARDBUS_CIS, &dev_info->header.normal.cardbus_cis); cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_SUB_VENDOR, &dev_info->header.normal.sub_vendor); cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_SUB_ID, &dev_info->header.normal.sub_id); cyg_pcihw_read_config_uint32(bus, devfn, CYG_PCI_CFG_ROM_ADDRESS, &dev_info->header.normal.rom_address); cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_CAP_LIST, &dev_info->header.normal.cap_list); cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_INT_LINE, &dev_info->header.normal.int_line); cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_INT_PIN, &dev_info->header.normal.int_pin); cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_MIN_GNT, &dev_info->header.normal.min_gnt); cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_MAX_LAT, &dev_info->header.normal.max_lat); break; case CYG_PCI_HEADER_BRIDGE: CYG_FAIL("PCI device header 'bridge' support not implemented"); 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; }}void cyg_pci_set_device_info ( cyg_pci_device_id devid, cyg_pci_device *dev_info ){ cyg_uint8 bus = CYG_PCI_DEV_GET_BUS(devid); cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(devid); // Only writable entries are updated. cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_COMMAND, dev_info->command); cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_STATUS, dev_info->status); cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_CACHE_LINE_SIZE, dev_info->cache_line_size); cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_LATENCY_TIMER, dev_info->latency_timer); cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_BIST, dev_info->bist); cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_0, dev_info->base_address[0]); cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_1, dev_info->base_address[1]); cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_2, dev_info->base_address[2]); cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_3, dev_info->base_address[3]); cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_4, dev_info->base_address[4]); cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_5, dev_info->base_address[5]); switch (dev_info->header_type & CYG_PCI_CFG_HEADER_TYPE_MASK) { case CYG_PCI_HEADER_NORMAL: cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_CARDBUS_CIS, dev_info->header.normal.cardbus_cis); cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_SUB_VENDOR, dev_info->header.normal.sub_vendor); cyg_pcihw_write_config_uint16(bus, devfn, CYG_PCI_CFG_SUB_ID, dev_info->header.normal.sub_id); cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_ROM_ADDRESS, dev_info->header.normal.rom_address); cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_INT_LINE, dev_info->header.normal.int_line); cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_INT_PIN, dev_info->header.normal.int_pin); cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_MIN_GNT, dev_info->header.normal.min_gnt); cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_MAX_LAT, dev_info->header.normal.max_lat); break; case CYG_PCI_HEADER_BRIDGE: CYG_FAIL("PCI device header 'bridge' support not implemented"); 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); // If this is the initializer, start with 0/0/0 if (CYG_PCI_NULL_DEVID == cur_devid) { bus = dev = fn = 0; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -