diff options
author | RajithaY <rajithax.yerrumsetty@intel.com> | 2017-04-25 03:31:15 -0700 |
---|---|---|
committer | Rajitha Yerrumchetty <rajithax.yerrumsetty@intel.com> | 2017-05-22 06:48:08 +0000 |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/roms/openbios/drivers/pci.c | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/roms/openbios/drivers/pci.c')
-rw-r--r-- | qemu/roms/openbios/drivers/pci.c | 1600 |
1 files changed, 0 insertions, 1600 deletions
diff --git a/qemu/roms/openbios/drivers/pci.c b/qemu/roms/openbios/drivers/pci.c deleted file mode 100644 index 5062f302f..000000000 --- a/qemu/roms/openbios/drivers/pci.c +++ /dev/null @@ -1,1600 +0,0 @@ -/* - * OpenBIOS pci driver - * - * This driver is compliant to the - * PCI bus binding to IEEE 1275-1994 Rev 2.1 - * - * (C) 2004 Stefan Reinauer <stepan@openbios.org> - * (C) 2005 Ed Schouten <ed@fxq.nl> - * - * Some parts from OpenHackWare-0.4, Copyright (c) 2004-2005 Jocelyn Mayer - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 - * - */ - -#include "config.h" -#include "libopenbios/bindings.h" -#include "libopenbios/ofmem.h" -#include "kernel/kernel.h" -#include "drivers/pci.h" -#include "libc/byteorder.h" -#include "libc/vsprintf.h" - -#include "drivers/drivers.h" -#include "drivers/vga.h" -#include "packages/video.h" -#include "libopenbios/video.h" -#include "timer.h" -#include "pci.h" -#include "pci_database.h" -#ifdef CONFIG_DRIVER_MACIO -#include "cuda.h" -#include "macio.h" -#endif -#ifdef CONFIG_DRIVER_USB -#include "drivers/usb.h" -#endif - -#if defined (CONFIG_DEBUG_PCI) -# define PCI_DPRINTF(format, ...) printk(format, ## __VA_ARGS__) -#else -# define PCI_DPRINTF(format, ...) do { } while (0) -#endif - -#define set_bool_property(ph, name) set_property(ph, name, NULL, 0); - -/* DECLARE data structures for the nodes. */ - -DECLARE_UNNAMED_NODE( ob_pci_bus_node, INSTALL_OPEN, 2*sizeof(int) ); -DECLARE_UNNAMED_NODE( ob_pci_simple_node, INSTALL_OPEN, 2*sizeof(int) ); -DECLARE_UNNAMED_NODE( ob_pci_empty_node, 0, 2*sizeof(int) ); - -const pci_arch_t *arch; - -#define IS_NOT_RELOCATABLE 0x80000000 -#define IS_PREFETCHABLE 0x40000000 -#define IS_ALIASED 0x20000000 - -enum { - CONFIGURATION_SPACE = 0, - IO_SPACE = 1, - MEMORY_SPACE_32 = 2, - MEMORY_SPACE_64 = 3, -}; - -static int encode_int32_cells(int num_cells, u32 *prop, ucell val) -{ - int i = 0; - - /* hi ... lo */ - for (i=0; i < num_cells; ++i) { - prop[num_cells - i - 1] = val; - val >>= 16; - val >>= 16; - } - - return num_cells; -} - -static inline int pci_encode_phys_addr(u32 *phys, int flags, int space_code, - pci_addr dev, uint8_t reg, uint64_t addr) -{ - - /* phys.hi */ - - phys[0] = flags | (space_code << 24) | dev | reg; - - /* phys.mid */ - - phys[1] = addr >> 32; - - /* phys.lo */ - - phys[2] = addr; - - return 3; -} - -static inline int pci_encode_size(u32 *prop, uint64_t size) -{ - return encode_int32_cells(2, prop, size); -} - -static int host_address_cells(void) -{ - return get_int_property(find_dev("/"), "#address-cells", NULL); -} - -static int host_encode_phys_addr(u32 *prop, ucell addr) -{ - return encode_int32_cells(host_address_cells(), prop, addr); -} - -static int host_size_cells(void) -{ - return get_int_property(find_dev("/"), "#size-cells", NULL); -} - -/* -static int parent_address_cells(void) -{ - phandle_t parent_ph = ih_to_phandle(my_parent()); - return get_int_property(parent_ph, "#address-cells", NULL); -} - -static int parent_size_cells(void) -{ - phandle_t parent_ph = ih_to_phandle(my_parent()); - return get_int_property(parent_ph, "#size-cells", NULL); -} -*/ - -#if defined(CONFIG_DEBUG_PCI) -static void dump_reg_property(const char* description, int nreg, u32 *reg) -{ - int i; - printk("%s reg", description); - for (i=0; i < nreg; ++i) { - printk(" %08X", reg[i]); - } - printk("\n"); -} -#endif - -static unsigned long pci_bus_addr_to_host_addr(int space, uint32_t ba) -{ - if (space == IO_SPACE) { - return arch->io_base + (unsigned long)ba; - } else if (space == MEMORY_SPACE_32) { - return arch->host_pci_base + (unsigned long)ba; - } else { - /* Return unaltered to aid debugging property values */ - return (unsigned long)ba; - } -} - -static void -ob_pci_open(int *idx) -{ - int ret=1; - RET ( -ret ); -} - -static void -ob_pci_close(int *idx) -{ -} - -static void -ob_pci_initialize(int *idx) -{ -} - -/* ( str len -- phys.lo phys.mid phys.hi ) */ - -static void -ob_pci_decode_unit(int *idx) -{ - ucell hi, mid, lo; - const char *arg = pop_fstr_copy(); - int dev, fn, reg, ss, n, p, t; - int bus = 0; /* no information */ - char *ptr; - - PCI_DPRINTF("ob_pci_decode_unit idx=%p\n", idx); - - fn = 0; - reg = 0; - n = 0; - p = 0; - t = 0; - - ptr = (char*)arg; - if (*ptr == 'n') { - n = IS_NOT_RELOCATABLE; - ptr++; - } - if (*ptr == 'i') { - ss = IO_SPACE; - ptr++; - if (*ptr == 't') { - t = IS_ALIASED; - ptr++; - } - - /* DD,F,RR,NNNNNNNN */ - - dev = strtol(ptr, &ptr, 16); - ptr++; - fn = strtol(ptr, &ptr, 16); - ptr++; - reg = strtol(ptr, &ptr, 16); - ptr++; - lo = strtol(ptr, &ptr, 16); - mid = 0; - - } else if (*ptr == 'm') { - ss = MEMORY_SPACE_32; - ptr++; - if (*ptr == 't') { - t = IS_ALIASED; - ptr++; - } - if (*ptr == 'p') { - p = IS_PREFETCHABLE; - ptr++; - } - - /* DD,F,RR,NNNNNNNN */ - - dev = strtol(ptr, &ptr, 16); - ptr++; - fn = strtol(ptr, &ptr, 16); - ptr++; - reg = strtol(ptr, &ptr, 16); - ptr++; - lo = strtol(ptr, &ptr, 16); - mid = 0; - - } else if (*ptr == 'x') { - unsigned long long addr64; - ss = MEMORY_SPACE_64; - ptr++; - if (*ptr == 'p') { - p = IS_PREFETCHABLE; - ptr++; - } - - /* DD,F,RR,NNNNNNNNNNNNNNNN */ - - dev = strtol(ptr, &ptr, 16); - ptr++; - fn = strtol(ptr, &ptr, 16); - ptr++; - reg = strtol(ptr, &ptr, 16); - ptr++; - addr64 = strtoll(ptr, &ptr, 16); - lo = (ucell)addr64; - mid = addr64 >> 32; - - } else { - ss = CONFIGURATION_SPACE; - /* "DD" or "DD,FF" */ - dev = strtol(ptr, &ptr, 16); - if (*ptr == ',') { - ptr++; - fn = strtol(ptr, NULL, 16); - } - lo = 0; - mid = 0; - } - free((char*)arg); - - hi = n | p | t | (ss << 24) | (bus << 16) | (dev << 11) | (fn << 8) | reg; - - PUSH(lo); - PUSH(mid); - PUSH(hi); - - PCI_DPRINTF("ob_pci_decode_unit idx=%p addr=" - FMT_ucellx " " FMT_ucellx " " FMT_ucellx "\n", - idx, lo, mid, hi); -} - -/* ( phys.lo phy.mid phys.hi -- str len ) */ - -static void -ob_pci_encode_unit(int *idx) -{ - char buf[28]; - cell hi = POP(); - cell mid = POP(); - cell lo = POP(); - int n, p, t, ss, dev, fn, reg; - - n = hi & IS_NOT_RELOCATABLE; - p = hi & IS_PREFETCHABLE; - t = hi & IS_ALIASED; - ss = (hi >> 24) & 0x03; - - dev = (hi >> 11) & 0x1F; - fn = (hi >> 8) & 0x07; - reg = hi & 0xFF; - - switch(ss) { - case CONFIGURATION_SPACE: - - if (fn == 0) /* DD */ - snprintf(buf, sizeof(buf), "%x", dev); - else /* DD,F */ - snprintf(buf, sizeof(buf), "%x,%x", dev, fn); - break; - - case IO_SPACE: - - /* [n]i[t]DD,F,RR,NNNNNNNN */ - snprintf(buf, sizeof(buf), "%si%s%x,%x,%x," FMT_ucellx, - n ? "n" : "", /* relocatable */ - t ? "t" : "", /* aliased */ - dev, fn, reg, t ? lo & 0x03FF : lo); - break; - - case MEMORY_SPACE_32: - - /* [n]m[t][p]DD,F,RR,NNNNNNNN */ - snprintf(buf, sizeof(buf), "%sm%s%s%x,%x,%x," FMT_ucellx, - n ? "n" : "", /* relocatable */ - t ? "t" : "", /* aliased */ - p ? "p" : "", /* prefetchable */ - dev, fn, reg, lo ); - break; - - case MEMORY_SPACE_64: - - /* [n]x[p]DD,F,RR,NNNNNNNNNNNNNNNN */ - snprintf(buf, sizeof(buf), "%sx%s%x,%x,%x,%llx", - n ? "n" : "", /* relocatable */ - p ? "p" : "", /* prefetchable */ - dev, fn, reg, ((long long)mid << 32) | (long long)lo); - break; - } - push_str(buf); - - PCI_DPRINTF("ob_pci_encode_unit space=%d dev=%d fn=%d buf=%s\n", - ss, dev, fn, buf); -} - -/* ( pci-addr.lo pci-addr.mid pci-addr.hi size -- virt ) */ - -static void -ob_pci_map_in(int *idx) -{ - phys_addr_t phys; - uint32_t ba; - ucell size, virt, tmp; - int space; - - PCI_DPRINTF("ob_pci_bar_map_in idx=%p\n", idx); - - size = POP(); - tmp = POP(); - POP(); - ba = POP(); - - /* Get the space from the pci-addr.hi */ - space = ((tmp & PCI_RANGE_TYPE_MASK) >> 24); - - phys = pci_bus_addr_to_host_addr(space, ba); - -#if defined(CONFIG_OFMEM) - ofmem_claim_phys(phys, size, 0); - -#if defined(CONFIG_PPC) - /* For some reason PPC gets upset when virt != phys for map-in... */ - virt = ofmem_claim_virt(phys, size, 0); -#else - virt = ofmem_claim_virt(-1, size, size); -#endif - - ofmem_map(phys, virt, size, ofmem_arch_io_translation_mode(phys)); - -#else - virt = size; /* Keep compiler quiet */ - virt = phys; -#endif - - PUSH(virt); -} - -NODE_METHODS(ob_pci_bus_node) = { - { NULL, ob_pci_initialize }, - { "open", ob_pci_open }, - { "close", ob_pci_close }, - { "decode-unit", ob_pci_decode_unit }, - { "encode-unit", ob_pci_encode_unit }, - { "pci-map-in", ob_pci_map_in }, -}; - -NODE_METHODS(ob_pci_simple_node) = { - { NULL, ob_pci_initialize }, - { "open", ob_pci_open }, - { "close", ob_pci_close }, -}; - -NODE_METHODS(ob_pci_empty_node) = { - { NULL, ob_pci_initialize } -}; - -static void pci_set_bus_range(const pci_config_t *config) -{ - phandle_t dev = find_dev(config->path); - u32 props[2]; - - props[0] = config->secondary_bus; - props[1] = config->subordinate_bus; - - PCI_DPRINTF("setting bus range for %s PCI device, " - "package handle " FMT_ucellx " " - "bus primary=%d secondary=%d subordinate=%d\n", - config->path, - dev, - config->primary_bus, - config->secondary_bus, - config->subordinate_bus); - - - set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0])); -} - -static void pci_host_set_reg(phandle_t phandle) -{ - phandle_t dev = phandle; - - /* at most 2 integers for address and size */ - u32 props[4]; - int ncells = 0; - - ncells += encode_int32_cells(host_address_cells(), props + ncells, - arch->cfg_base); - - ncells += encode_int32_cells(host_size_cells(), props + ncells, - arch->cfg_len); - - set_property(dev, "reg", (char *)props, ncells * sizeof(props[0])); - -#if defined(CONFIG_DEBUG_PCI) - dump_reg_property("pci_host_set_reg", 4, props); -#endif -} - -/* child-phys : parent-phys : size */ -/* 3 cells for PCI : 2 cells for 64bit parent : 2 cells for PCI */ - -static void pci_host_set_ranges(const pci_config_t *config) -{ - phandle_t dev = get_cur_dev(); - u32 props[32]; - int ncells; - - ncells = 0; - -#ifdef CONFIG_SPARC64 - /* While configuration space isn't mentioned in the IEEE-1275 PCI - bindings, it appears in the PCI host bridge ranges property in - real device trees. Hence we disable this range for all host - bridges except for SPARC, particularly as it causes Darwin/OS X - to incorrectly calculated PCI memory space ranges on PPC. */ - ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, - config->dev, 0, 0); - ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr); - ncells += pci_encode_size(props + ncells, arch->cfg_len); -#endif - - if (arch->io_base) { - ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE, - config->dev, 0, 0); - ncells += host_encode_phys_addr(props + ncells, arch->io_base); - ncells += pci_encode_size(props + ncells, arch->io_len); - } - if (arch->rbase) { - ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, - config->dev, 0, 0); - ncells += host_encode_phys_addr(props + ncells, arch->rbase); - ncells += pci_encode_size(props + ncells, arch->rlen); - } - if (arch->pci_mem_base) { - ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, - config->dev, 0, arch->pci_mem_base); - ncells += host_encode_phys_addr(props + ncells, arch->host_pci_base + - arch->pci_mem_base); - ncells += pci_encode_size(props + ncells, arch->mem_len); - } - set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0])); -} - -int host_config_cb(const pci_config_t *config) -{ - //XXX this overrides "reg" property - pci_host_set_reg(get_cur_dev()); - pci_host_set_ranges(config); - - return 0; -} - -static int sabre_configure(phandle_t dev) -{ - uint32_t props[28]; - - props[0] = 0xc0000000; - props[1] = 0x20000000; - set_property(dev, "virtual-dma", (char *)props, 2 * sizeof(props[0])); - props[0] = 1; - set_property(dev, "#virtual-dma-size-cells", (char *)props, - sizeof(props[0])); - set_property(dev, "#virtual-dma-addr-cells", (char *)props, - sizeof(props[0])); - - set_property(dev, "no-streaming-cache", (char *)props, 0); - - props[0] = 0x000007f0; - props[1] = 0x000007ee; - props[2] = 0x000007ef; - props[3] = 0x000007e5; - set_property(dev, "interrupts", (char *)props, 4 * sizeof(props[0])); - props[0] = 0x0000001f; - set_property(dev, "upa-portid", (char *)props, 1 * sizeof(props[0])); - return 0; -} - -int sabre_config_cb(const pci_config_t *config) -{ - host_config_cb(config); - - return sabre_configure(get_cur_dev()); -} - -int bridge_config_cb(const pci_config_t *config) -{ - phandle_t aliases; - - aliases = find_dev("/aliases"); - set_property(aliases, "bridge", config->path, strlen(config->path) + 1); - - return 0; -} - -int ide_config_cb2 (const pci_config_t *config) -{ - ob_ide_init(config->path, - config->assigned[0] & ~0x0000000F, - (config->assigned[1] & ~0x0000000F) + 2, - config->assigned[2] & ~0x0000000F, - (config->assigned[3] & ~0x0000000F) + 2); - return 0; -} - -int eth_config_cb (const pci_config_t *config) -{ - phandle_t ph = get_cur_dev(); - - set_property(ph, "network-type", "ethernet", 9); - set_property(ph, "removable", "network", 8); - set_property(ph, "category", "net", 4); - - return 0; -} - -static inline void pci_decode_pci_addr(pci_addr addr, int *flags, - int *space_code, uint32_t *mask) -{ - *flags = 0; - - if (addr & 0x01) { - *space_code = IO_SPACE; - *mask = 0x00000001; - } else { - if (addr & 0x04) { - *space_code = MEMORY_SPACE_64; - *flags |= IS_NOT_RELOCATABLE; /* XXX: why not relocatable? */ - } else { - *space_code = MEMORY_SPACE_32; - } - - if (addr & 0x08) { - *flags |= IS_PREFETCHABLE; - } - - *mask = 0x0000000F; - } -} - -/* - * "Designing PCI Cards and Drivers for Power Macintosh Computers", p. 454 - * - * "AAPL,address" provides an array of 32-bit logical addresses - * Nth entry corresponding to Nth "assigned-address" base address entry. - */ - -static void pci_set_AAPL_address(const pci_config_t *config) -{ - phandle_t dev = get_cur_dev(); - cell props[7]; - uint32_t mask; - int ncells, i, flags, space_code; - - ncells = 0; - for (i = 0; i < 6; i++) { - if (!config->assigned[i] || !config->sizes[i]) - continue; - pci_decode_pci_addr(config->assigned[i], - &flags, &space_code, &mask); - - props[ncells++] = pci_bus_addr_to_host_addr(space_code, - config->assigned[i] & ~mask); - } - if (ncells) - set_property(dev, "AAPL,address", (char *)props, - ncells * sizeof(cell)); -} - -static void pci_set_assigned_addresses(phandle_t phandle, - const pci_config_t *config, int num_bars) -{ - phandle_t dev = phandle; - u32 props[32]; - int ncells; - int i; - uint32_t mask; - int flags, space_code; - - ncells = 0; - for (i = 0; i < num_bars; i++) { - /* consider only bars with non-zero region size */ - if (!config->sizes[i]) - continue; - pci_decode_pci_addr(config->assigned[i], - &flags, &space_code, &mask); - - ncells += pci_encode_phys_addr(props + ncells, - flags, space_code, config->dev, - PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)), - config->assigned[i] & ~mask); - - props[ncells++] = 0x00000000; - props[ncells++] = config->sizes[i]; - } - if (ncells) - set_property(dev, "assigned-addresses", (char *)props, - ncells * sizeof(props[0])); -} - -/* call after writing "reg" property to update config->path */ -static void ob_pci_reload_device_path(phandle_t phandle, pci_config_t *config) -{ - /* since "name" and "reg" are now assigned - we need to reload current node name */ - - PUSH(phandle); - fword("get-package-path"); - char *new_path = pop_fstr_copy(); - if (new_path) { - if (0 != strcmp(config->path, new_path)) { - PCI_DPRINTF("\n=== CHANGED === package path old=%s new=%s\n", - config->path, new_path); - strncpy(config->path, new_path, sizeof(config->path)); - config->path[sizeof(config->path)-1] = '\0'; - } - free(new_path); - } else { - PCI_DPRINTF("\n=== package path old=%s new=NULL\n", config->path); - } -} - -static void pci_set_reg(phandle_t phandle, - pci_config_t *config, int num_bars) -{ - phandle_t dev = phandle; - u32 props[38]; - int ncells; - int i; - uint32_t mask; - int space_code, flags; - - ncells = 0; - - /* first (addr, size) pair is the beginning of configuration address space */ - ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, - config->dev, 0, 0); - - ncells += pci_encode_size(props + ncells, 0); - - for (i = 0; i < num_bars; i++) { - /* consider only bars with non-zero region size */ - if (!config->sizes[i]) - continue; - - pci_decode_pci_addr(config->regions[i], - &flags, &space_code, &mask); - - ncells += pci_encode_phys_addr(props + ncells, - flags, space_code, config->dev, - PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)), - config->regions[i] & ~mask); - - /* set size */ - ncells += pci_encode_size(props + ncells, config->sizes[i]); - } - - set_property(dev, "reg", (char *)props, ncells * sizeof(props[0])); - ob_pci_reload_device_path(dev, config); - -#if defined(CONFIG_DEBUG_PCI) - dump_reg_property("pci_set_reg", ncells, props); -#endif -} - - -static void pci_set_ranges(const pci_config_t *config) -{ - phandle_t dev = get_cur_dev(); - u32 props[32]; - int ncells; - int i; - uint32_t mask; - int flags; - int space_code; - - ncells = 0; - for (i = 0; i < 6; i++) { - if (!config->assigned[i] || !config->sizes[i]) - continue; - - /* child address */ - - props[ncells++] = 0x00000000; - - /* parent address */ - - pci_decode_pci_addr(config->assigned[i], - &flags, &space_code, &mask); - ncells += pci_encode_phys_addr(props + ncells, flags, space_code, - config->dev, 0x10 + i * 4, - config->assigned[i] & ~mask); - - /* size */ - - props[ncells++] = config->sizes[i]; - } - set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0])); -} - -int macio_heathrow_config_cb (const pci_config_t *config) -{ - pci_set_ranges(config); - -#ifdef CONFIG_DRIVER_MACIO - ob_macio_heathrow_init(config->path, config->assigned[0] & ~0x0000000F); -#endif - return 0; -} - -int macio_keylargo_config_cb (const pci_config_t *config) -{ - pci_set_ranges(config); - -#ifdef CONFIG_DRIVER_MACIO - ob_macio_keylargo_init(config->path, config->assigned[0] & ~0x0000000F); -#endif - return 0; -} - -int vga_config_cb (const pci_config_t *config) -{ - unsigned long rom; - uint32_t rom_size, size, mask; - int flags, space_code; - phandle_t ph; - - if (config->assigned[0] != 0x00000000) { - setup_video(); - - pci_decode_pci_addr(config->assigned[1], - &flags, &space_code, &mask); - - rom = pci_bus_addr_to_host_addr(space_code, - config->assigned[1] & ~0x0000000F); - - rom_size = config->sizes[1]; - - ph = get_cur_dev(); - - if (rom_size >= 8) { - const char *p; - - p = (const char *)rom; - if (p[0] == 'N' && p[1] == 'D' && p[2] == 'R' && p[3] == 'V') { - size = *(uint32_t*)(p + 4); - set_property(ph, "driver,AAPL,MacOS,PowerPC", p + 8, size); - } - } - - /* Currently we don't read FCode from the hardware but execute it directly */ - feval("['] vga-driver-fcode 2 cells + 1 byte-load"); - -#ifdef CONFIG_MOL - /* Install special words for Mac On Linux */ - molvideo_init(); -#endif - - } - - return 0; -} - -int ebus_config_cb(const pci_config_t *config) -{ -#ifdef CONFIG_DRIVER_EBUS - phandle_t dev = get_cur_dev(); - uint32_t props[12]; - int ncells; - int i; - uint32_t mask; - int flags, space_code; - - props[0] = 0x14; - props[1] = 0x3f8; - props[2] = 1; - props[3] = find_dev("/"); - props[4] = 0x2b; - set_property(dev, "interrupt-map", (char *)props, 5 * sizeof(props[0])); - - props[0] = 0x000001ff; - props[1] = 0xffffffff; - props[2] = 3; - set_property(dev, "interrupt-map-mask", (char *)props, 3 * sizeof(props[0])); - - /* Build ranges property from the BARs */ - ncells = 0; - for (i = 0; i < 6; i++) { - /* consider only bars with non-zero region size */ - if (!config->sizes[i]) - continue; - - pci_decode_pci_addr(config->assigned[i], - &flags, &space_code, &mask); - - props[ncells++] = PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)); - props[ncells++] = 0x0; - - ncells += pci_encode_phys_addr(props + ncells, - flags, space_code, config->dev, - PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)), - config->assigned[i] & ~mask); - - props[ncells++] = config->sizes[i]; - } - - set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0])); - - /* Build eeprom node */ - fword("new-device"); - PUSH(0x14); - fword("encode-int"); - PUSH(0x2000); - fword("encode-int"); - fword("encode+"); - PUSH(0x2000); - fword("encode-int"); - fword("encode+"); - push_str("reg"); - fword("property"); - - push_str("mk48t59"); - fword("model"); - - push_str("eeprom"); - fword("device-name"); - fword("finish-device"); - -#ifdef CONFIG_DRIVER_FLOPPY - ob_floppy_init(config->path, "fdthree", 0x3f0ULL, 0); -#endif -#ifdef CONFIG_DRIVER_PC_SERIAL - ob_pc_serial_init(config->path, "su", (PCI_BASE_ADDR_1 | 0ULL) << 32, 0x3f8ULL, 0); -#endif -#ifdef CONFIG_DRIVER_PC_KBD - ob_pc_kbd_init(config->path, "kb_ps2", (PCI_BASE_ADDR_1 | 0ULL) << 32, 0x60ULL, 0); -#endif -#endif - return 0; -} - -int i82378_config_cb(const pci_config_t *config) -{ -#ifdef CONFIG_DRIVER_PC_SERIAL - ob_pc_serial_init(config->path, "serial", arch->io_base, 0x3f8ULL, 0); -#endif -#ifdef CONFIG_DRIVER_PC_KBD - ob_pc_kbd_init(config->path, "8042", arch->io_base, 0x60ULL, 0); -#endif -#ifdef CONFIG_DRIVER_IDE - ob_ide_init(config->path, 0x1f0, 0x3f6, 0x170, 0x376); -#endif - - return 0; -} - -int usb_ohci_config_cb(const pci_config_t *config) -{ -#ifdef CONFIG_DRIVER_USB - ob_usb_ohci_init(config->path, 0x80000000 | config->dev); -#endif - return 0; -} - -static void ob_pci_add_properties(phandle_t phandle, - pci_addr addr, const pci_dev_t *pci_dev, - const pci_config_t *config, int num_bars) -{ - /* cannot use get_cur_dev() path resolution since "name" and "reg" - properties are being changed */ - phandle_t dev=phandle; - int status,id; - uint16_t vendor_id, device_id; - uint8_t rev; - uint8_t class_prog; - uint32_t class_code; - - vendor_id = pci_config_read16(addr, PCI_VENDOR_ID); - device_id = pci_config_read16(addr, PCI_DEVICE_ID); - rev = pci_config_read8(addr, PCI_REVISION_ID); - class_prog = pci_config_read8(addr, PCI_CLASS_PROG); - class_code = pci_config_read16(addr, PCI_CLASS_DEVICE); - - if (pci_dev) { - /**/ - if (pci_dev->name) { - push_str(pci_dev->name); - fword("encode-string"); - push_str("name"); - fword("property"); - } else { - char path[256]; - snprintf(path, sizeof(path), - "pci%x,%x", vendor_id, device_id); - push_str(path); - fword("encode-string"); - push_str("name"); - fword("property"); - } - } else { - PCI_DPRINTF("*** missing pci_dev\n"); - } - - /* create properties as described in 2.5 */ - - set_int_property(dev, "vendor-id", vendor_id); - set_int_property(dev, "device-id", device_id); - set_int_property(dev, "revision-id", rev); - set_int_property(dev, "class-code", class_code << 8 | class_prog); - - if (config->irq_pin) { - OLDWORLD(set_int_property(dev, "AAPL,interrupts", - config->irq_line)); -#if defined(CONFIG_SPARC64) - set_int_property(dev, "interrupts", config->irq_pin); -#else - NEWWORLD(set_int_property(dev, "interrupts", config->irq_pin)); -#endif - } - - set_int_property(dev, "min-grant", pci_config_read8(addr, PCI_MIN_GNT)); - set_int_property(dev, "max-latency", pci_config_read8(addr, PCI_MAX_LAT)); - - status=pci_config_read16(addr, PCI_STATUS); - - set_int_property(dev, "devsel-speed", - (status&PCI_STATUS_DEVSEL_MASK)>>10); - - if(status&PCI_STATUS_FAST_BACK) - set_bool_property(dev, "fast-back-to-back"); - if(status&PCI_STATUS_66MHZ) - set_bool_property(dev, "66mhz-capable"); - if(status&PCI_STATUS_UDF) - set_bool_property(dev, "udf-supported"); - - id=pci_config_read16(addr, PCI_SUBSYSTEM_VENDOR_ID); - if(id) - set_int_property(dev, "subsystem-vendor-id", id); - id=pci_config_read16(addr, PCI_SUBSYSTEM_ID); - if(id) - set_int_property(dev, "subsystem-id", id); - - set_int_property(dev, "cache-line-size", - pci_config_read16(addr, PCI_CACHE_LINE_SIZE)); - - if (pci_dev) { - if (pci_dev->type) { - push_str(pci_dev->type); - fword("encode-string"); - push_str("device_type"); - fword("property"); - } - if (pci_dev->model) { - push_str(pci_dev->model); - fword("encode-string"); - push_str("model"); - fword("property"); - } - if (pci_dev->compat) - set_property(dev, "compatible", - pci_dev->compat, pci_compat_len(pci_dev)); - - if (pci_dev->acells) - set_int_property(dev, "#address-cells", - pci_dev->acells); - if (pci_dev->scells) - set_int_property(dev, "#size-cells", - pci_dev->scells); - if (pci_dev->icells) - set_int_property(dev, "#interrupt-cells", - pci_dev->icells); - } - - pci_set_assigned_addresses(phandle, config, num_bars); - - if (is_apple()) { - pci_set_AAPL_address(config); - } - - PCI_DPRINTF("\n"); -} - -#ifdef CONFIG_XBOX -static char pci_xbox_blacklisted (int bus, int devnum, int fn) -{ - /* - * The Xbox MCPX chipset is a derivative of the nForce 1 - * chipset. It almost has the same bus layout; some devices - * cannot be used, because they have been removed. - */ - - /* - * Devices 00:00.1 and 00:00.2 used to be memory controllers on - * the nForce chipset, but on the Xbox, using them will lockup - * the chipset. - */ - if ((bus == 0) && (devnum == 0) && ((fn == 1) || (fn == 2))) - return 1; - - /* - * Bus 1 only contains a VGA controller at 01:00.0. When you try - * to probe beyond that device, you only get garbage, which - * could cause lockups. - */ - if ((bus == 1) && ((devnum != 0) || (fn != 0))) - return 1; - - /* - * Bus 2 used to contain the AGP controller, but the Xbox MCPX - * doesn't have one. Probing it can cause lockups. - */ - if (bus >= 2) - return 1; - - /* - * The device is not blacklisted. - */ - return 0; -} -#endif - -static void ob_pci_configure_bar(pci_addr addr, pci_config_t *config, - int reg, int config_addr, - uint32_t *p_omask, - unsigned long *mem_base, - unsigned long *io_base) -{ - uint32_t smask, amask, size, reloc, min_align; - unsigned long base; - - config->assigned[reg] = 0x00000000; - config->sizes[reg] = 0x00000000; - - if ((*p_omask & 0x0000000f) == 0x4) { - /* 64 bits memory mapping */ - PCI_DPRINTF("Skipping 64 bit BARs for %s\n", config->path); - return; - } - - config->regions[reg] = pci_config_read32(addr, config_addr); - - /* get region size */ - - pci_config_write32(addr, config_addr, 0xffffffff); - smask = pci_config_read32(addr, config_addr); - if (smask == 0x00000000 || smask == 0xffffffff) - return; - - if (smask & 0x00000001 && reg != 6) { - /* I/O space */ - base = *io_base; - min_align = 1 << 7; - amask = 0x00000001; - } else { - /* Memory Space */ - base = *mem_base; - min_align = 1 << 16; - amask = 0x0000000F; - if (reg == 6) { - smask |= 1; /* ROM */ - } - } - *p_omask = smask & amask; - smask &= ~amask; - size = (~smask) + 1; - config->sizes[reg] = size; - reloc = base; - if (size < min_align) - size = min_align; - reloc = (reloc + size -1) & ~(size - 1); - if (*io_base == base) { - PCI_DPRINTF("changing io_base from 0x%lx to 0x%x\n", - *io_base, reloc + size); - *io_base = reloc + size; - } else { - PCI_DPRINTF("changing mem_base from 0x%lx to 0x%x\n", - *mem_base, reloc + size); - *mem_base = reloc + size; - } - PCI_DPRINTF("Configuring BARs for %s: reloc 0x%x omask 0x%x " - "io_base 0x%lx mem_base 0x%lx size 0x%x\n", - config->path, reloc, *p_omask, *io_base, *mem_base, size); - pci_config_write32(addr, config_addr, reloc | *p_omask); - config->assigned[reg] = reloc | *p_omask; -} - -static void ob_pci_configure_irq(pci_addr addr, pci_config_t *config) -{ - uint8_t irq_pin, irq_line; - - irq_pin = pci_config_read8(addr, PCI_INTERRUPT_PIN); - if (irq_pin) { - config->irq_pin = irq_pin; - irq_pin = (((config->dev >> 11) & 0x1F) + irq_pin - 1) & 3; - irq_line = arch->irqs[irq_pin]; - pci_config_write8(addr, PCI_INTERRUPT_LINE, irq_line); - config->irq_line = irq_line; - } else - config->irq_line = -1; -} - -static void -ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar, - unsigned long *mem_base, unsigned long *io_base) - -{ - uint32_t omask; - uint16_t cmd; - int reg; - pci_addr config_addr; - - ob_pci_configure_irq(addr, config); - - omask = 0x00000000; - for (reg = 0; reg < num_regs; ++reg) { - config_addr = PCI_BASE_ADDR_0 + reg * 4; - - ob_pci_configure_bar(addr, config, reg, config_addr, - &omask, mem_base, - io_base); - } - - if (rom_bar) { - config_addr = rom_bar; - ob_pci_configure_bar(addr, config, reg, config_addr, - &omask, mem_base, io_base); - } - cmd = pci_config_read16(addr, PCI_COMMAND); - cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY; - pci_config_write16(addr, PCI_COMMAND, cmd); -} - -static void ob_configure_pci_device(const char* parent_path, - int *bus_num, unsigned long *mem_base, unsigned long *io_base, - int bus, int devnum, int fn, int *p_is_multi); - -static void ob_scan_pci_bus(int *bus_num, unsigned long *mem_base, - unsigned long *io_base, const char *path, - int bus) -{ - int devnum, fn, is_multi; - - PCI_DPRINTF("\nScanning bus %d at %s...\n", bus, path); - - for (devnum = 0; devnum < 32; devnum++) { - is_multi = 0; - for (fn = 0; fn==0 || (is_multi && fn<8); fn++) { - ob_configure_pci_device(path, bus_num, mem_base, io_base, - bus, devnum, fn, &is_multi); - - } - } -} - -static void ob_configure_pci_bridge(pci_addr addr, - int *bus_num, unsigned long *mem_base, - unsigned long *io_base, - int primary_bus, pci_config_t *config) -{ - config->primary_bus = primary_bus; - pci_config_write8(addr, PCI_PRIMARY_BUS, config->primary_bus); - - config->secondary_bus = *bus_num; - pci_config_write8(addr, PCI_SECONDARY_BUS, config->secondary_bus); - - config->subordinate_bus = 0xff; - pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus); - - PCI_DPRINTF("scanning new pci bus %u under bridge %s\n", - config->secondary_bus, config->path); - - /* make pci bridge parent device, prepare for recursion */ - - ob_scan_pci_bus(bus_num, mem_base, io_base, - config->path, config->secondary_bus); - - /* bus scan updates *bus_num to last revealed pci bus number */ - config->subordinate_bus = *bus_num; - pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus); - - PCI_DPRINTF("bridge %s PCI bus primary=%d secondary=%d subordinate=%d\n", - config->path, config->primary_bus, config->secondary_bus, - config->subordinate_bus); - - pci_set_bus_range(config); -} - -static int ob_pci_read_identification(int bus, int devnum, int fn, - int *p_vid, int *p_did, - uint8_t *p_class, uint8_t *p_subclass) -{ - int vid, did; - uint32_t ccode; - pci_addr addr; - -#ifdef CONFIG_XBOX - if (pci_xbox_blacklisted (bus, devnum, fn)) - return; -#endif - addr = PCI_ADDR(bus, devnum, fn); - vid = pci_config_read16(addr, PCI_VENDOR_ID); - did = pci_config_read16(addr, PCI_DEVICE_ID); - - if (vid==0xffff || vid==0) { - return 0; - } - - if (p_vid) { - *p_vid = vid; - } - - if (p_did) { - *p_did = did; - } - - ccode = pci_config_read16(addr, PCI_CLASS_DEVICE); - - if (p_class) { - *p_class = ccode >> 8; - } - - if (p_subclass) { - *p_subclass = ccode; - } - - return 1; -} - -static void ob_configure_pci_device(const char* parent_path, - int *bus_num, unsigned long *mem_base, unsigned long *io_base, - int bus, int devnum, int fn, int *p_is_multi) -{ - int vid, did; - unsigned int htype; - pci_addr addr; - pci_config_t config = {}; - const pci_dev_t *pci_dev; - uint8_t class, subclass, iface; - int num_bars, rom_bar; - - phandle_t phandle = 0; - int is_host_bridge = 0; - - if (!ob_pci_read_identification(bus, devnum, fn, &vid, &did, &class, &subclass)) { - return; - } - - addr = PCI_ADDR(bus, devnum, fn); - iface = pci_config_read8(addr, PCI_CLASS_PROG); - - pci_dev = pci_find_device(class, subclass, iface, - vid, did); - - PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn, - vid, did); - - htype = pci_config_read8(addr, PCI_HEADER_TYPE); - - if (fn == 0) { - if (p_is_multi) { - *p_is_multi = htype & 0x80; - } - } - - /* stop adding host bridge accessible from it's primary bus - PCI host bridge is to be added by host code - */ - if (class == PCI_BASE_CLASS_BRIDGE && - subclass == PCI_SUBCLASS_BRIDGE_HOST) { - is_host_bridge = 1; - } - - if (is_host_bridge) { - /* reuse device tree node */ - PCI_DPRINTF("host bridge found - "); - snprintf(config.path, sizeof(config.path), - "%s", parent_path); - } else if (pci_dev == NULL || pci_dev->name == NULL) { - snprintf(config.path, sizeof(config.path), - "%s/pci%x,%x", parent_path, vid, did); - } - else { - snprintf(config.path, sizeof(config.path), - "%s/%s", parent_path, pci_dev->name); - } - - PCI_DPRINTF("%s - ", config.path); - - config.dev = addr & 0x00FFFFFF; - - switch (class) { - case PCI_BASE_CLASS_BRIDGE: - if (subclass != PCI_SUBCLASS_BRIDGE_HOST) { - REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle); - } - break; - case PCI_CLASS_DISPLAY: - REGISTER_NAMED_NODE_PHANDLE(ob_pci_empty_node, config.path, phandle); - break; - default: - REGISTER_NAMED_NODE_PHANDLE(ob_pci_simple_node, config.path, phandle); - break; - } - - if (is_host_bridge) { - phandle = find_dev(config.path); - - if (get_property(phandle, "vendor-id", NULL)) { - PCI_DPRINTF("host bridge already configured\n"); - return; - } - } - - activate_dev(phandle); - - if (htype & PCI_HEADER_TYPE_BRIDGE) { - num_bars = 2; - rom_bar = PCI_ROM_ADDRESS1; - } else { - num_bars = 6; - rom_bar = PCI_ROM_ADDRESS; - } - - ob_pci_configure(addr, &config, num_bars, rom_bar, - mem_base, io_base); - - ob_pci_add_properties(phandle, addr, pci_dev, &config, num_bars); - - if (!is_host_bridge) { - pci_set_reg(phandle, &config, num_bars); - } - - /* call device-specific configuration callback */ - if (pci_dev && pci_dev->config_cb) { - //activate_device(config.path); - pci_dev->config_cb(&config); - } - - /* device is configured so we may move it out of scope */ - device_end(); - - /* scan bus behind bridge device */ - //if (htype & PCI_HEADER_TYPE_BRIDGE && class == PCI_BASE_CLASS_BRIDGE) { - if ( class == PCI_BASE_CLASS_BRIDGE && - ( subclass == PCI_SUBCLASS_BRIDGE_PCI || - subclass == PCI_SUBCLASS_BRIDGE_HOST ) ) { - - if (subclass == PCI_SUBCLASS_BRIDGE_PCI) { - /* reserve next pci bus number for this PCI bridge */ - ++(*bus_num); - } - - ob_configure_pci_bridge(addr, bus_num, mem_base, io_base, bus, &config); - } -} - -static void ob_pci_set_available(phandle_t host, unsigned long mem_base, unsigned long io_base) -{ - /* Create an available property for both memory and IO space */ - uint32_t props[10]; - int ncells; - - ncells = 0; - ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, 0, 0, mem_base); - ncells += pci_encode_size(props + ncells, arch->mem_len - mem_base); - ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE, 0, 0, io_base); - ncells += pci_encode_size(props + ncells, arch->io_len - io_base); - - set_property(host, "available", (char *)props, ncells * sizeof(props[0])); -} - -/* Convert device/irq pin to interrupt property */ -#define SUN4U_INTERRUPT(dev, irq_pin) \ - ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f) - -static void ob_pci_host_set_interrupt_map(phandle_t host) -{ - phandle_t dnode = 0, pci_childnode = 0; - u32 props[128], intno; - int i, ncells, len; - u32 *val, addr; - char *reg; - -#if defined(CONFIG_PPC) - phandle_t target_node; - - /* Oldworld macs do interrupt maps differently */ - if (!is_newworld()) - return; - - dnode = dt_iterate_type(0, "open-pic"); - if (dnode) { - /* patch in openpic interrupt-parent properties */ - target_node = find_dev("/pci/mac-io"); - set_int_property(target_node, "interrupt-parent", dnode); - - target_node = find_dev("/pci/mac-io/escc/ch-a"); - set_int_property(target_node, "interrupt-parent", dnode); - - target_node = find_dev("/pci/mac-io/escc/ch-b"); - set_int_property(target_node, "interrupt-parent", dnode); - - target_node = find_dev("/pci/mac-io/escc-legacy/ch-a"); - set_int_property(target_node, "interrupt-parent", dnode); - - target_node = find_dev("/pci/mac-io/escc-legacy/ch-b"); - set_int_property(target_node, "interrupt-parent", dnode); - - /* QEMU only emulates 2 of the 3 ata buses currently */ - /* On a new world Mac these are not numbered but named by the - * ATA version they support. Thus we have: ata-3, ata-3, ata-4 - * On g3beige they all called just ide. - * We take 2 x ata-3 buses which seems to work for - * at least the clients we care about */ - target_node = find_dev("/pci/mac-io/ata-3@20000"); - set_int_property(target_node, "interrupt-parent", dnode); - - target_node = find_dev("/pci/mac-io/ata-3@21000"); - set_int_property(target_node, "interrupt-parent", dnode); - - target_node = find_dev("/pci/mac-io/via-cuda"); - set_int_property(target_node, "interrupt-parent", dnode); - - target_node = find_dev("/pci"); - set_int_property(target_node, "interrupt-parent", dnode); - } -#else - /* PCI host bridge is the default interrupt controller */ - dnode = host; -#endif - - /* Set interrupt-map for PCI devices with an interrupt pin present */ - ncells = 0; - - PUSH(host); - fword("child"); - pci_childnode = POP(); - while (pci_childnode) { - intno = get_int_property(pci_childnode, "interrupts", &len); - if (len && intno) { - reg = get_property(pci_childnode, "reg", &len); - if (len && reg) { - val = (u32 *)reg; - - for (i = 0; i < (len / sizeof(u32)); i += 5) { - addr = val[i]; - - /* Device address is in 1st 32-bit word of encoded PCI address for config space */ - if ((addr & PCI_RANGE_TYPE_MASK) == PCI_RANGE_CONFIG) { -#if defined(CONFIG_SPARC64) - ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0); - props[ncells++] = intno; - props[ncells++] = dnode; - props[ncells++] = SUN4U_INTERRUPT(addr, intno); -#elif defined(CONFIG_PPC) - ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0); - props[ncells++] = intno; - props[ncells++] = dnode; - props[ncells++] = arch->irqs[intno - 1]; - props[ncells++] = 3; -#else - /* Keep compiler quiet */ - dnode = dnode; -#endif - } - } - } - } - - PUSH(pci_childnode); - fword("peer"); - pci_childnode = POP(); - } - set_property(host, "interrupt-map", (char *)props, ncells * sizeof(props[0])); - - props[0] = 0x0000f800; - props[1] = 0x0; - props[2] = 0x0; - props[3] = 0x7; - set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); -} - -int ob_pci_init(void) -{ - int bus, devnum, fn; - uint8_t class, subclass; - unsigned long mem_base, io_base; - - pci_config_t config = {}; /* host bridge */ - phandle_t phandle_host = 0; - - PCI_DPRINTF("Initializing PCI host bridge...\n"); - - activate_device("/"); - - /* Find all PCI bridges */ - - mem_base = arch->pci_mem_base; - /* I/O ports under 0x400 are used by devices mapped at fixed - location. */ - io_base = 0x400; - - bus = 0; - - for (devnum = 0; devnum < 32; devnum++) { - /* scan only fn 0 */ - fn = 0; - - if (!ob_pci_read_identification(bus, devnum, fn, - 0, 0, &class, &subclass)) { - continue; - } - - if (class != PCI_BASE_CLASS_BRIDGE || subclass != PCI_SUBCLASS_BRIDGE_HOST) { - continue; - } - - /* create root node for host PCI bridge */ - - /* configure */ - snprintf(config.path, sizeof(config.path), "/pci"); - - REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle_host); - - pci_host_set_reg(phandle_host); - - /* update device path after changing "reg" property */ - ob_pci_reload_device_path(phandle_host, &config); - - ob_configure_pci_device(config.path, &bus, &mem_base, &io_base, - bus, devnum, fn, 0); - - /* we expect single host PCI bridge - but this may be machine-specific */ - break; - } - - /* create available attributes for the PCI bridge */ - ob_pci_set_available(phandle_host, mem_base, io_base); - - /* configure the host bridge interrupt map */ - ob_pci_host_set_interrupt_map(phandle_host); - - device_end(); - - return 0; -} |