1 1.15 andvar /* $NetBSD: OsdHardware.c,v 1.15 2024/06/23 15:21:52 andvar Exp $ */ 2 1.1 kochi 3 1.1 kochi /* 4 1.1 kochi * Copyright 2001 Wasabi Systems, Inc. 5 1.1 kochi * All rights reserved. 6 1.1 kochi * 7 1.1 kochi * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 1.1 kochi * 9 1.1 kochi * Redistribution and use in source and binary forms, with or without 10 1.1 kochi * modification, are permitted provided that the following conditions 11 1.1 kochi * are met: 12 1.1 kochi * 1. Redistributions of source code must retain the above copyright 13 1.1 kochi * notice, this list of conditions and the following disclaimer. 14 1.1 kochi * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 kochi * notice, this list of conditions and the following disclaimer in the 16 1.1 kochi * documentation and/or other materials provided with the distribution. 17 1.1 kochi * 3. All advertising materials mentioning features or use of this software 18 1.1 kochi * must display the following acknowledgement: 19 1.1 kochi * This product includes software developed for the NetBSD Project by 20 1.1 kochi * Wasabi Systems, Inc. 21 1.1 kochi * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 1.1 kochi * or promote products derived from this software without specific prior 23 1.1 kochi * written permission. 24 1.1 kochi * 25 1.1 kochi * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 1.1 kochi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 1.1 kochi * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 1.1 kochi * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 1.1 kochi * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 1.1 kochi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 1.1 kochi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 1.1 kochi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 1.1 kochi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 1.1 kochi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 1.1 kochi * POSSIBILITY OF SUCH DAMAGE. 36 1.1 kochi */ 37 1.1 kochi 38 1.1 kochi /* 39 1.1 kochi * OS Services Layer 40 1.1 kochi * 41 1.1 kochi * 6.7: Address Space Access: Port Input/Output 42 1.1 kochi * 6.8: Address Space Access: Memory and Memory Mapped I/O 43 1.1 kochi * 6.9: Address Space Access: PCI Configuration Space 44 1.1 kochi */ 45 1.1 kochi 46 1.1 kochi #include <sys/cdefs.h> 47 1.15 andvar __KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.15 2024/06/23 15:21:52 andvar Exp $"); 48 1.14 mrg 49 1.14 mrg #include "pci.h" 50 1.1 kochi 51 1.1 kochi #include <sys/param.h> 52 1.1 kochi #include <sys/device.h> 53 1.1 kochi 54 1.1 kochi #include <dev/acpi/acpica.h> 55 1.1 kochi #include <dev/acpi/acpivar.h> 56 1.6 gsutre #include <dev/acpi/acpi_pci.h> 57 1.1 kochi 58 1.1 kochi #include <machine/acpi_machdep.h> 59 1.1 kochi 60 1.1 kochi /* 61 1.1 kochi * ACPICA doesn't provide much in the way of letting us know which 62 1.1 kochi * hardware resources it wants to use. We therefore have to resort 63 1.15 andvar * to calling machine-dependent code to do the access for us. 64 1.1 kochi */ 65 1.1 kochi 66 1.1 kochi /* 67 1.1 kochi * AcpiOsReadPort: 68 1.1 kochi * 69 1.1 kochi * Read a value from an input port. 70 1.1 kochi */ 71 1.1 kochi ACPI_STATUS 72 1.1 kochi AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width) 73 1.1 kochi { 74 1.1 kochi 75 1.1 kochi switch (Width) { 76 1.1 kochi case 8: 77 1.1 kochi *Value = acpi_md_OsIn8(Address); 78 1.1 kochi break; 79 1.1 kochi 80 1.1 kochi case 16: 81 1.1 kochi *Value = acpi_md_OsIn16(Address); 82 1.1 kochi break; 83 1.1 kochi 84 1.1 kochi case 32: 85 1.1 kochi *Value = acpi_md_OsIn32(Address); 86 1.1 kochi break; 87 1.1 kochi 88 1.1 kochi default: 89 1.1 kochi return AE_BAD_PARAMETER; 90 1.1 kochi } 91 1.1 kochi 92 1.1 kochi return AE_OK; 93 1.1 kochi } 94 1.1 kochi 95 1.1 kochi /* 96 1.1 kochi * AcpiOsWritePort: 97 1.1 kochi * 98 1.1 kochi * Write a value to an output port. 99 1.1 kochi */ 100 1.1 kochi ACPI_STATUS 101 1.1 kochi AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width) 102 1.1 kochi { 103 1.1 kochi 104 1.1 kochi switch (Width) { 105 1.1 kochi case 8: 106 1.1 kochi acpi_md_OsOut8(Address, Value); 107 1.1 kochi break; 108 1.1 kochi 109 1.1 kochi case 16: 110 1.1 kochi acpi_md_OsOut16(Address, Value); 111 1.1 kochi break; 112 1.1 kochi 113 1.1 kochi case 32: 114 1.1 kochi acpi_md_OsOut32(Address, Value); 115 1.1 kochi break; 116 1.1 kochi 117 1.1 kochi default: 118 1.1 kochi return AE_BAD_PARAMETER; 119 1.1 kochi } 120 1.1 kochi 121 1.1 kochi return AE_OK; 122 1.1 kochi } 123 1.1 kochi 124 1.1 kochi /* 125 1.1 kochi * AcpiOsReadMemory: 126 1.1 kochi * 127 1.1 kochi * Read a value from a memory location. 128 1.1 kochi */ 129 1.1 kochi ACPI_STATUS 130 1.9 christos AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width) 131 1.1 kochi { 132 1.1 kochi void *LogicalAddress; 133 1.5 drochner ACPI_STATUS rv = AE_OK; 134 1.1 kochi 135 1.3 jmcneill LogicalAddress = AcpiOsMapMemory(Address, Width / 8); 136 1.3 jmcneill if (LogicalAddress == NULL) 137 1.3 jmcneill return AE_NOT_EXIST; 138 1.1 kochi 139 1.1 kochi switch (Width) { 140 1.1 kochi case 8: 141 1.1 kochi *Value = *(volatile uint8_t *) LogicalAddress; 142 1.1 kochi break; 143 1.1 kochi 144 1.1 kochi case 16: 145 1.1 kochi *Value = *(volatile uint16_t *) LogicalAddress; 146 1.1 kochi break; 147 1.1 kochi 148 1.1 kochi case 32: 149 1.1 kochi *Value = *(volatile uint32_t *) LogicalAddress; 150 1.1 kochi break; 151 1.1 kochi 152 1.9 christos case 64: 153 1.9 christos *Value = *(volatile uint64_t *) LogicalAddress; 154 1.9 christos break; 155 1.9 christos 156 1.1 kochi default: 157 1.1 kochi rv = AE_BAD_PARAMETER; 158 1.1 kochi } 159 1.1 kochi 160 1.1 kochi AcpiOsUnmapMemory(LogicalAddress, Width / 8); 161 1.1 kochi 162 1.1 kochi return rv; 163 1.1 kochi } 164 1.1 kochi 165 1.1 kochi /* 166 1.1 kochi * AcpiOsWriteMemory: 167 1.1 kochi * 168 1.1 kochi * Write a value to a memory location. 169 1.1 kochi */ 170 1.1 kochi ACPI_STATUS 171 1.9 christos AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width) 172 1.1 kochi { 173 1.1 kochi void *LogicalAddress; 174 1.5 drochner ACPI_STATUS rv = AE_OK; 175 1.1 kochi 176 1.3 jmcneill LogicalAddress = AcpiOsMapMemory(Address, Width / 8); 177 1.3 jmcneill if (LogicalAddress == NULL) 178 1.3 jmcneill return AE_NOT_FOUND; 179 1.1 kochi 180 1.1 kochi switch (Width) { 181 1.1 kochi case 8: 182 1.1 kochi *(volatile uint8_t *) LogicalAddress = Value; 183 1.1 kochi break; 184 1.1 kochi 185 1.1 kochi case 16: 186 1.1 kochi *(volatile uint16_t *) LogicalAddress = Value; 187 1.1 kochi break; 188 1.1 kochi 189 1.1 kochi case 32: 190 1.1 kochi *(volatile uint32_t *) LogicalAddress = Value; 191 1.1 kochi break; 192 1.1 kochi 193 1.9 christos case 64: 194 1.9 christos *(volatile uint64_t *) LogicalAddress = Value; 195 1.9 christos break; 196 1.9 christos 197 1.1 kochi default: 198 1.1 kochi rv = AE_BAD_PARAMETER; 199 1.1 kochi } 200 1.1 kochi 201 1.1 kochi AcpiOsUnmapMemory(LogicalAddress, Width / 8); 202 1.1 kochi 203 1.1 kochi return rv; 204 1.1 kochi } 205 1.1 kochi 206 1.1 kochi /* 207 1.1 kochi * AcpiOsReadPciConfiguration: 208 1.1 kochi * 209 1.1 kochi * Read a value from a PCI configuration register. 210 1.1 kochi */ 211 1.1 kochi ACPI_STATUS 212 1.8 jruoho AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, 213 1.1 kochi UINT32 Width) 214 1.1 kochi { 215 1.14 mrg #if NPCI > 0 216 1.12 jmcneill pci_chipset_tag_t pc; 217 1.1 kochi pcitag_t tag; 218 1.1 kochi pcireg_t tmp; 219 1.1 kochi 220 1.4 jmcneill if (PciId->Bus >= 256 || PciId->Device >= 32 || PciId->Function >= 8) 221 1.4 jmcneill return AE_BAD_PARAMETER; 222 1.4 jmcneill 223 1.12 jmcneill pc = acpi_pcidev_get_tag(PciId->Segment, PciId->Bus, PciId->Device, PciId->Function); 224 1.12 jmcneill 225 1.10 christos tag = pci_make_tag(pc, PciId->Bus, PciId->Device, PciId->Function); 226 1.10 christos tmp = pci_conf_read(pc, tag, Register & ~3); 227 1.1 kochi 228 1.1 kochi switch (Width) { 229 1.1 kochi case 8: 230 1.13 riastrad *Value = (tmp >> ((Register & 3) * 8)) & 0xff; 231 1.1 kochi break; 232 1.1 kochi 233 1.1 kochi case 16: 234 1.13 riastrad *Value = (tmp >> ((Register & 3) * 8)) & 0xffff; 235 1.1 kochi break; 236 1.1 kochi 237 1.1 kochi case 32: 238 1.13 riastrad *Value = tmp; 239 1.1 kochi break; 240 1.1 kochi 241 1.1 kochi default: 242 1.1 kochi return AE_BAD_PARAMETER; 243 1.1 kochi } 244 1.1 kochi 245 1.1 kochi return AE_OK; 246 1.14 mrg #else 247 1.14 mrg return AE_BAD_PARAMETER; 248 1.14 mrg #endif 249 1.1 kochi } 250 1.1 kochi 251 1.1 kochi /* 252 1.1 kochi * AcpiOsWritePciConfiguration: 253 1.1 kochi * 254 1.1 kochi * Write a value to a PCI configuration register. 255 1.1 kochi */ 256 1.1 kochi ACPI_STATUS 257 1.1 kochi AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, 258 1.1 kochi ACPI_INTEGER Value, UINT32 Width) 259 1.1 kochi { 260 1.14 mrg #if NPCI > 0 261 1.12 jmcneill pci_chipset_tag_t pc; 262 1.1 kochi pcitag_t tag; 263 1.1 kochi pcireg_t tmp; 264 1.1 kochi 265 1.12 jmcneill pc = acpi_pcidev_get_tag(PciId->Segment, PciId->Bus, PciId->Device, PciId->Function); 266 1.10 christos tag = pci_make_tag(pc, PciId->Bus, PciId->Device, PciId->Function); 267 1.1 kochi 268 1.1 kochi switch (Width) { 269 1.1 kochi case 8: 270 1.10 christos tmp = pci_conf_read(pc, tag, Register & ~3); 271 1.11 kamil tmp &= ~(0xffu << ((Register & 3) * 8)); 272 1.1 kochi tmp |= (Value << ((Register & 3) * 8)); 273 1.1 kochi break; 274 1.1 kochi 275 1.1 kochi case 16: 276 1.10 christos tmp = pci_conf_read(pc, tag, Register & ~3); 277 1.11 kamil tmp &= ~(0xffffu << ((Register & 3) * 8)); 278 1.1 kochi tmp |= (Value << ((Register & 3) * 8)); 279 1.1 kochi break; 280 1.1 kochi 281 1.1 kochi case 32: 282 1.1 kochi tmp = Value; 283 1.1 kochi break; 284 1.1 kochi 285 1.1 kochi default: 286 1.1 kochi return AE_BAD_PARAMETER; 287 1.1 kochi } 288 1.1 kochi 289 1.10 christos pci_conf_write(pc, tag, Register & ~3, tmp); 290 1.1 kochi 291 1.1 kochi return AE_OK; 292 1.14 mrg #else 293 1.14 mrg return AE_BAD_PARAMETER; 294 1.14 mrg #endif 295 1.1 kochi } 296