From 9a981c4c0ba1d5c657dadf0c99e758e1733ead73 Mon Sep 17 00:00:00 2001
From: Theo de Raadt <deraadt@cvs.openbsd.org>
Date: Wed, 29 Jul 2015 18:33:18 +0000
Subject: Something subtle in previous revision is locking up suspend or
 booting on some laptops.  Mailing lists threads mention x220 and Asus
 machines. Reverting for now.

---
 sys/dev/acpi/acpi.c | 94 +++++++----------------------------------------------
 1 file changed, 11 insertions(+), 83 deletions(-)

diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index f57b51774d1..e79c9470682 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.289 2015/07/21 15:44:04 kettenis Exp $ */
+/* $OpenBSD: acpi.c,v 1.290 2015/07/29 18:33:17 deraadt Exp $ */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -218,50 +218,6 @@ struct acpi_softc *acpi_softc;
 #define acpi_bus_space_map	_bus_space_map
 #define acpi_bus_space_unmap	_bus_space_unmap
 
-uint8_t
-acpi_pci_conf_read_1(pci_chipset_tag_t pc, pcitag_t tag, int reg)
-{
-	uint32_t val = pci_conf_read(pc, tag, reg & ~0x3);
-	return (val >> ((reg & 0x3) << 3));
-}
-
-uint16_t
-acpi_pci_conf_read_2(pci_chipset_tag_t pc, pcitag_t tag, int reg)
-{
-	uint32_t val = pci_conf_read(pc, tag, reg & ~0x2);
-	return (val >> ((reg & 0x2) << 3));
-}
-
-uint32_t
-acpi_pci_conf_read_4(pci_chipset_tag_t pc, pcitag_t tag, int reg)
-{
-	return pci_conf_read(pc, tag, reg);
-}
-
-void
-acpi_pci_conf_write_1(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint8_t val)
-{
-	uint32_t tmp = pci_conf_read(pc, tag, reg & ~0x3);
-	tmp &= ~(0xff << ((reg & 0x3) << 3));
-	tmp |= (val << ((reg & 0x3) << 3));
-	pci_conf_write(pc, tag, reg & ~0x3, tmp);
-}
-
-void
-acpi_pci_conf_write_2(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint16_t val)
-{
-	uint32_t tmp = pci_conf_read(pc, tag, reg & ~0x2);
-	tmp &= ~(0xffff << ((reg & 0x2) << 3));
-	tmp |= (val << ((reg & 0x2) << 3));
-	pci_conf_write(pc, tag, reg & ~0x2, tmp);
-}
-
-void
-acpi_pci_conf_write_4(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint32_t val)
-{
-	pci_conf_write(pc, tag, reg, val);
-}
-
 int
 acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
     int access_size, int len, void *buffer)
@@ -271,7 +227,7 @@ acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
 	bus_space_handle_t ioh;
 	pci_chipset_tag_t pc;
 	pcitag_t tag;
-	int reg, idx;
+	int reg, idx, ival, sval;
 
 	dnprintf(50, "gasio: %.2x 0x%.8llx %s\n",
 	    iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read");
@@ -370,47 +326,19 @@ acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
 		    ACPI_PCI_BUS(address), ACPI_PCI_DEV(address),
 		    ACPI_PCI_FN(address));
 
+		/* XXX: This is ugly. read-modify-write does a byte at a time */
 		reg = ACPI_PCI_REG(address);
-		for (idx = 0; idx < len; idx += access_size) {
+		for (idx = reg; idx < reg+len; idx++) {
+			ival = pci_conf_read(pc, tag, idx & ~0x3);
 			if (iodir == ACPI_IOREAD) {
-				switch (access_size) {
-				case 1:
-					*(uint8_t *)(pb + idx) = 
-					    acpi_pci_conf_read_1(pc, tag, reg + idx);
-					break;
-				case 2:
-					*(uint16_t *)(pb + idx) =
-					    acpi_pci_conf_read_2(pc, tag, reg + idx);
-					break;
-				case 4:
-					*(uint32_t *)(pb + idx) =
-					    acpi_pci_conf_read_4(pc, tag, reg + idx);
-					break;
-				default:
-					printf("%s: rdcfg: invalid size %d\n",
-					    DEVNAME(sc), access_size);
-					return (-1);
-				}
+				*pb = ival >> (8 * (idx & 0x3));
 			} else {
-				switch (access_size) {
-				case 1:
-					acpi_pci_conf_write_1(pc, tag, reg + idx,
-					    *(uint8_t *)(pb + idx));
-					break;
-				case 2:
-					acpi_pci_conf_write_2(pc, tag, reg + idx,
-					    *(uint16_t *)(pb + idx));
-					break;
-				case 4:
-					acpi_pci_conf_write_4(pc, tag, reg + idx,
-					    *(uint32_t *)(pb + idx));
-					break;
-				default:
-					printf("%s: wrcfg: invalid size %d\n",
-					    DEVNAME(sc), access_size);
-					return (-1);
-				}
+				sval = *pb;
+				ival &= ~(0xFF << (8* (idx & 0x3)));
+				ival |= sval << (8* (idx & 0x3));
+				pci_conf_write(pc, tag, idx & ~0x3, ival);
 			}
+			pb++;
 		}
 		break;
 
-- 
cgit v1.2.3