ppc405_pci.c
来自「eCos操作系统源码」· C语言 代码 · 共 287 行
C
287 行
//==========================================================================//// ppc405_pci.c//// HAL variant support code for PCI on PowerPC 405GP////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2003, 2004 Gary Thomas//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): Gary Thomas <gary@mlbassoc.com>// Contributors: // Date: 2003-09-02// Purpose: HAL PCI support// Description: Implementations of HAL PCI interfaces////####DESCRIPTIONEND####////========================================================================*/#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS#include <pkgconf/hal.h>#include <pkgconf/system.h>#include CYGBLD_HAL_PLATFORM_H#include <cyg/infra/cyg_type.h> // base types#include <cyg/infra/cyg_trac.h> // tracing macros#include <cyg/infra/cyg_ass.h> // assertion macros#include <cyg/infra/diag.h> // diag_printf() and friends#include <cyg/hal/hal_io.h> // IO macros#include <cyg/hal/hal_arch.h> // Register state info#include <cyg/hal/hal_diag.h>#include <cyg/hal/hal_intr.h> // Interrupt names#include <cyg/hal/hal_cache.h>#include <cyg/hal/ppc_regs.h> // Hardware definitions#include <cyg/hal/hal_if.h> // calling interface API#include <pkgconf/io_pci.h>#include <cyg/io/pci_hw.h>#include <cyg/io/pci.h>// PCI supportexternC voidhal_ppc405_pci_init(void){ static int _init = 0; cyg_uint8 next_bus; cyg_uint32 cmd_state, bridge_state; if (_init) return; _init = 1; // Configure PCI bridge HAL_WRITE_UINT32LE(PCIL0_PMM0PCILA, 0); HAL_WRITE_UINT32LE(PCIL0_PMM0PCIHA, 0); HAL_WRITE_UINT32LE(PCIL0_PMM0LA, HAL_PCI_PHYSICAL_MEMORY_BASE); HAL_WRITE_UINT32LE(PCIL0_PMM0MA, ~(0x10000000-1) | 0x00000001); HAL_PCI_CFG_WRITE_UINT32(0, CYG_PCI_DEV_MAKE_DEVFN(0,0), CYG_PCI_CFG_BAR_1, 0); HAL_WRITE_UINT32LE(PCIL0_PTM1LA, 0); HAL_WRITE_UINT32LE(PCIL0_PTM1MS, ~(0x10000000-1) | 0x00000001); // Indicate that the bridge has been configured HAL_PCI_CFG_READ_UINT32(0, CYG_PCI_DEV_MAKE_DEVFN(0,0), 0x60, bridge_state); bridge_state |= 0x0001; HAL_PCI_CFG_WRITE_UINT32(0, CYG_PCI_DEV_MAKE_DEVFN(0,0), 0x60, bridge_state); // Setup for bus mastering HAL_PCI_CFG_READ_UINT32(0, CYG_PCI_DEV_MAKE_DEVFN(0,0), CYG_PCI_CFG_COMMAND, cmd_state); cyg_pci_init(); if ((cmd_state & CYG_PCI_CFG_COMMAND_MEMORY) == 0) {#if defined(CYGPKG_IO_PCI_DEBUG) diag_printf("Configure PCI bus\n");#endif HAL_PCI_CFG_WRITE_UINT32(0, CYG_PCI_DEV_MAKE_DEVFN(0,0), CYG_PCI_CFG_COMMAND, CYG_PCI_CFG_COMMAND_MEMORY | CYG_PCI_CFG_COMMAND_MASTER | CYG_PCI_CFG_COMMAND_PARITY | CYG_PCI_CFG_COMMAND_SERR); // Setup latency timer field HAL_PCI_CFG_WRITE_UINT8(0, CYG_PCI_DEV_MAKE_DEVFN(0,0), CYG_PCI_CFG_LATENCY_TIMER, 32); // Configure PCI bus. next_bus = 1; cyg_pci_configure_bus(0, &next_bus); }#if defined(CYGSEM_HAL_POWERPC_PPC405_PCI_SHOW_BUS) if (1) { cyg_uint8 req; cyg_uint8 devfn; cyg_pci_device_id devid; cyg_pci_device dev_info; int i; devid = CYG_PCI_DEV_MAKE_ID(next_bus-1, 0) | CYG_PCI_NULL_DEVFN; while (cyg_pci_find_next(devid, &devid)) { devfn = CYG_PCI_DEV_GET_DEVFN(devid); cyg_pci_get_device_info(devid, &dev_info); HAL_PCI_CFG_READ_UINT8(0, devfn, CYG_PCI_CFG_INT_PIN, req); diag_printf("\n"); diag_printf("Bus: %d", CYG_PCI_DEV_GET_BUS(devid)); diag_printf(", PCI Device: %d", CYG_PCI_DEV_GET_DEV(devfn)); diag_printf(", PCI Func: %d\n", CYG_PCI_DEV_GET_FN(devfn)); diag_printf(" Vendor Id: 0x%04X", dev_info.vendor); diag_printf(", Device Id: 0x%04X", dev_info.device); diag_printf(", Command: 0x%04X", dev_info.command); diag_printf(", IRQ: %d\n", req); for (i = 0; i < dev_info.num_bars; i++) { diag_printf(" BAR[%d] 0x%08x /", i, dev_info.base_address[i]); diag_printf(" probed size 0x%08x / CPU addr 0x%08x\n", dev_info.base_size[i], dev_info.base_map[i]); } } }#endif}externC void hal_ppc405_pci_translate_interrupt(int bus, int devfn, int *vec, int *valid){ cyg_uint8 req; cyg_uint8 dev = CYG_PCI_DEV_GET_DEV(devfn); if ((dev >= CYG_PCI_MIN_DEV) && (dev < CYG_PCI_MAX_DEV)) { HAL_PCI_CFG_READ_UINT8(bus, devfn, CYG_PCI_CFG_INT_PIN, req); if (0 != req) { #ifdef CYG_PCI_IRQ_MAP char pci_irq_table[][4] = CYG_PCI_IRQ_MAP;#else#error "Need platform defined IRQ map"#endif *vec = pci_irq_table[dev-CYG_PCI_MIN_DEV][req-1]; *valid = (*vec != -1); } else { /* Device will not generate interrupt requests. */ *valid = false; } #if defined(CYGPKG_IO_PCI_DEBUG) diag_printf("Int - dev: %d, req: %d, vector: %d\n", dev, req, *vec);#endif } else { *valid = false; // Invalid device }}// PCI configuration space access#define _EXT_ENABLE 0x80000000 // Could be 0x80000000static __inline__ cyg_uint32_cfg_addr(int bus, int devfn, int offset){ return _EXT_ENABLE | (bus << 16) | (devfn << 8) | (offset << 0);}externC cyg_uint8 hal_ppc405_pci_cfg_read_uint8(int bus, int devfn, int offset){ cyg_uint32 cfg_addr; cyg_uint8 cfg_val = (cyg_uint8) 0xFF;#ifdef CYGPKG_IO_PCI_DEBUG diag_printf("%s(bus=%x, devfn=%x, offset=%x) = ", __FUNCTION__, bus, devfn, offset);#endif // CYGPKG_IO_PCI_DEBUG cfg_addr = _cfg_addr(bus, devfn, offset); HAL_WRITE_UINT32LE(PCIC0_CFGADDR, cfg_addr); HAL_READ_UINT8LE(PCIC0_CFGDATA|(offset & 0x03), cfg_val);#ifdef CYGPKG_IO_PCI_DEBUG diag_printf("%x\n", cfg_val);#endif // CYGPKG_IO_PCI_DEBUG return cfg_val;}externC cyg_uint16 hal_ppc405_pci_cfg_read_uint16(int bus, int devfn, int offset){ cyg_uint32 cfg_addr; cyg_uint16 cfg_val = (cyg_uint16) 0xFFFF;#ifdef CYGPKG_IO_PCI_DEBUG diag_printf("%s(bus=%x, devfn=%x, offset=%x) = ", __FUNCTION__, bus, devfn, offset);#endif // CYGPKG_IO_PCI_DEBUG cfg_addr = _cfg_addr(bus, devfn, offset); HAL_WRITE_UINT32LE(PCIC0_CFGADDR, cfg_addr); HAL_READ_UINT16LE(PCIC0_CFGDATA|(offset & 0x03), cfg_val);#ifdef CYGPKG_IO_PCI_DEBUG diag_printf("%x\n", cfg_val);#endif // CYGPKG_IO_PCI_DEBUG return cfg_val;}externC cyg_uint32 hal_ppc405_pci_cfg_read_uint32(int bus, int devfn, int offset){ cyg_uint32 cfg_addr; cyg_uint32 cfg_val = (cyg_uint32) 0xFFFFFFFF;#ifdef CYGPKG_IO_PCI_DEBUG diag_printf("%s(bus=%x, devfn=%x, offset=%x) = ", __FUNCTION__, bus, devfn, offset);#endif // CYGPKG_IO_PCI_DEBUG cfg_addr = _cfg_addr(bus, devfn, offset); HAL_WRITE_UINT32LE(PCIC0_CFGADDR, cfg_addr); HAL_READ_UINT32LE(PCIC0_CFGDATA, cfg_val);#ifdef CYGPKG_IO_PCI_DEBUG diag_printf("%x\n", cfg_val);#endif // CYGPKG_IO_PCI_DEBUG return cfg_val;}externC voidhal_ppc405_pci_cfg_write_uint8(int bus, int devfn, int offset, cyg_uint8 cfg_val){ cyg_uint32 cfg_addr;#ifdef CYGPKG_IO_PCI_DEBUG diag_printf("%s(bus=%x, devfn=%x, offset=%x, val=%x)\n", __FUNCTION__, bus, devfn, offset, cfg_val);#endif // CYGPKG_IO_PCI_DEBUG cfg_addr = _cfg_addr(bus, devfn, offset); HAL_WRITE_UINT32LE(PCIC0_CFGADDR, cfg_addr); HAL_WRITE_UINT8LE(PCIC0_CFGDATA|(offset & 0x03), cfg_val);}externC voidhal_ppc405_pci_cfg_write_uint16(int bus, int devfn, int offset, cyg_uint16 cfg_val){ cyg_uint32 cfg_addr;#ifdef CYGPKG_IO_PCI_DEBUG diag_printf("%s(bus=%x, devfn=%x, offset=%x, val=%x)\n", __FUNCTION__, bus, devfn, offset, cfg_val);#endif // CYGPKG_IO_PCI_DEBUG cfg_addr = _cfg_addr(bus, devfn, offset); HAL_WRITE_UINT32LE(PCIC0_CFGADDR, cfg_addr); HAL_WRITE_UINT16LE(PCIC0_CFGDATA|(offset & 0x03), cfg_val);}externC voidhal_ppc405_pci_cfg_write_uint32(int bus, int devfn, int offset, cyg_uint32 cfg_val){ cyg_uint32 cfg_addr;#ifdef CYGPKG_IO_PCI_DEBUG diag_printf("%s(bus=%x, devfn=%x, offset=%x, val=%x)\n", __FUNCTION__, bus, devfn, offset, cfg_val);#endif // CYGPKG_IO_PCI_DEBUG cfg_addr = _cfg_addr(bus, devfn, offset); HAL_WRITE_UINT32LE(PCIC0_CFGADDR, cfg_addr); HAL_WRITE_UINT32LE(PCIC0_CFGDATA, cfg_val);}/*------------------------------------------------------------------------*/// EOF ppc405_pci.c
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?