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