1 /* $NetBSD: OsdHardware.c,v 1.8 2011/02/17 10:23:43 jruoho 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.8 2011/02/17 10:23:43 jruoho 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, UINT32 *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 default: 151 rv = AE_BAD_PARAMETER; 152 } 153 154 AcpiOsUnmapMemory(LogicalAddress, Width / 8); 155 156 return rv; 157 } 158 159 /* 160 * AcpiOsWriteMemory: 161 * 162 * Write a value to a memory location. 163 */ 164 ACPI_STATUS 165 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 Value, UINT32 Width) 166 { 167 void *LogicalAddress; 168 ACPI_STATUS rv = AE_OK; 169 170 LogicalAddress = AcpiOsMapMemory(Address, Width / 8); 171 if (LogicalAddress == NULL) 172 return AE_NOT_FOUND; 173 174 switch (Width) { 175 case 8: 176 *(volatile uint8_t *) LogicalAddress = Value; 177 break; 178 179 case 16: 180 *(volatile uint16_t *) LogicalAddress = Value; 181 break; 182 183 case 32: 184 *(volatile uint32_t *) LogicalAddress = Value; 185 break; 186 187 default: 188 rv = AE_BAD_PARAMETER; 189 } 190 191 AcpiOsUnmapMemory(LogicalAddress, Width / 8); 192 193 return rv; 194 } 195 196 /* 197 * AcpiOsReadPciConfiguration: 198 * 199 * Read a value from a PCI configuration register. 200 */ 201 ACPI_STATUS 202 AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, 203 UINT32 Width) 204 { 205 pcitag_t tag; 206 pcireg_t tmp; 207 208 /* XXX Need to deal with "segment" ("hose" in Alpha terminology). */ 209 210 if (PciId->Bus >= 256 || PciId->Device >= 32 || PciId->Function >= 8) 211 return AE_BAD_PARAMETER; 212 213 tag = pci_make_tag(acpi_softc->sc_pc, PciId->Bus, PciId->Device, 214 PciId->Function); 215 tmp = pci_conf_read(acpi_softc->sc_pc, tag, Register & ~3); 216 217 switch (Width) { 218 case 8: 219 *(uint8_t *) Value = (tmp >> ((Register & 3) * 8)) & 0xff; 220 break; 221 222 case 16: 223 *(uint16_t *) Value = (tmp >> ((Register & 3) * 8)) & 0xffff; 224 break; 225 226 case 32: 227 *(uint32_t *) Value = tmp; 228 break; 229 230 default: 231 return AE_BAD_PARAMETER; 232 } 233 234 return AE_OK; 235 } 236 237 /* 238 * AcpiOsWritePciConfiguration: 239 * 240 * Write a value to a PCI configuration register. 241 */ 242 ACPI_STATUS 243 AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, 244 ACPI_INTEGER Value, UINT32 Width) 245 { 246 pcitag_t tag; 247 pcireg_t tmp; 248 249 /* XXX Need to deal with "segment" ("hose" in Alpha terminology). */ 250 251 tag = pci_make_tag(acpi_softc->sc_pc, PciId->Bus, PciId->Device, 252 PciId->Function); 253 254 switch (Width) { 255 case 8: 256 tmp = pci_conf_read(acpi_softc->sc_pc, tag, Register & ~3); 257 tmp &= ~(0xff << ((Register & 3) * 8)); 258 tmp |= (Value << ((Register & 3) * 8)); 259 break; 260 261 case 16: 262 tmp = pci_conf_read(acpi_softc->sc_pc, tag, Register & ~3); 263 tmp &= ~(0xffff << ((Register & 3) * 8)); 264 tmp |= (Value << ((Register & 3) * 8)); 265 break; 266 267 case 32: 268 tmp = Value; 269 break; 270 271 default: 272 return AE_BAD_PARAMETER; 273 } 274 275 pci_conf_write(acpi_softc->sc_pc, tag, Register & ~3, tmp); 276 277 return AE_OK; 278 } 279