xref: /netbsd-src/sys/dev/acpi/acpica/OsdHardware.c (revision 9bc9ab6dd7ad133c0f1a157e74967e7c98796b6f)
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
AcpiOsReadPort(ACPI_IO_ADDRESS Address,UINT32 * Value,UINT32 Width)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
AcpiOsWritePort(ACPI_IO_ADDRESS Address,UINT32 Value,UINT32 Width)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
AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address,UINT64 * Value,UINT32 Width)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
AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address,UINT64 Value,UINT32 Width)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
AcpiOsReadPciConfiguration(ACPI_PCI_ID * PciId,UINT32 Register,UINT64 * Value,UINT32 Width)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
AcpiOsWritePciConfiguration(ACPI_PCI_ID * PciId,UINT32 Register,ACPI_INTEGER Value,UINT32 Width)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