1 /* $OpenBSD: xspd.c,v 1.5 2016/01/29 19:04:30 mikeb Exp $ */ 2 3 /* 4 * Copyright (c) 2015 Mike Belopuhov 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "xen.h" 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/atomic.h> 24 #include <sys/device.h> 25 #include <sys/task.h> 26 27 #include <dev/pci/pcireg.h> 28 #include <dev/pci/pcivar.h> 29 #include <dev/pci/pcidevs.h> 30 31 #include <machine/i82093var.h> 32 33 #include <dev/pv/xenreg.h> 34 #include <dev/pv/xenvar.h> 35 36 struct xspd_softc { 37 struct device sc_dev; 38 void * sc_ih; 39 }; 40 41 int xspd_match(struct device *, void *, void *); 42 void xspd_attach(struct device *, struct device *, void *); 43 int xspd_intr(void *); 44 45 struct cfdriver xspd_cd = { 46 NULL, "xspd", DV_DULL 47 }; 48 49 struct cfattach xspd_ca = { 50 sizeof(struct xspd_softc), xspd_match, xspd_attach, NULL, NULL 51 }; 52 53 const struct pci_matchid xspd_devices[] = { 54 { PCI_VENDOR_XENSOURCE, PCI_PRODUCT_XENSOURCE_PLATFORMDEV } 55 }; 56 57 int 58 xspd_match(struct device *parent, void *match, void *aux) 59 { 60 return (pci_matchbyid(aux, xspd_devices, nitems(xspd_devices))); 61 } 62 63 #if NXEN > 0 64 void 65 xspd_attach(struct device *parent, struct device *self, void *aux) 66 { 67 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 68 struct xspd_softc *sc = (struct xspd_softc *)self; 69 const char *intrstr = NULL; 70 pci_intr_handle_t ih; 71 struct xen_hvm_param xhp; 72 extern struct xen_softc *xen_sc; 73 74 if (xen_sc == NULL || (xen_sc->sc_flags & XSF_CBVEC)) { 75 printf("\n"); 76 return; 77 } 78 79 if (pci_intr_map(pa, &ih) != 0) { 80 printf(": couldn't map interrupt\n"); 81 return; 82 } 83 84 intrstr = pci_intr_string(pa->pa_pc, ih); 85 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET | IPL_MPSAFE, 86 xspd_intr, sc, sc->sc_dev.dv_xname); 87 if (sc->sc_ih == NULL) { 88 printf(": couldn't establish interrupt\n"); 89 if (intrstr != NULL) 90 printf(" at %s", intrstr); 91 printf("\n"); 92 return; 93 } 94 printf(": %s\n", intrstr); 95 96 xhp.domid = DOMID_SELF; 97 xhp.index = HVM_PARAM_CALLBACK_IRQ; 98 99 if (ih.line & APIC_INT_VIA_APIC) 100 xhp.value = HVM_CALLBACK_PCI_INTX(pa->pa_device, 101 pa->pa_intrpin - 1); 102 else 103 xhp.value = HVM_CALLBACK_GSI(pci_intr_line(pa->pa_pc, ih)); 104 105 if (xen_hypercall(xen_sc, XC_HVM, 2, HVMOP_set_param, &xhp)) { 106 printf("%s: failed to register callback PCI vector\n", 107 sc->sc_dev.dv_xname); 108 pci_intr_disestablish(pa->pa_pc, sc->sc_ih); 109 return; 110 } 111 112 xen_sc->sc_flags |= XSF_CBVEC; 113 } 114 115 int 116 xspd_intr(void *arg) 117 { 118 xen_intr(); 119 120 return (1); 121 } 122 #else 123 void 124 xspd_attach(struct device *parent, struct device *self, void *aux) 125 { 126 printf("\n"); 127 } 128 #endif /* NXEN > 0 */ 129 130