pci_emul.h revision 221828
1/*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29#ifndef _PCI_EMUL_H_ 30#define _PCI_EMUL_H_ 31 32#include <sys/types.h> 33#include <sys/queue.h> 34#include <sys/kernel.h> 35 36#include <dev/pci/pcireg.h> 37 38#include <assert.h> 39 40#define PCI_BARMAX PCIR_MAX_BAR_0 /* BAR registers in a Type 0 header */ 41#define PCIY_RESERVED 0x00 42 43struct vmctx; 44struct pci_devinst; 45 46struct pci_devemu { 47 char *pe_emu; /* Name of device emulation */ 48 49 /* instance creation */ 50 int (*pe_init)(struct vmctx *, struct pci_devinst *, char *opts); 51 52 /* config space read/write callbacks */ 53 int (*pe_cfgwrite)(struct vmctx *ctx, int vcpu, 54 struct pci_devinst *pi, int offset, 55 int bytes, uint32_t val); 56 int (*pe_cfgread)(struct vmctx *ctx, int vcpu, 57 struct pci_devinst *pi, int offset, 58 int bytes, uint32_t *retval); 59 60 /* I/O space read/write callbacks */ 61 void (*pe_iow)(struct pci_devinst *pi, int baridx, 62 int offset, int size, uint32_t value); 63 uint32_t (*pe_ior)(struct pci_devinst *pi, int baridx, 64 int offset, int size); 65}; 66#define PCI_EMUL_SET(x) DATA_SET(pci_devemu_set, x); 67 68enum pcibar_type { 69 PCIBAR_NONE, 70 PCIBAR_IO, 71 PCIBAR_MEM32, 72 PCIBAR_MEM64, 73 PCIBAR_MEMHI64 74}; 75 76struct pcibar { 77 enum pcibar_type type; /* io or memory */ 78 uint64_t size; 79 uint64_t addr; 80}; 81 82#define PI_NAMESZ 40 83 84struct pci_devinst { 85 struct pci_devemu *pi_d; 86 struct vmctx *pi_vmctx; 87 uint8_t pi_bus, pi_slot, pi_func; 88 char pi_name[PI_NAMESZ]; 89 uint16_t pi_iobase; 90 int pi_bar_getsize; 91 92 struct { 93 int enabled; 94 int cpu; 95 int vector; 96 int msgnum; 97 } pi_msi; 98 99 void *pi_arg; /* devemu-private data */ 100 101 u_char pi_cfgdata[PCI_REGMAX + 1]; 102 struct pcibar pi_bar[PCI_BARMAX + 1]; 103}; 104 105struct msicap { 106 uint8_t capid; 107 uint8_t nextptr; 108 uint16_t msgctrl; 109 uint32_t addrlo; 110 uint32_t addrhi; 111 uint16_t msgdata; 112} __packed; 113 114void init_pci(struct vmctx *ctx); 115void pci_parse_slot(char *opt); 116void pci_parse_name(char *opt); 117void pci_callback(void); 118int pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, uint64_t hostbase, 119 enum pcibar_type type, uint64_t size); 120int pci_emul_add_msicap(struct pci_devinst *pi, int msgnum); 121void msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 122 int bytes, uint32_t val); 123 124void pci_generate_msi(struct pci_devinst *pi, int msgnum); 125int pci_msi_enabled(struct pci_devinst *pi); 126int pci_msi_msgnum(struct pci_devinst *pi); 127void pci_populate_msicap(struct msicap *cap, int msgs, int nextptr); 128 129static __inline void 130pci_set_cfgdata8(struct pci_devinst *pi, int offset, uint8_t val) 131{ 132 assert(offset <= PCI_REGMAX); 133 *(uint8_t *)(pi->pi_cfgdata + offset) = val; 134} 135 136static __inline void 137pci_set_cfgdata16(struct pci_devinst *pi, int offset, uint16_t val) 138{ 139 assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0); 140 *(uint16_t *)(pi->pi_cfgdata + offset) = val; 141} 142 143static __inline void 144pci_set_cfgdata32(struct pci_devinst *pi, int offset, uint32_t val) 145{ 146 assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0); 147 *(uint32_t *)(pi->pi_cfgdata + offset) = val; 148} 149 150static __inline uint8_t 151pci_get_cfgdata8(struct pci_devinst *pi, int offset) 152{ 153 assert(offset <= PCI_REGMAX); 154 return (*(uint8_t *)(pi->pi_cfgdata + offset)); 155} 156 157static __inline uint16_t 158pci_get_cfgdata16(struct pci_devinst *pi, int offset) 159{ 160 assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0); 161 return (*(uint16_t *)(pi->pi_cfgdata + offset)); 162} 163 164static __inline uint32_t 165pci_get_cfgdata32(struct pci_devinst *pi, int offset) 166{ 167 assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0); 168 return (*(uint32_t *)(pi->pi_cfgdata + offset)); 169} 170 171#endif /* _PCI_EMUL_H_ */ 172