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

📄 pci.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 3 页
字号:
//=============================================================================
//
//      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 <pkgconf/hal.h>
#include <pkgconf/io_pci.h>
#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;

void
cyg_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 functions

void 
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);
    cyg_uint8 header_type;

    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,
                                &header_type);
    dev_info->header_type = (cyg_pci_header_type) header_type;
    cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_BIST,
                                &dev_info->bist);

    if ((dev_info->header_type & CYG_PCI_CFG_HEADER_TYPE_MASK) == CYG_PCI_HEADER_BRIDGE)
	dev_info->num_bars = 2;
    else
	dev_info->num_bars = 6;

    for (i = 0; i < dev_info->num_bars; i++)
        cyg_pcihw_read_config_uint32(bus, devfn,
                                     CYG_PCI_CFG_BAR_BASE + 4*i,
                                     &dev_info->base_address[i]);

    // If device is disabled, probe BARs for sizes.
    if ((dev_info->command & CYG_PCI_CFG_COMMAND_ACTIVE) == 0) {

        for (i = 0; i < dev_info->num_bars; 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;
#ifdef CYGPKG_IO_PCI_DEBUG
			printf("BAR %d size = 0x%08x\n", i, dev_info->base_size[i]);
#endif

	    if (size == 0) {
		continue;
	    }

            // 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 {
	// If the device is already configured. Fill in the base_map.
	CYG_PCI_ADDRESS64 tmp_addr;
	cyg_uint32 bar;

#ifdef CYGPKG_IO_PCI_DEBUG
			printf("Device is already initialized\n");
#endif

        for (i = 0; i < dev_info->num_bars; i++){

	    dev_info->base_size[i] = 0;

            bar = dev_info->base_address[i];

	    if ((bar & CYG_PCI_CFG_BAR_SPACE_MASK) == CYG_PCI_CFG_BAR_SPACE_IO) {
		dev_info->base_map[i] = (bar & (CYG_PRI_CFG_BAR_IO_MASK & XSCALE_PCI_IO_SZ_MASK)) + HAL_PCI_PHYSICAL_IO_BASE;
	    } else {
		tmp_addr = bar & (CYG_PRI_CFG_BAR_MEM_MASK & XSCALE_PCI_MEM_SZ_MASK);

		if ((bar & CYG_PRI_CFG_BAR_MEM_TYPE_MASK) == CYG_PRI_CFG_BAR_MEM_TYPE_64)
		    tmp_addr |= ((CYG_PCI_ADDRESS64)(dev_info->base_address[i+1] & CYG_PRI_CFG_BAR_MEM_MASK)) << 32;
			
		tmp_addr += HAL_PCI_PHYSICAL_MEMORY_BASE;

		dev_info->base_map[i] = tmp_addr;
		if ((bar & CYG_PRI_CFG_BAR_MEM_TYPE_MASK) == CYG_PRI_CFG_BAR_MEM_TYPE_64)
		    dev_info->base_map[i++] = tmp_addr >> 32;
	    }
        }
    }
            

    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_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_PRI_BUS,
                                    &dev_info->header.bridge.pri_bus);
        cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_SEC_BUS,
                                    &dev_info->header.bridge.sec_bus);
        cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_SUB_BUS,
                                    &dev_info->header.bridge.sub_bus);
        cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_SEC_LATENCY_TIMER,
                                    &dev_info->header.bridge.sec_latency_timer);
        cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_IO_BASE,
                                    &dev_info->header.bridge.io_base);
        cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_IO_LIMIT,
                                    &dev_info->header.bridge.io_limit);
        cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_SEC_STATUS,
                                    &dev_info->header.bridge.sec_status);
        cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_MEM_BASE,
                                    &dev_info->header.bridge.mem_base);
        cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_MEM_LIMIT,
                                    &dev_info->header.bridge.mem_limit);
        cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_PREFETCH_BASE,
                                    &dev_info->header.bridge.prefetch_base);
        cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_PREFETCH_LIMIT,
                                    &dev_info->header.bridge.prefetch_limit);
        cyg_pcihw_read_config_uint32(bus, devfn, CYG_PCI_CFG_PREFETCH_BASE_UPPER32,
                                    &dev_info->header.bridge.prefetch_base_upper32);
        cyg_pcihw_read_config_uint32(bus, devfn, CYG_PCI_CFG_PREFETCH_LIMIT_UPPER32,
                                    &dev_info->header.bridge.prefetch_limit_upper32);
        cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_IO_BASE_UPPER16,
                                    &dev_info->header.bridge.io_base_upper16);
        cyg_pcihw_read_config_uint16(bus, devfn, CYG_PCI_CFG_IO_LIMIT_UPPER16,
                                    &dev_info->header.bridge.io_limit_upper16);
        cyg_pcihw_read_config_uint32(bus, devfn, CYG_PCI_CFG_BRIDGE_ROM_ADDRESS,
                                    &dev_info->header.bridge.rom_address);
        cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_INT_LINE,
                                    &dev_info->header.bridge.int_line);
        cyg_pcihw_read_config_uint8(bus, devfn, CYG_PCI_CFG_INT_PIN,
                                    &dev_info->header.bridge.int_pin);
        cyg_pcihw_read_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;
    }
}

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);
    int i;

    // 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);

    for (i = 0; i < dev_info->num_bars; i++) {
	cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_BASE+4*i,
				      dev_info->base_address[i]);
    }

    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_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_PRI_BUS,
				     dev_info->header.bridge.pri_bus);
        cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_SEC_BUS,
				     dev_info->header.bridge.sec_bus);
        cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_SUB_BUS,
				     dev_info->header.bridge.sub_bus);
        cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_SEC_LATENCY_TIMER,
				     dev_info->header.bridge.sec_latency_timer);
        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 functions
void 
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),

⌨️ 快捷键说明

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