xref: /openbsd-src/sys/dev/pci/xspd.c (revision 8d2c75e49a1f1e140a0efd2b93f23844e8cb679f)
1*8d2c75e4Smpi /*	$OpenBSD: xspd.c,v 1.7 2022/03/11 18:00:52 mpi Exp $	*/
23de569e7Sreyk 
31863fb1eSmikeb /*
41863fb1eSmikeb  * Copyright (c) 2015 Mike Belopuhov
51863fb1eSmikeb  *
61863fb1eSmikeb  * Permission to use, copy, modify, and distribute this software for any
71863fb1eSmikeb  * purpose with or without fee is hereby granted, provided that the above
81863fb1eSmikeb  * copyright notice and this permission notice appear in all copies.
91863fb1eSmikeb  *
101863fb1eSmikeb  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
111863fb1eSmikeb  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
121863fb1eSmikeb  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
131863fb1eSmikeb  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
141863fb1eSmikeb  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
151863fb1eSmikeb  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
161863fb1eSmikeb  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
171863fb1eSmikeb  */
181863fb1eSmikeb 
191863fb1eSmikeb #include "xen.h"
201863fb1eSmikeb 
211863fb1eSmikeb #include <sys/param.h>
221863fb1eSmikeb #include <sys/systm.h>
231863fb1eSmikeb #include <sys/atomic.h>
241863fb1eSmikeb #include <sys/device.h>
25da2beeadSmikeb #include <sys/task.h>
261863fb1eSmikeb 
271863fb1eSmikeb #include <dev/pci/pcireg.h>
281863fb1eSmikeb #include <dev/pci/pcivar.h>
291863fb1eSmikeb #include <dev/pci/pcidevs.h>
301863fb1eSmikeb 
311863fb1eSmikeb #include <machine/i82093var.h>
321863fb1eSmikeb 
331863fb1eSmikeb #include <dev/pv/xenreg.h>
341863fb1eSmikeb #include <dev/pv/xenvar.h>
351863fb1eSmikeb 
361863fb1eSmikeb struct xspd_softc {
371863fb1eSmikeb 	struct device		sc_dev;
381863fb1eSmikeb 	void *			sc_ih;
391863fb1eSmikeb };
401863fb1eSmikeb 
411863fb1eSmikeb int 	xspd_match(struct device *, void *, void *);
421863fb1eSmikeb void	xspd_attach(struct device *, struct device *, void *);
431863fb1eSmikeb int	xspd_intr(void *);
441863fb1eSmikeb 
451863fb1eSmikeb struct cfdriver xspd_cd = {
461863fb1eSmikeb 	NULL, "xspd", DV_DULL
471863fb1eSmikeb };
481863fb1eSmikeb 
49*8d2c75e4Smpi const struct cfattach xspd_ca = {
501863fb1eSmikeb 	sizeof(struct xspd_softc), xspd_match, xspd_attach, NULL, NULL
511863fb1eSmikeb };
521863fb1eSmikeb 
531863fb1eSmikeb const struct pci_matchid xspd_devices[] = {
541863fb1eSmikeb 	{ PCI_VENDOR_XENSOURCE, PCI_PRODUCT_XENSOURCE_PLATFORMDEV }
551863fb1eSmikeb };
561863fb1eSmikeb 
571863fb1eSmikeb int
xspd_match(struct device * parent,void * match,void * aux)581863fb1eSmikeb xspd_match(struct device *parent, void *match, void *aux)
591863fb1eSmikeb {
601863fb1eSmikeb 	return (pci_matchbyid(aux, xspd_devices, nitems(xspd_devices)));
611863fb1eSmikeb }
621863fb1eSmikeb 
631863fb1eSmikeb #if NXEN > 0
641863fb1eSmikeb void
xspd_attach(struct device * parent,struct device * self,void * aux)651863fb1eSmikeb xspd_attach(struct device *parent, struct device *self, void *aux)
661863fb1eSmikeb {
671863fb1eSmikeb 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
681863fb1eSmikeb 	struct xspd_softc *sc = (struct xspd_softc *)self;
691863fb1eSmikeb 	const char *intrstr = NULL;
701863fb1eSmikeb 	pci_intr_handle_t ih;
711863fb1eSmikeb 	struct xen_hvm_param xhp;
721863fb1eSmikeb 	extern struct xen_softc *xen_sc;
731863fb1eSmikeb 
744ac18c3eSmikeb 	if (xen_sc == NULL || (xen_sc->sc_flags & XSF_CBVEC)) {
751863fb1eSmikeb 		printf("\n");
761863fb1eSmikeb 		return;
771863fb1eSmikeb 	}
781863fb1eSmikeb 
791863fb1eSmikeb 	if (pci_intr_map(pa, &ih) != 0) {
801863fb1eSmikeb 		printf(": couldn't map interrupt\n");
811863fb1eSmikeb 		return;
821863fb1eSmikeb 	}
831863fb1eSmikeb 
841863fb1eSmikeb 	intrstr = pci_intr_string(pa->pa_pc, ih);
851863fb1eSmikeb 	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET | IPL_MPSAFE,
861863fb1eSmikeb 	    xspd_intr, sc, sc->sc_dev.dv_xname);
871863fb1eSmikeb 	if (sc->sc_ih == NULL) {
88f49698d6Smikeb 		printf(": couldn't establish interrupt");
891863fb1eSmikeb 		if (intrstr != NULL)
901863fb1eSmikeb 			printf(" at %s", intrstr);
911863fb1eSmikeb 		printf("\n");
921863fb1eSmikeb 		return;
931863fb1eSmikeb 	}
941863fb1eSmikeb 	printf(": %s\n", intrstr);
951863fb1eSmikeb 
961863fb1eSmikeb 	xhp.domid = DOMID_SELF;
971863fb1eSmikeb 	xhp.index = HVM_PARAM_CALLBACK_IRQ;
981863fb1eSmikeb 
991863fb1eSmikeb 	if (ih.line & APIC_INT_VIA_APIC)
1001863fb1eSmikeb 		xhp.value = HVM_CALLBACK_PCI_INTX(pa->pa_device,
1011863fb1eSmikeb 		    pa->pa_intrpin - 1);
1021863fb1eSmikeb 	else
1031863fb1eSmikeb 		xhp.value = HVM_CALLBACK_GSI(pci_intr_line(pa->pa_pc, ih));
1041863fb1eSmikeb 
105f4354c37Smikeb 	if (xen_hypercall(xen_sc, XC_HVM, 2, HVMOP_set_param, &xhp)) {
1061863fb1eSmikeb 		printf("%s: failed to register callback PCI vector\n",
1071863fb1eSmikeb 		    sc->sc_dev.dv_xname);
1081863fb1eSmikeb 		pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
1091863fb1eSmikeb 		return;
1101863fb1eSmikeb 	}
1111863fb1eSmikeb 
1124ac18c3eSmikeb 	xen_sc->sc_flags |= XSF_CBVEC;
1131863fb1eSmikeb }
1141863fb1eSmikeb 
1151863fb1eSmikeb int
xspd_intr(void * arg)1161863fb1eSmikeb xspd_intr(void *arg)
1171863fb1eSmikeb {
1181863fb1eSmikeb 	xen_intr();
1191863fb1eSmikeb 
1201863fb1eSmikeb 	return (1);
1211863fb1eSmikeb }
1221863fb1eSmikeb #else
1231863fb1eSmikeb void
xspd_attach(struct device * parent,struct device * self,void * aux)1241863fb1eSmikeb xspd_attach(struct device *parent, struct device *self, void *aux)
1251863fb1eSmikeb {
1261863fb1eSmikeb 	printf("\n");
1271863fb1eSmikeb }
1281863fb1eSmikeb #endif	/* NXEN > 0 */
129