xref: /netbsd-src/sys/rump/dev/lib/libpci/rumpdev_pci.c (revision 412bc0ef8dafd0c57f8733b9dde6a7464e55eab9)
1*412bc0efSpooka /*      $NetBSD: rumpdev_pci.c,v 1.5 2015/05/17 13:51:31 pooka Exp $	*/
269955daeSpooka 
369955daeSpooka /*
469955daeSpooka  * Copyright (c) 2013 Antti Kantee.  All Rights Reserved.
569955daeSpooka  *
669955daeSpooka  * Redistribution and use in source and binary forms, with or without
769955daeSpooka  * modification, are permitted provided that the following conditions
869955daeSpooka  * are met:
969955daeSpooka  * 1. Redistributions of source code must retain the above copyright
1069955daeSpooka  *    notice, this list of conditions and the following disclaimer.
1169955daeSpooka  * 2. Redistributions in binary form must reproduce the above copyright
1269955daeSpooka  *    notice, this list of conditions and the following disclaimer in the
1369955daeSpooka  *    documentation and/or other materials provided with the distribution.
1469955daeSpooka  *
1569955daeSpooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
1669955daeSpooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1769955daeSpooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1869955daeSpooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1969955daeSpooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2069955daeSpooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2169955daeSpooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2269955daeSpooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2369955daeSpooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2469955daeSpooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2569955daeSpooka  * SUCH DAMAGE.
2669955daeSpooka  */
2769955daeSpooka 
2869955daeSpooka #include <sys/cdefs.h>
29*412bc0efSpooka __KERNEL_RCSID(0, "$NetBSD: rumpdev_pci.c,v 1.5 2015/05/17 13:51:31 pooka Exp $");
3069955daeSpooka 
3169955daeSpooka #include <sys/cdefs.h>
3269955daeSpooka #include <sys/param.h>
335145f215Spooka #include <sys/atomic.h>
3469955daeSpooka 
3569955daeSpooka #include <dev/pci/pcivar.h>
3669955daeSpooka 
3769955daeSpooka #include "pci_user.h"
3869955daeSpooka 
3969955daeSpooka void
pci_attach_hook(device_t parent,device_t self,struct pcibus_attach_args * pba)4069955daeSpooka pci_attach_hook(device_t parent, device_t self, struct pcibus_attach_args *pba)
4169955daeSpooka {
4269955daeSpooka 
4369955daeSpooka 	/* nada */
4469955daeSpooka }
4569955daeSpooka 
4669955daeSpooka int
pci_bus_maxdevs(pci_chipset_tag_t pc,int busno)4769955daeSpooka pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
4869955daeSpooka {
4969955daeSpooka 
5069955daeSpooka 	return 32;
5169955daeSpooka }
5269955daeSpooka 
5369955daeSpooka pcitag_t
pci_make_tag(pci_chipset_tag_t pc,int bus,int device,int function)5469955daeSpooka pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
5569955daeSpooka {
5669955daeSpooka 	pcitag_t pt;
5769955daeSpooka 	int *tag;
5869955daeSpooka 	unsigned csr;
5969955daeSpooka 	int rv;
6069955daeSpooka 
6169955daeSpooka 	CTASSERT(sizeof(pt) >= sizeof(int));
6269955daeSpooka 
6369955daeSpooka 	/* a "bit" ugly, but keeps us MI */
6469955daeSpooka 	tag = (int *)&pt;
6569955daeSpooka 	*tag = (bus << 16) | (device << 8) | (function << 0);
6669955daeSpooka 
6769955daeSpooka 	/*
6869955daeSpooka 	 * On Xen, we need to enable the device io/mem space.
6969955daeSpooka 	 * Doesn't really belong here, but we need to do it somewhere.
7069955daeSpooka 	 */
7169955daeSpooka 	rv = rumpcomp_pci_confread(bus, device, function,
7269955daeSpooka 	    PCI_COMMAND_STATUS_REG, &csr);
7369955daeSpooka 	if (rv == 0 && (csr & PCI_COMMAND_MEM_ENABLE) == 0) {
7469955daeSpooka 		rumpcomp_pci_confwrite(bus, device, function,
7569955daeSpooka 		    PCI_COMMAND_STATUS_REG, csr | PCI_COMMAND_MEM_ENABLE);
7669955daeSpooka 	}
7769955daeSpooka 
7869955daeSpooka 	return pt;
7969955daeSpooka }
8069955daeSpooka 
8169955daeSpooka pcireg_t
pci_conf_read(pci_chipset_tag_t pc,pcitag_t tag,int reg)8269955daeSpooka pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
8369955daeSpooka {
8469955daeSpooka 	unsigned int rv;
8569955daeSpooka 	int bus, device, fun;
8669955daeSpooka 
8769955daeSpooka 	pci_decompose_tag(pc, tag, &bus, &device, &fun);
8869955daeSpooka 	rumpcomp_pci_confread(bus, device, fun, reg, &rv);
8969955daeSpooka 	return rv;
9069955daeSpooka }
9169955daeSpooka 
9269955daeSpooka void
pci_conf_write(pci_chipset_tag_t pc,pcitag_t tag,int reg,pcireg_t data)9369955daeSpooka pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
9469955daeSpooka {
9569955daeSpooka 	int bus, device, fun;
9669955daeSpooka 
9769955daeSpooka 	pci_decompose_tag(pc, tag, &bus, &device, &fun);
9869955daeSpooka 	rumpcomp_pci_confwrite(bus, device, fun, reg, data);
9969955daeSpooka }
10069955daeSpooka 
10169955daeSpooka void
pci_decompose_tag(pci_chipset_tag_t pc,pcitag_t tag,int * bp,int * dp,int * fp)10269955daeSpooka pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag,
10369955daeSpooka 	int *bp, int *dp, int *fp)
10469955daeSpooka {
10569955daeSpooka 	int *t = (int *)&tag;
10669955daeSpooka 
10769955daeSpooka 	*bp = (*t >> 16) & 0xff;
10869955daeSpooka 	*dp = (*t >> 8)  & 0xff;
10969955daeSpooka 	*fp = (*t >> 0)  & 0xff;
11069955daeSpooka }
11169955daeSpooka 
1125145f215Spooka /*
1135145f215Spooka  * Well, yay, deal with the wonders of weird_t.  We'll just
1145145f215Spooka  * assume it's an integral type (which, btw, isn't universally true).
1155145f215Spooka  * The hypercall will map "cookie" to its internal structure.
1165145f215Spooka  * Dial _t for a good time.
1175145f215Spooka  */
11869955daeSpooka int
pci_intr_map(const struct pci_attach_args * pa,pci_intr_handle_t * ih)11969955daeSpooka pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih)
12069955daeSpooka {
1215145f215Spooka 	static unsigned int intrhandle;
1225145f215Spooka 	unsigned cookie;
1235145f215Spooka 	int rv;
12469955daeSpooka 
1255145f215Spooka 	cookie = atomic_inc_uint_nv(&intrhandle);
1265145f215Spooka 	rv = rumpcomp_pci_irq_map(pa->pa_bus,
1275145f215Spooka 	    pa->pa_device, pa->pa_function, pa->pa_intrline, cookie);
1285145f215Spooka 	if (rv == 0)
1295145f215Spooka 		*ih = cookie;
13069955daeSpooka 	return 0;
13169955daeSpooka }
13269955daeSpooka 
13369955daeSpooka const char *
pci_intr_string(pci_chipset_tag_t pc,pci_intr_handle_t ih,char * buf,size_t buflen)134db08ffefSpooka pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih,
135db08ffefSpooka 	char *buf, size_t buflen)
13669955daeSpooka {
13769955daeSpooka 
138db08ffefSpooka 	snprintf(buf, buflen, "pausebreak");
139db08ffefSpooka 	return buf;
14069955daeSpooka }
14169955daeSpooka 
14269955daeSpooka void *
pci_intr_establish(pci_chipset_tag_t pc,pci_intr_handle_t ih,int level,int (* func)(void *),void * arg)14369955daeSpooka pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih,
14469955daeSpooka 	int level, int (*func)(void *), void *arg)
14569955daeSpooka {
14669955daeSpooka 
14769955daeSpooka 	return rumpcomp_pci_irq_establish(ih, func, arg);
14869955daeSpooka }
14969955daeSpooka 
1501dc56c39Spooka int
pci_intr_setattr(pci_chipset_tag_t pc,pci_intr_handle_t * ih,int attr,uint64_t data)1511dc56c39Spooka pci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ih,
1521dc56c39Spooka 	int attr, uint64_t data)
1531dc56c39Spooka {
1541dc56c39Spooka 
1551dc56c39Spooka 	switch (attr) {
1561dc56c39Spooka 	case PCI_INTR_MPSAFE:
1571dc56c39Spooka 		return 0;
1581dc56c39Spooka 	default:
1591dc56c39Spooka 		return ENODEV;
1601dc56c39Spooka 	}
1611dc56c39Spooka }
1621dc56c39Spooka 
16369955daeSpooka void
pci_intr_disestablish(pci_chipset_tag_t pc,void * not_your_above_ih)1645145f215Spooka pci_intr_disestablish(pci_chipset_tag_t pc, void *not_your_above_ih)
16569955daeSpooka {
16669955daeSpooka 
16769955daeSpooka 	panic("%s: unimplemented", __func__);
16869955daeSpooka }
169*412bc0efSpooka 
170*412bc0efSpooka #ifdef __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH
171*412bc0efSpooka #include <dev/pci/pcireg.h>
172*412bc0efSpooka #include <dev/pci/pcivar.h>
173*412bc0efSpooka #include <dev/pci/pciidereg.h>
174*412bc0efSpooka #include <dev/pci/pciidevar.h>
175*412bc0efSpooka 
176*412bc0efSpooka void *
pciide_machdep_compat_intr_establish(device_t dev,const struct pci_attach_args * pa,int chan,int (* func)(void *),void * arg)177*412bc0efSpooka pciide_machdep_compat_intr_establish(device_t dev,
178*412bc0efSpooka 	const struct pci_attach_args *pa, int chan,
179*412bc0efSpooka 	int (*func)(void *), void *arg)
180*412bc0efSpooka {
181*412bc0efSpooka 	pci_intr_handle_t ih;
182*412bc0efSpooka 	struct pci_attach_args mypa = *pa;
183*412bc0efSpooka 
184*412bc0efSpooka 	mypa.pa_intrline = PCIIDE_COMPAT_IRQ(chan);
185*412bc0efSpooka 	if (pci_intr_map(&mypa, &ih) != 0)
186*412bc0efSpooka 		return NULL;
187*412bc0efSpooka 	return rumpcomp_pci_irq_establish(ih, func, arg);
188*412bc0efSpooka }
189*412bc0efSpooka 
190*412bc0efSpooka __strong_alias(pciide_machdep_compat_intr_disestablish,pci_intr_disestablish);
191*412bc0efSpooka #endif /* __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH */
192