/* * \brief PCI device component implementation * \author Alexander Boettcher */ /* * Copyright (C) 2015 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 "pci_session_component.h" #include "pci_device_component.h" Genode::Io_port_session_capability Pci::Device_component::io_port(Genode::uint8_t v_id) { Genode::uint8_t max = sizeof(_io_port_conn) / sizeof(_io_port_conn[0]); Genode::uint8_t i = 0, r_id = 0; for (Resource res = resource(0); i < max; i++, res = resource(i)) { if (res.type() != Resource::IO) continue; if (v_id != r_id) { r_id ++; continue; } if (_io_port_conn[v_id] == nullptr) _io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(res.base(), res.size()); return _io_port_conn[v_id]->cap(); } return Genode::Io_port_session_capability(); } Genode::Io_mem_session_capability Pci::Device_component::io_mem(Genode::uint8_t v_id) { Genode::uint8_t max = sizeof(_io_mem_conn) / sizeof(_io_mem_conn[0]); Genode::uint8_t i = 0, r_id = 0; for (Resource res = resource(0); i < max; i++, res = resource(i)) { if (res.type() != Resource::MEMORY) continue; if (v_id != r_id) { r_id ++; continue; } if (_io_mem_conn[v_id] == nullptr) _io_mem_conn[v_id] = new (_slab_iomem) Genode::Io_mem_connection(res.base(), res.size()); return _io_mem_conn[v_id]->cap(); } return Genode::Io_mem_session_capability(); } void Pci::Device_component::config_write(unsigned char address, unsigned value, Access_size size) { /* white list of ports which we permit to write */ switch (address) { case 0x40 ... 0xff: /* allow access to device-specific registers */ break; case PCI_CMD_REG: /* COMMAND register - first byte */ if (size == Access_size::ACCESS_16BIT) break; case PCI_CMD_REG + 1: /* COMMAND register - second byte */ case 0xd: /* Latency timer */ if (size == Access_size::ACCESS_8BIT) break; case PCI_IRQ_LINE: /* permitted up to now solely for acpi driver */ if (address == PCI_IRQ_LINE && _rewrite_irq_line && size == Access_size::ACCESS_8BIT) break; default: PWRN("%x:%x:%x write access to address=%x value=0x%x " " size=0x%x got dropped", _device_config.bus_number(), _device_config.device_number(), _device_config.function_number(), address, value, size); return; } /* assign device to device_pd */ if (address == PCI_CMD_REG && value & PCI_CMD_DMA && _session) _session->assign_device(this); _device_config.write(&_config_access, address, value, size); }