Home | History | Annotate | Line # | Download | only in acpica
OsdHardware.c revision 1.15
      1 /*	$NetBSD: OsdHardware.c,v 1.15 2024/06/23 15:21:52 andvar 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.15 2024/06/23 15:21:52 andvar Exp $");
     48 
     49 #include "pci.h"
     50 
     51 #include <sys/param.h>
     52 #include <sys/device.h>
     53 
     54 #include <dev/acpi/acpica.h>
     55 #include <dev/acpi/acpivar.h>
     56 #include <dev/acpi/acpi_pci.h>
     57 
     58 #include <machine/acpi_machdep.h>
     59 
     60 /*
     61  * ACPICA doesn't provide much in the way of letting us know which
     62  * hardware resources it wants to use.  We therefore have to resort
     63  * to calling machine-dependent code to do the access for us.
     64  */
     65 
     66 /*
     67  * AcpiOsReadPort:
     68  *
     69  *	Read a value from an input port.
     70  */
     71 ACPI_STATUS
     72 AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
     73 {
     74 
     75 	switch (Width) {
     76 	case 8:
     77 		*Value = acpi_md_OsIn8(Address);
     78 		break;
     79 
     80 	case 16:
     81 		*Value = acpi_md_OsIn16(Address);
     82 		break;
     83 
     84 	case 32:
     85 		*Value = acpi_md_OsIn32(Address);
     86 		break;
     87 
     88 	default:
     89 		return AE_BAD_PARAMETER;
     90 	}
     91 
     92 	return AE_OK;
     93 }
     94 
     95 /*
     96  * AcpiOsWritePort:
     97  *
     98  *	Write a value to an output port.
     99  */
    100 ACPI_STATUS
    101 AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
    102 {
    103 
    104 	switch (Width) {
    105 	case 8:
    106 		acpi_md_OsOut8(Address, Value);
    107 		break;
    108 
    109 	case 16:
    110 		acpi_md_OsOut16(Address, Value);
    111 		break;
    112 
    113 	case 32:
    114 		acpi_md_OsOut32(Address, Value);
    115 		break;
    116 
    117 	default:
    118 		return AE_BAD_PARAMETER;
    119 	}
    120 
    121 	return AE_OK;
    122 }
    123 
    124 /*
    125  * AcpiOsReadMemory:
    126  *
    127  *	Read a value from a memory location.
    128  */
    129 ACPI_STATUS
    130 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
    131 {
    132 	void *LogicalAddress;
    133 	ACPI_STATUS rv = AE_OK;
    134 
    135 	LogicalAddress = AcpiOsMapMemory(Address, Width / 8);
    136 	if (LogicalAddress == NULL)
    137 		return AE_NOT_EXIST;
    138 
    139 	switch (Width) {
    140 	case 8:
    141 		*Value = *(volatile uint8_t *) LogicalAddress;
    142 		break;
    143 
    144 	case 16:
    145 		*Value = *(volatile uint16_t *) LogicalAddress;
    146 		break;
    147 
    148 	case 32:
    149 		*Value = *(volatile uint32_t *) LogicalAddress;
    150 		break;
    151 
    152 	case 64:
    153 		*Value = *(volatile uint64_t *) LogicalAddress;
    154 		break;
    155 
    156 	default:
    157 		rv = AE_BAD_PARAMETER;
    158 	}
    159 
    160 	AcpiOsUnmapMemory(LogicalAddress, Width / 8);
    161 
    162 	return rv;
    163 }
    164 
    165 /*
    166  * AcpiOsWriteMemory:
    167  *
    168  *	Write a value to a memory location.
    169  */
    170 ACPI_STATUS
    171 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
    172 {
    173 	void *LogicalAddress;
    174 	ACPI_STATUS rv = AE_OK;
    175 
    176 	LogicalAddress = AcpiOsMapMemory(Address, Width / 8);
    177 	if (LogicalAddress == NULL)
    178 		return AE_NOT_FOUND;
    179 
    180 	switch (Width) {
    181 	case 8:
    182 		*(volatile uint8_t *) LogicalAddress = Value;
    183 		break;
    184 
    185 	case 16:
    186 		*(volatile uint16_t *) LogicalAddress = Value;
    187 		break;
    188 
    189 	case 32:
    190 		*(volatile uint32_t *) LogicalAddress = Value;
    191 		break;
    192 
    193 	case 64:
    194 		*(volatile uint64_t *) LogicalAddress = Value;
    195 		break;
    196 
    197 	default:
    198 		rv = AE_BAD_PARAMETER;
    199 	}
    200 
    201 	AcpiOsUnmapMemory(LogicalAddress, Width / 8);
    202 
    203 	return rv;
    204 }
    205 
    206 /*
    207  * AcpiOsReadPciConfiguration:
    208  *
    209  *	Read a value from a PCI configuration register.
    210  */
    211 ACPI_STATUS
    212 AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value,
    213     UINT32 Width)
    214 {
    215 #if NPCI > 0
    216 	pci_chipset_tag_t pc;
    217 	pcitag_t tag;
    218 	pcireg_t tmp;
    219 
    220 	if (PciId->Bus >= 256 || PciId->Device >= 32 || PciId->Function >= 8)
    221 		return AE_BAD_PARAMETER;
    222 
    223 	pc = acpi_pcidev_get_tag(PciId->Segment, PciId->Bus, PciId->Device, PciId->Function);
    224 
    225 	tag = pci_make_tag(pc, PciId->Bus, PciId->Device, PciId->Function);
    226 	tmp = pci_conf_read(pc, tag, Register & ~3);
    227 
    228 	switch (Width) {
    229 	case 8:
    230 		*Value = (tmp >> ((Register & 3) * 8)) & 0xff;
    231 		break;
    232 
    233 	case 16:
    234 		*Value = (tmp >> ((Register & 3) * 8)) & 0xffff;
    235 		break;
    236 
    237 	case 32:
    238 		*Value = tmp;
    239 		break;
    240 
    241 	default:
    242 		return AE_BAD_PARAMETER;
    243 	}
    244 
    245 	return AE_OK;
    246 #else
    247 	return AE_BAD_PARAMETER;
    248 #endif
    249 }
    250 
    251 /*
    252  * AcpiOsWritePciConfiguration:
    253  *
    254  *	Write a value to a PCI configuration register.
    255  */
    256 ACPI_STATUS
    257 AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
    258     ACPI_INTEGER Value, UINT32 Width)
    259 {
    260 #if NPCI > 0
    261 	pci_chipset_tag_t pc;
    262 	pcitag_t tag;
    263 	pcireg_t tmp;
    264 
    265 	pc = acpi_pcidev_get_tag(PciId->Segment, PciId->Bus, PciId->Device, PciId->Function);
    266 	tag = pci_make_tag(pc, PciId->Bus, PciId->Device, PciId->Function);
    267 
    268 	switch (Width) {
    269 	case 8:
    270 		tmp = pci_conf_read(pc, tag, Register & ~3);
    271 		tmp &= ~(0xffu << ((Register & 3) * 8));
    272 		tmp |= (Value << ((Register & 3) * 8));
    273 		break;
    274 
    275 	case 16:
    276 		tmp = pci_conf_read(pc, tag, Register & ~3);
    277 		tmp &= ~(0xffffu << ((Register & 3) * 8));
    278 		tmp |= (Value << ((Register & 3) * 8));
    279 		break;
    280 
    281 	case 32:
    282 		tmp = Value;
    283 		break;
    284 
    285 	default:
    286 		return AE_BAD_PARAMETER;
    287 	}
    288 
    289 	pci_conf_write(pc, tag, Register & ~3, tmp);
    290 
    291 	return AE_OK;
    292 #else
    293 	return AE_BAD_PARAMETER;
    294 #endif
    295 }
    296