Module Name: src Committed By: jmcneill Date: Thu Feb 10 12:37:58 UTC 2011
Modified Files: src/sys/dev/pci: pci.c pci_usrreq.c pcivar.h Log Message: pcimmap: if the requested page is marked prefetchable in a child device's BAR, pass the BUS_SPACE_MAP_PREFETCHABLE flag down to bus_space_mmap To generate a diff of this commit: cvs rdiff -u -r1.131 -r1.132 src/sys/dev/pci/pci.c cvs rdiff -u -r1.22 -r1.23 src/sys/dev/pci/pci_usrreq.c cvs rdiff -u -r1.90 -r1.91 src/sys/dev/pci/pcivar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/pci.c diff -u src/sys/dev/pci/pci.c:1.131 src/sys/dev/pci/pci.c:1.132 --- src/sys/dev/pci/pci.c:1.131 Tue Feb 1 19:37:37 2011 +++ src/sys/dev/pci/pci.c Thu Feb 10 12:37:58 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pci.c,v 1.131 2011/02/01 19:37:37 dyoung Exp $ */ +/* $NetBSD: pci.c,v 1.132 2011/02/10 12:37:58 jmcneill Exp $ */ /* * Copyright (c) 1995, 1996, 1997, 1998 @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.131 2011/02/01 19:37:37 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.132 2011/02/10 12:37:58 jmcneill Exp $"); #include "opt_pci.h" @@ -272,8 +272,8 @@ { pci_chipset_tag_t pc = sc->sc_pc; struct pci_attach_args pa; - pcireg_t id, csr, class, intr, bhlcr; - int ret, pin, bus, device, function; + pcireg_t id, csr, class, intr, bhlcr, bar; + int ret, pin, bus, device, function, i, width; int locs[PCICF_NLOCS]; pci_decompose_tag(pc, tag, &bus, &device, &function); @@ -297,6 +297,27 @@ if (PCI_VENDOR(id) == 0) return 0; + /* Collect memory range info */ + memset(sc->PCI_SC_DEVICESC(device, function).c_range, 0, + sizeof(sc->PCI_SC_DEVICESC(device, function).c_range)); + i = 0; + for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += width) { + int type = pci_mapreg_type(pc, tag, bar); + struct pci_range *r; + + width = 4; + if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) { + if (PCI_MAPREG_MEM_TYPE(type) == + PCI_MAPREG_MEM_TYPE_64BIT) + width = 8; + + r = &sc->PCI_SC_DEVICESC(device, function).c_range[i++]; + if (pci_mapreg_info(pc, tag, bar, type, + &r->r_offset, &r->r_size, &r->r_flags) != 0) + break; + } + } + pa.pa_iot = sc->sc_iot; pa.pa_memt = sc->sc_memt; pa.pa_dmat = sc->sc_dmat; Index: src/sys/dev/pci/pci_usrreq.c diff -u src/sys/dev/pci/pci_usrreq.c:1.22 src/sys/dev/pci/pci_usrreq.c:1.23 --- src/sys/dev/pci/pci_usrreq.c:1.22 Thu Jul 30 04:38:24 2009 +++ src/sys/dev/pci/pci_usrreq.c Thu Feb 10 12:37:58 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_usrreq.c,v 1.22 2009/07/30 04:38:24 macallan Exp $ */ +/* $NetBSD: pci_usrreq.c,v 1.23 2011/02/10 12:37:58 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_usrreq.c,v 1.22 2009/07/30 04:38:24 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_usrreq.c,v 1.23 2011/02/10 12:37:58 jmcneill Exp $"); #include <sys/param.h> #include <sys/conf.h> @@ -114,6 +114,10 @@ pcimmap(dev_t dev, off_t offset, int prot) { struct pci_softc *sc = device_lookup_private(&pci_cd, minor(dev)); + struct pci_child *c; + struct pci_range *r; + int flags = 0; + int device, range; if (kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER, NULL) != 0) { @@ -124,7 +128,7 @@ * take the offset to be the address on the bus, * and pass 0 as the offset into that range. * - * XXX Need a way to deal with linear/prefetchable/etc. + * XXX Need a way to deal with linear/etc. * * XXX we rely on MD mmap() methods to enforce limits since these * are hidden in *_tag_t structs if they exist at all @@ -145,7 +149,24 @@ 0, prot, 0); } #endif /* PCI_MAGIC_IO_RANGE */ - return bus_space_mmap(sc->sc_memt, offset, 0, prot, 0); + + for (device = 0; device < __arraycount(sc->sc_devices); device++) { + c = &sc->sc_devices[device]; + if (c->c_dev == NULL) + continue; + for (range = 0; range < __arraycount(c->c_range); range++) { + r = &c->c_range[range]; + if (r->r_size == 0) + break; + if (offset >= r->r_offset && + offset < r->r_offset + r->r_size) { + flags = r->r_flags; + break; + } + } + } + + return bus_space_mmap(sc->sc_memt, offset, 0, prot, flags); } const struct cdevsw pci_cdevsw = { Index: src/sys/dev/pci/pcivar.h diff -u src/sys/dev/pci/pcivar.h:1.90 src/sys/dev/pci/pcivar.h:1.91 --- src/sys/dev/pci/pcivar.h:1.90 Wed Jun 9 02:39:32 2010 +++ src/sys/dev/pci/pcivar.h Thu Feb 10 12:37:58 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pcivar.h,v 1.90 2010/06/09 02:39:32 mrg Exp $ */ +/* $NetBSD: pcivar.h,v 1.91 2011/02/10 12:37:58 jmcneill Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -196,11 +196,18 @@ pcireg_t reg[16]; }; +struct pci_range { + bus_addr_t r_offset; + bus_size_t r_size; + int r_flags; +}; + struct pci_child { device_t c_dev; bool c_psok; pcireg_t c_powerstate; struct pci_conf_state c_conf; + struct pci_range c_range[8]; }; struct pci_softc {