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