/* * \brief PCI bus access * \author Christian Helmuth * \date 2008-10-22 * * We provide a virtual PCI bus hierarchy in pci_tree.cc: * * - Grab all accessible devices at pci_drv and populate virtual bus hierarchy. * (This also works if parents/device managers limit device access in the * future.) * - DDE kit C interface in pci.cc * - Read/write config space * - Convenience functions */ /* * Copyright (C) 2008-2013 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ #include #include extern "C" { #include #include } #include "pci_tree.h" #include "device.h" static const bool verbose = false; static Dde_kit::Pci_tree *pci_tree(unsigned device_class = 0, unsigned class_mask = 0) { static Dde_kit::Pci_tree _pci_tree(device_class, class_mask); return &_pci_tree; } /******************************** ** Configuration space access ** ********************************/ extern "C" void dde_kit_pci_readb(int bus, int dev, int fun, int pos, dde_kit_uint8_t *val) { try { *val = pci_tree()->config_read(bus, dev, fun, pos, Pci::Device::ACCESS_8BIT) & 0xff; } catch (...) { if (verbose) PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun); *val = ~0; } } extern "C" void dde_kit_pci_readw(int bus, int dev, int fun, int pos, dde_kit_uint16_t *val) { try { *val = pci_tree()->config_read(bus, dev, fun, pos, Pci::Device::ACCESS_16BIT) & 0xffff; } catch (...) { if (verbose) PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun); *val = ~0; } } extern "C" void dde_kit_pci_readl(int bus, int dev, int fun, int pos, dde_kit_uint32_t *val) { try { *val = pci_tree()->config_read(bus, dev, fun, pos, Pci::Device::ACCESS_32BIT); } catch (...) { if (verbose) PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun); *val = ~0; } } extern "C" void dde_kit_pci_writeb(int bus, int dev, int fun, int pos, dde_kit_uint8_t val) { try { pci_tree()->config_write(bus, dev, fun, pos, val, Pci::Device::ACCESS_8BIT); } catch (...) { if (verbose) PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun); } } extern "C" void dde_kit_pci_writew(int bus, int dev, int fun, int pos, dde_kit_uint16_t val) { try { pci_tree()->config_write(bus, dev, fun, pos, val, Pci::Device::ACCESS_16BIT); } catch (...) { if (verbose) PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun); } } extern "C" void dde_kit_pci_writel(int bus, int dev, int fun, int pos, dde_kit_uint32_t val) { try { pci_tree()->config_write(bus, dev, fun, pos, val, Pci::Device::ACCESS_32BIT); } catch (...) { if (verbose) PWRN("PCI device %02x:%02x.%x not found", bus, dev, fun); } } /*************************** ** Convenience functions ** ***************************/ extern "C" int dde_kit_pci_first_device(int *bus, int *dev, int *fun) { try { pci_tree()->first_device(bus, dev, fun); return 0; } catch (...) { return -1; } } extern "C" int dde_kit_pci_next_device(int *bus, int *dev, int *fun) { try { pci_tree()->next_device(bus, dev, fun); return 0; } catch (...) { return -1; } } extern "C" dde_kit_addr_t dde_kit_pci_alloc_dma_buffer(int bus, int dev, int fun, dde_kit_size_t size) { try { using namespace Genode; Ram_dataspace_capability ram_cap; ram_cap = pci_tree()->alloc_dma_buffer(bus, dev, fun, size); addr_t base = (addr_t)env()->rm_session()->attach(ram_cap); /* add to DDE-kit page tables */ addr_t phys = Dataspace_client(ram_cap).phys_addr(); dde_kit_pgtab_set_region_with_size((void *)base, phys, size); return base; } catch (...) { return 0; } } /******************** ** Initialization ** ********************/ extern "C" void dde_kit_pci_init(unsigned device_class, unsigned class_mask) { try { pci_tree(device_class, class_mask); } catch (...) { PERR("PCI initialization failed"); } }