|  | /* | 
|  | * Copyright 2017, Data61 | 
|  | * Commonwealth Scientific and Industrial Research Organisation (CSIRO) | 
|  | * ABN 41 687 119 230. | 
|  | * | 
|  | * This software may be distributed and modified according to the terms of | 
|  | * the GNU General Public License version 2. Note that NO WARRANTY is provided. | 
|  | * See "LICENSE_GPLv2.txt" for details. | 
|  | * | 
|  | * @TAG(DATA61_GPL) | 
|  | */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #include <stdint.h> | 
|  | #include <pci/pci.h> | 
|  |  | 
|  | #include "vmm/driver/pci.h" | 
|  | #include "vmm/vmm.h" | 
|  |  | 
|  | /* Struct definition of a PCI device. This is used for emulating a device from | 
|  | * purely memory reads. This is not generally useful on its own, but provides | 
|  | * a nice skeleton */ | 
|  | typedef struct vmm_pci_device_def { | 
|  | uint16_t vendor_id; | 
|  | uint16_t device_id; | 
|  | uint16_t command; | 
|  | uint16_t status; | 
|  | uint8_t revision_id; | 
|  | uint8_t prog_if; | 
|  | uint8_t subclass; | 
|  | uint8_t class_code; | 
|  | uint8_t cache_line_size; | 
|  | uint8_t latency_timer; | 
|  | uint8_t header_type; | 
|  | uint8_t bist; | 
|  | uint32_t bar0; | 
|  | uint32_t bar1; | 
|  | uint32_t bar2; | 
|  | uint32_t bar3; | 
|  | uint32_t bar4; | 
|  | uint32_t bar5; | 
|  | uint32_t cardbus; | 
|  | uint16_t subsystem_vendor_id; | 
|  | uint16_t subsystem_id; | 
|  | uint32_t expansion_rom; | 
|  | uint8_t caps_pointer; | 
|  | uint8_t reserved1; | 
|  | uint16_t reserved2; | 
|  | uint32_t reserved3; | 
|  | uint8_t interrupt_line; | 
|  | uint8_t interrupt_pin; | 
|  | uint8_t min_grant; | 
|  | uint8_t max_latency; | 
|  | /* Now additional pointer to arbitrary capabilities */ | 
|  | int caps_len; | 
|  | void *caps; | 
|  | } __attribute__((packed)) vmm_pci_device_def_t; | 
|  |  | 
|  | typedef struct vmm_pci_bar { | 
|  | int ismem; | 
|  | /* Address must be size aligned */ | 
|  | uintptr_t address; | 
|  | int size_bits; | 
|  | /* only if memory */ | 
|  | int prefetchable; | 
|  | } vmm_pci_bar_t; | 
|  |  | 
|  | /* Helper write function that just ignores any writes */ | 
|  | int vmm_pci_entry_ignore_write(void *cookie, int offset, int size, uint32_t value); | 
|  |  | 
|  | /* Read and write methods for a memory device */ | 
|  | int vmm_pci_mem_device_read(void *cookie, int offset, int size, uint32_t *result); | 
|  | int vmm_pci_mem_device_write(void *cookie, int offset, int size, uint32_t value); | 
|  |  | 
|  | void define_pci_host_bridge(vmm_pci_device_def_t *bridge); | 
|  |  | 
|  | /* Construct a pure passthrough device based on the real PCI. This is almost always useless as | 
|  | * you will almost certainly want to rebase io memory */ | 
|  | vmm_pci_entry_t vmm_pci_create_passthrough(vmm_pci_address_t addr, vmm_pci_config_t config); | 
|  |  | 
|  | /* Bar read/write emulation, rest passed on */ | 
|  | vmm_pci_entry_t vmm_pci_create_bar_emulation(vmm_pci_entry_t existing, int num_bars, vmm_pci_bar_t *bars); | 
|  |  | 
|  | /* Interrupt read/write emulation, rest passed on */ | 
|  | vmm_pci_entry_t vmm_pci_create_irq_emulation(vmm_pci_entry_t existing, int irq); | 
|  |  | 
|  | /* Capability space emulation. Takes list of addresses to use to form a capability | 
|  | * linked list, as well as a ranges of the capability space that should be | 
|  | * directly disallowed. Assumes a type 0 device. | 
|  | */ | 
|  | vmm_pci_entry_t vmm_pci_create_cap_emulation(vmm_pci_entry_t existing, int num_caps, uint8_t *caps, int num_ranges, uint8_t *range_starts, uint8_t *range_ends); | 
|  |  | 
|  | /* Finds the MSI capabilities and uses vmm_pci_create_cap_emulation to remove them */ | 
|  | vmm_pci_entry_t vmm_pci_no_msi_cap_emulation(vmm_pci_entry_t existing); | 
|  |  | 
|  | /* Takes a libpci device scan and adds the bar resources to the guest, creating | 
|  | * new pci bar information that can be passed to a virtual config space creator. | 
|  | * Creates at most 6 bars, returns how many it created, negative on error */ | 
|  | int vmm_pci_helper_map_bars(vmm_t *vmm, libpci_device_iocfg_t *cfg, vmm_pci_bar_t *bars); | 
|  |  |