1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12/* Virtual PCI devices - allows rebasing base addresses. 13 14 Example usage: 15 d = libpci_find_device(0x1022, 0x2000); assert(d); 16 v = vpci->vdevice_assign(vpci); assert(v); 17 v->enable(v, d->bus, d->dev, d->fun, d); 18 v->rebase_ioaddr_realdevice(v, 0, 0x3000, d); 19 */ 20#pragma once 21 22#include <stdint.h> 23#include <stdbool.h> 24#include <pci/pci.h> 25#include <pci/pci_config.h> 26 27/* Passthrough any config space writes straight onto real device. 28 Make sure vdevice->physical_device_passthrough is set. */ 29#define PCI_VDEVICE_MODE_PASSTHROUGH 0 30 31/* Debug mode which asserts and while(1); when read/write is attempted. */ 32#define PCI_VDEVICE_MODE_FATAL_ERROR 1 33 34/* Invoke a callback function on read/write to this config space byte. */ 35#define PCI_VDEVICE_MODE_CALLBACK 2 36 37/* Only used by rebase_addr_* functions. Rebased addrs and callbacks cannot 38 be used at same time */ 39#define PCI_VDEVICE_MODE_REBASED_ADDR 3 40 41struct libpci_vdevice; 42typedef struct libpci_vdevice libpci_vdevice_t; 43 44typedef struct libpci_vdevice_mode { 45 int mode; /* PCI_VDEVICE_MODE_* */ 46 uint8_t (*callback_ioread) (libpci_vdevice_t* vdevice, int offset); 47 void (*callback_iowrite) (libpci_vdevice_t* vdevice, int offset, uint8_t val); 48} libpci_vdevice_mode_t; 49 50struct libpci_vdevice { 51 bool enabled; 52 bool allow_extended_pci_config_space; 53 54 uint8_t location_bus; 55 uint8_t location_dev; 56 uint8_t location_fun; 57 58 /* Per-byte device config space virtualisation mode. */ 59 libpci_vdevice_mode_t mode[PCI_CONFIG_HEADER_SIZE_BYTES]; 60 /* Which physical device to pass through. */ 61 libpci_device_t* physical_device_passthrough; 62 63 uint32_t rebased_addr[6]; 64 uint32_t rebased_writemask[6]; 65 uint32_t rebased_type[6]; 66 67 void (*enable) (libpci_vdevice_t* self, uint8_t bus, uint8_t dev, uint8_t fun, 68 libpci_device_t* pdevice_passthrough /* may be NULL. */); 69 70 void (*disable) (libpci_vdevice_t* self); 71 72 bool (*match) (libpci_vdevice_t* self, uint8_t bus, uint8_t dev, uint8_t fun); 73 74 void (*set_mode) (libpci_vdevice_t* self, 75 int offset, /* 0 ... PCI_STD_HEADER_SIZEOF - 1 */ 76 libpci_vdevice_mode_t m /* The mode to set it to */ 77 ); 78 79 /* implicitly sets physical_device_passthrough to the given device. */ 80 void (*rebase_addr_realdevice) (libpci_vdevice_t* self, 81 int base_addr_index, /* 0 ... 5 */ 82 uint32_t base_addr, /* correctly aligned new address. */ 83 libpci_device_t* dev /* contains physical device info */ 84 ); 85 86 /* implicitly sets physical_device_passthrough to the given device. */ 87 void (*rebase_ioaddr_realdevice) (libpci_vdevice_t* self, 88 int base_addr_index, /* 0 ... 5 */ 89 uint32_t base_addr, /* correctly aligned new address. */ 90 libpci_device_t* dev /* contains physical device info */ 91 ); 92 93 void (*rebase_addr_virtdevice) (libpci_vdevice_t* self, 94 int base_addr_index, /* 0 ... 5 */ 95 uint32_t base_addr, /* correctly aligned new address. */ 96 uint32_t size_mask, /* the size mask. last 3 bits must be 0. */ 97 bool prefetch, /* prefetchable? */ 98 bool LWord64 /* Is this address the LWORD of a 64-bit address? */ 99 ); 100 101 void (*rebase_ioaddr_virtdevice) (libpci_vdevice_t* self, 102 int base_addr_index, /* 0 ... 5 */ 103 uint32_t base_addr, /* correctly aligned new address. */ 104 uint32_t size_mask /* the size mask. last 3 bits must be 0. */ 105 ); 106 107 uint32_t (*ioread) (libpci_vdevice_t* self, 108 int offset /* 0 ... PCI_STD_HEADER_SIZEOF - 1 */, 109 int size /* 1, 2 or 4 */); 110 111 void (*iowrite) (libpci_vdevice_t* self, 112 int offset /* 0 ... PCI_STD_HEADER_SIZEOF - 1 */, 113 int size /* 1, 2 or 4 */, 114 uint32_t val); 115}; 116 117void libpci_vdevice_init(libpci_vdevice_t* vd); 118