Module Name: src Committed By: msaitoh Date: Tue Jan 13 08:57:02 UTC 2015
Modified Files: src/sys/arch/x86/pci: ichlpcib.c Log Message: As I wrote in the last commit, The PMBASE and GPIOBASE registers are not compltible with the PCI spec and the map sizes are fixed to 128bytes. The pci_mapreg_submap() function has a code to check the range of the BAR. The PCI_MAPREG_IO_SIZE() macro returns lower than 128bytes on some machines. It makes impossible to use pci_mapreg_submap(). Use pci_conf_read() and bus_space_map() directly. Observed and tested with my Thinkpad X61. To generate a diff of this commit: cvs rdiff -u -r1.45 -r1.46 src/sys/arch/x86/pci/ichlpcib.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/pci/ichlpcib.c diff -u src/sys/arch/x86/pci/ichlpcib.c:1.45 src/sys/arch/x86/pci/ichlpcib.c:1.46 --- src/sys/arch/x86/pci/ichlpcib.c:1.45 Fri Dec 26 05:09:03 2014 +++ src/sys/arch/x86/pci/ichlpcib.c Tue Jan 13 08:57:02 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ichlpcib.c,v 1.45 2014/12/26 05:09:03 msaitoh Exp $ */ +/* $NetBSD: ichlpcib.c,v 1.46 2015/01/13 08:57:02 msaitoh Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ichlpcib.c,v 1.45 2014/12/26 05:09:03 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ichlpcib.c,v 1.46 2015/01/13 08:57:02 msaitoh Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -303,6 +303,7 @@ lpcibattach(device_t parent, device_t se struct pci_attach_args *pa = aux; struct lpcib_softc *sc = device_private(self); struct lpcib_device *lpcib_dev; + pcireg_t pmbase; sc->sc_pa = *pa; @@ -324,12 +325,16 @@ lpcibattach(device_t parent, device_t se * * The PMBASE register is alike PCI BAR but not completely compatible * with it. The PMBASE define the base address and the type but - * not describe the size. + * not describe the size. The value of the register may be lower + * than LPCIB_PCI_PM_SIZE. It makes impossible to use + * pci_mapreg_submap() because the function does range check. */ - if (pci_mapreg_submap(pa, LPCIB_PCI_PMBASE, PCI_MAPREG_TYPE_IO, 0, - LPCIB_PCI_PM_SIZE, 0, &sc->sc_iot, &sc->sc_ioh, NULL, - &sc->sc_iosize)) { - aprint_error_dev(self, "can't map power management i/o space\n"); + sc->sc_iot = pa->pa_iot; + pmbase = pci_conf_read(pa->pa_pc, pa->pa_tag, LPCIB_PCI_PMBASE); + if (bus_space_map(sc->sc_iot, PCI_MAPREG_IO_ADDR(pmbase), + LPCIB_PCI_PM_SIZE, 0, &sc->sc_ioh) != 0) { + aprint_error_dev(self, + "can't map power management i/o space\n"); return; } @@ -1082,11 +1087,14 @@ lpcib_gpio_configure(device_t self) /* * The GPIO_BASE register is alike PCI BAR but not completely * compatible with it. The PMBASE define the base address and the type - * but not describe the size. + * but not describe the size. The value of the register may be lower + * than LPCIB_PCI_GPIO_SIZE. It makes impossible to use + * pci_mapreg_submap() because the function does range check. */ - rv = pci_mapreg_submap(&sc->sc_pa, base_reg, PCI_MAPREG_TYPE_IO, 0, - LPCIB_PCI_GPIO_SIZE, 0, &sc->sc_gpio_iot, &sc->sc_gpio_ioh, - NULL, &sc->sc_gpio_ios); + sc->sc_gpio_iot = sc->sc_pa.pa_iot; + reg = pci_conf_read(sc->sc_pa.pa_pc, sc->sc_pa.pa_tag, base_reg); + rv = bus_space_map(sc->sc_gpio_iot, PCI_MAPREG_IO_ADDR(reg), + LPCIB_PCI_GPIO_SIZE, 0, &sc->sc_gpio_ioh); if (rv != 0) { aprint_error_dev(self, "can't map general purpose i/o space(rv = %d)\n", rv); return;