1 /* $NetBSD: rumpdev_pci.c,v 1.5 2015/05/17 13:51:31 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2013 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: rumpdev_pci.c,v 1.5 2015/05/17 13:51:31 pooka Exp $"); 30 31 #include <sys/cdefs.h> 32 #include <sys/param.h> 33 #include <sys/atomic.h> 34 35 #include <dev/pci/pcivar.h> 36 37 #include "pci_user.h" 38 39 void 40 pci_attach_hook(device_t parent, device_t self, struct pcibus_attach_args *pba) 41 { 42 43 /* nada */ 44 } 45 46 int 47 pci_bus_maxdevs(pci_chipset_tag_t pc, int busno) 48 { 49 50 return 32; 51 } 52 53 pcitag_t 54 pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function) 55 { 56 pcitag_t pt; 57 int *tag; 58 unsigned csr; 59 int rv; 60 61 CTASSERT(sizeof(pt) >= sizeof(int)); 62 63 /* a "bit" ugly, but keeps us MI */ 64 tag = (int *)&pt; 65 *tag = (bus << 16) | (device << 8) | (function << 0); 66 67 /* 68 * On Xen, we need to enable the device io/mem space. 69 * Doesn't really belong here, but we need to do it somewhere. 70 */ 71 rv = rumpcomp_pci_confread(bus, device, function, 72 PCI_COMMAND_STATUS_REG, &csr); 73 if (rv == 0 && (csr & PCI_COMMAND_MEM_ENABLE) == 0) { 74 rumpcomp_pci_confwrite(bus, device, function, 75 PCI_COMMAND_STATUS_REG, csr | PCI_COMMAND_MEM_ENABLE); 76 } 77 78 return pt; 79 } 80 81 pcireg_t 82 pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) 83 { 84 unsigned int rv; 85 int bus, device, fun; 86 87 pci_decompose_tag(pc, tag, &bus, &device, &fun); 88 rumpcomp_pci_confread(bus, device, fun, reg, &rv); 89 return rv; 90 } 91 92 void 93 pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 94 { 95 int bus, device, fun; 96 97 pci_decompose_tag(pc, tag, &bus, &device, &fun); 98 rumpcomp_pci_confwrite(bus, device, fun, reg, data); 99 } 100 101 void 102 pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, 103 int *bp, int *dp, int *fp) 104 { 105 int *t = (int *)&tag; 106 107 *bp = (*t >> 16) & 0xff; 108 *dp = (*t >> 8) & 0xff; 109 *fp = (*t >> 0) & 0xff; 110 } 111 112 /* 113 * Well, yay, deal with the wonders of weird_t. We'll just 114 * assume it's an integral type (which, btw, isn't universally true). 115 * The hypercall will map "cookie" to its internal structure. 116 * Dial _t for a good time. 117 */ 118 int 119 pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih) 120 { 121 static unsigned int intrhandle; 122 unsigned cookie; 123 int rv; 124 125 cookie = atomic_inc_uint_nv(&intrhandle); 126 rv = rumpcomp_pci_irq_map(pa->pa_bus, 127 pa->pa_device, pa->pa_function, pa->pa_intrline, cookie); 128 if (rv == 0) 129 *ih = cookie; 130 return 0; 131 } 132 133 const char * 134 pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih, 135 char *buf, size_t buflen) 136 { 137 138 snprintf(buf, buflen, "pausebreak"); 139 return buf; 140 } 141 142 void * 143 pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, 144 int level, int (*func)(void *), void *arg) 145 { 146 147 return rumpcomp_pci_irq_establish(ih, func, arg); 148 } 149 150 int 151 pci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ih, 152 int attr, uint64_t data) 153 { 154 155 switch (attr) { 156 case PCI_INTR_MPSAFE: 157 return 0; 158 default: 159 return ENODEV; 160 } 161 } 162 163 void 164 pci_intr_disestablish(pci_chipset_tag_t pc, void *not_your_above_ih) 165 { 166 167 panic("%s: unimplemented", __func__); 168 } 169 170 #ifdef __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH 171 #include <dev/pci/pcireg.h> 172 #include <dev/pci/pcivar.h> 173 #include <dev/pci/pciidereg.h> 174 #include <dev/pci/pciidevar.h> 175 176 void * 177 pciide_machdep_compat_intr_establish(device_t dev, 178 const struct pci_attach_args *pa, int chan, 179 int (*func)(void *), void *arg) 180 { 181 pci_intr_handle_t ih; 182 struct pci_attach_args mypa = *pa; 183 184 mypa.pa_intrline = PCIIDE_COMPAT_IRQ(chan); 185 if (pci_intr_map(&mypa, &ih) != 0) 186 return NULL; 187 return rumpcomp_pci_irq_establish(ih, func, arg); 188 } 189 190 __strong_alias(pciide_machdep_compat_intr_disestablish,pci_intr_disestablish); 191 #endif /* __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH */ 192