1 | /* $NetBSD: OsdHardware.c,v 1.10 2016/01/26 22:52:14 christos 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.10 2016/01/26 22:52:14 christos 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 &= ~(0xff << ((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 &= ~(0xffff << ((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 | |