acpi_quirks.c revision 1.20 1 1.20 jmcneill /* $NetBSD: acpi_quirks.c,v 1.20 2011/11/14 02:44:59 jmcneill Exp $ */
2 1.19 jruoho
3 1.19 jruoho /*-
4 1.19 jruoho * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 1.19 jruoho * All rights reserved.
6 1.19 jruoho *
7 1.19 jruoho * Redistribution and use in source and binary forms, with or without
8 1.19 jruoho * modification, are permitted provided that the following conditions
9 1.19 jruoho * are met:
10 1.19 jruoho *
11 1.19 jruoho * 1. Redistributions of source code must retain the above copyright
12 1.19 jruoho * notice, this list of conditions and the following disclaimer.
13 1.19 jruoho * 2. Redistributions in binary form must reproduce the above copyright
14 1.19 jruoho * notice, this list of conditions and the following disclaimer in the
15 1.19 jruoho * documentation and/or other materials provided with the distribution.
16 1.19 jruoho *
17 1.19 jruoho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 1.19 jruoho * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 1.19 jruoho * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 1.19 jruoho * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 1.19 jruoho * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.19 jruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 1.19 jruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.19 jruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.19 jruoho * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.19 jruoho * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.19 jruoho * SUCH DAMAGE.
28 1.19 jruoho */
29 1.1 fvdl
30 1.1 fvdl /*
31 1.1 fvdl * Copyright 2002 Wasabi Systems, Inc.
32 1.1 fvdl * All rights reserved.
33 1.1 fvdl *
34 1.1 fvdl * Written by Frank van der Linden for Wasabi Systems, Inc.
35 1.1 fvdl *
36 1.1 fvdl * Redistribution and use in source and binary forms, with or without
37 1.1 fvdl * modification, are permitted provided that the following conditions
38 1.1 fvdl * are met:
39 1.1 fvdl * 1. Redistributions of source code must retain the above copyright
40 1.1 fvdl * notice, this list of conditions and the following disclaimer.
41 1.1 fvdl * 2. Redistributions in binary form must reproduce the above copyright
42 1.1 fvdl * notice, this list of conditions and the following disclaimer in the
43 1.1 fvdl * documentation and/or other materials provided with the distribution.
44 1.1 fvdl * 3. All advertising materials mentioning features or use of this software
45 1.1 fvdl * must display the following acknowledgement:
46 1.1 fvdl * This product includes software developed for the NetBSD Project by
47 1.1 fvdl * Wasabi Systems, Inc.
48 1.1 fvdl * 4. The name of Wasabi Systems, Inc. may not be used to endorse
49 1.1 fvdl * or promote products derived from this software without specific prior
50 1.1 fvdl * written permission.
51 1.1 fvdl *
52 1.1 fvdl * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
53 1.1 fvdl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
54 1.1 fvdl * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55 1.1 fvdl * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
56 1.1 fvdl * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
57 1.1 fvdl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
58 1.1 fvdl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
59 1.1 fvdl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
60 1.1 fvdl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
61 1.1 fvdl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
62 1.1 fvdl * POSSIBILITY OF SUCH DAMAGE.
63 1.1 fvdl */
64 1.1 fvdl
65 1.1 fvdl #include <sys/cdefs.h>
66 1.1 fvdl
67 1.20 jmcneill __KERNEL_RCSID(0, "$NetBSD: acpi_quirks.c,v 1.20 2011/11/14 02:44:59 jmcneill Exp $");
68 1.1 fvdl
69 1.1 fvdl #include "opt_acpi.h"
70 1.1 fvdl
71 1.1 fvdl #include <sys/param.h>
72 1.1 fvdl
73 1.19 jruoho #include <dev/acpi/acpireg.h>
74 1.1 fvdl #include <dev/acpi/acpivar.h>
75 1.1 fvdl
76 1.19 jruoho #define _COMPONENT ACPI_UTILITIES
77 1.19 jruoho ACPI_MODULE_NAME ("acpi_quirks")
78 1.19 jruoho
79 1.12 jruoho #define AQ_GT 0 /* > */
80 1.12 jruoho #define AQ_LT 1 /* < */
81 1.12 jruoho #define AQ_GTE 2 /* >= */
82 1.12 jruoho #define AQ_LTE 3 /* <= */
83 1.12 jruoho #define AQ_EQ 4 /* == */
84 1.12 jruoho
85 1.19 jruoho static int acpi_quirks_revcmp(uint32_t, uint32_t, int);
86 1.7 christos
87 1.5 kochi static struct acpi_quirk acpi_quirks[] = {
88 1.13 jruoho
89 1.13 jruoho { ACPI_SIG_FADT, "ASUS ", 0x30303031, AQ_LTE, "CUV4X-D ",
90 1.13 jruoho ACPI_QUIRK_BROKEN },
91 1.13 jruoho
92 1.9 jmcneill { ACPI_SIG_FADT, "PTLTD ", 0x06040000, AQ_LTE, " FACP ",
93 1.7 christos ACPI_QUIRK_BROKEN },
94 1.13 jruoho
95 1.9 jmcneill { ACPI_SIG_FADT, "NVIDIA", 0x06040000, AQ_EQ, "CK8 ",
96 1.8 fvdl ACPI_QUIRK_IRQ0 },
97 1.13 jruoho
98 1.10 christos { ACPI_SIG_FADT, "HP ", 0x06040012, AQ_LTE, "HWPC20F ",
99 1.10 christos ACPI_QUIRK_BROKEN },
100 1.1 fvdl };
101 1.1 fvdl
102 1.7 christos static int
103 1.19 jruoho acpi_quirks_revcmp(uint32_t tabval, uint32_t wanted, int op)
104 1.7 christos {
105 1.19 jruoho
106 1.7 christos switch (op) {
107 1.19 jruoho
108 1.7 christos case AQ_GT:
109 1.19 jruoho return (tabval > wanted) ? 0 : 1;
110 1.19 jruoho
111 1.7 christos case AQ_LT:
112 1.19 jruoho return (tabval < wanted) ? 0 : 1;
113 1.19 jruoho
114 1.7 christos case AQ_LTE:
115 1.19 jruoho return (tabval <= wanted) ? 0 : 1;
116 1.19 jruoho
117 1.7 christos case AQ_GTE:
118 1.19 jruoho return (tabval >= wanted) ? 0 : 1;
119 1.19 jruoho
120 1.7 christos case AQ_EQ:
121 1.19 jruoho return (tabval == wanted) ? 0 : 1;
122 1.19 jruoho
123 1.19 jruoho default:
124 1.19 jruoho return 1;
125 1.7 christos }
126 1.7 christos }
127 1.7 christos
128 1.18 jmcneill #ifdef ACPI_BLACKLIST_YEAR
129 1.18 jmcneill static int
130 1.19 jruoho acpi_quirks_bios_year(void)
131 1.18 jmcneill {
132 1.20 jmcneill const char *datestr = pmf_get_platform("bios-date");
133 1.18 jmcneill unsigned long date;
134 1.18 jmcneill
135 1.18 jmcneill if (datestr == NULL)
136 1.18 jmcneill return -1;
137 1.18 jmcneill
138 1.18 jmcneill date = strtoul(datestr, NULL, 10);
139 1.18 jmcneill if (date == 0 || date == ULONG_MAX)
140 1.18 jmcneill return -1;
141 1.18 jmcneill if (date < 19000000 || date > 99999999)
142 1.18 jmcneill return -1;
143 1.18 jmcneill return date / 10000;
144 1.18 jmcneill }
145 1.18 jmcneill #endif
146 1.18 jmcneill
147 1.1 fvdl /*
148 1.19 jruoho * Simple function to search the quirk table. Only to be
149 1.19 jruoho * used after AcpiLoadTables() has been successfully called.
150 1.1 fvdl */
151 1.1 fvdl int
152 1.1 fvdl acpi_find_quirks(void)
153 1.1 fvdl {
154 1.9 jmcneill ACPI_TABLE_HEADER fadt, dsdt, xsdt, *hdr;
155 1.19 jruoho struct acpi_quirk *aq;
156 1.19 jruoho ACPI_STATUS rv;
157 1.19 jruoho size_t i, len;
158 1.19 jruoho
159 1.18 jmcneill #ifdef ACPI_BLACKLIST_YEAR
160 1.19 jruoho int year = acpi_quirks_bios_year();
161 1.18 jmcneill
162 1.18 jmcneill if (year != -1 && year <= ACPI_BLACKLIST_YEAR)
163 1.18 jmcneill return ACPI_QUIRK_OLDBIOS;
164 1.18 jmcneill #endif
165 1.1 fvdl
166 1.19 jruoho rv = AcpiGetTableHeader(ACPI_SIG_FADT, 0, &fadt);
167 1.19 jruoho
168 1.19 jruoho if (ACPI_FAILURE(rv))
169 1.19 jruoho (void)memset(&fadt, 0, sizeof(fadt));
170 1.19 jruoho
171 1.19 jruoho rv = AcpiGetTableHeader(ACPI_SIG_DSDT, 0, &dsdt);
172 1.19 jruoho
173 1.19 jruoho if (ACPI_FAILURE(rv))
174 1.19 jruoho (void)memset(&dsdt, 0, sizeof(dsdt));
175 1.19 jruoho
176 1.19 jruoho rv = AcpiGetTableHeader(ACPI_SIG_XSDT, 0, &xsdt);
177 1.19 jruoho
178 1.19 jruoho if (ACPI_FAILURE(rv))
179 1.19 jruoho (void)memset(&xsdt, 0, sizeof(xsdt));
180 1.19 jruoho
181 1.19 jruoho for (i = 0; i < __arraycount(acpi_quirks); i++) {
182 1.19 jruoho
183 1.19 jruoho aq = &acpi_quirks[i];
184 1.1 fvdl
185 1.19 jruoho if (strncmp(aq->aq_tabletype, ACPI_SIG_DSDT, 4) == 0)
186 1.9 jmcneill hdr = &dsdt;
187 1.19 jruoho else if (strncmp(aq->aq_tabletype, ACPI_SIG_XSDT, 4) == 0)
188 1.9 jmcneill hdr = &xsdt;
189 1.19 jruoho else if (strncmp(aq->aq_tabletype, ACPI_SIG_FADT, 4) == 0)
190 1.9 jmcneill hdr = &fadt;
191 1.19 jruoho else {
192 1.7 christos continue;
193 1.19 jruoho }
194 1.19 jruoho
195 1.19 jruoho len = strlen(aq->aq_oemid);
196 1.19 jruoho
197 1.19 jruoho if (strncmp(aq->aq_oemid, hdr->OemId, len) != 0)
198 1.7 christos continue;
199 1.19 jruoho
200 1.19 jruoho if (acpi_quirks_revcmp(aq->aq_oemrev,
201 1.19 jruoho hdr->OemRevision, aq->aq_cmpop) != 0)
202 1.7 christos continue;
203 1.19 jruoho
204 1.19 jruoho len = strlen(aq->aq_tabid);
205 1.19 jruoho
206 1.19 jruoho if (strncmp(aq->aq_tabid, hdr->OemTableId, len) != 0)
207 1.7 christos continue;
208 1.19 jruoho
209 1.19 jruoho return aq->aq_quirks;
210 1.1 fvdl }
211 1.19 jruoho
212 1.1 fvdl return 0;
213 1.1 fvdl }
214 1.19 jruoho
215 1.19 jruoho /*
216 1.19 jruoho * Add or delete a string to the list that should return
217 1.19 jruoho * true when _OSI is being queried. The defaults are:
218 1.19 jruoho *
219 1.19 jruoho * "Windows 2000" # Windows 2000
220 1.19 jruoho * "Windows 2001" # Windows XP
221 1.19 jruoho * "Windows 2001 SP1" # Windows XP SP1
222 1.19 jruoho * "Windows 2001.1" # Windows Server 2003
223 1.19 jruoho * "Windows 2001 SP2" # Windows XP SP2
224 1.19 jruoho * "Windows 2001.1 SP1" # Windows Server 2003 SP1
225 1.19 jruoho * "Windows 2006" # Windows Vista
226 1.19 jruoho * "Windows 2006.1" # Windows Server 2008
227 1.19 jruoho * "Windows 2006 SP1" # Windows Vista SP1
228 1.19 jruoho * "Windows 2006 SP2" # Windows Vista SP2
229 1.19 jruoho * "Windows 2009" # Windows 7 and Server 2008
230 1.19 jruoho */
231 1.19 jruoho int
232 1.19 jruoho acpi_quirks_osi_add(const char *str)
233 1.19 jruoho {
234 1.19 jruoho ACPI_STATUS rv;
235 1.19 jruoho
236 1.19 jruoho if (str == NULL || *str == '\0')
237 1.19 jruoho return EINVAL;
238 1.19 jruoho
239 1.19 jruoho rv = AcpiInstallInterface(__UNCONST(str));
240 1.19 jruoho
241 1.19 jruoho return (rv != AE_OK) ? EIO : 0;
242 1.19 jruoho }
243 1.19 jruoho
244 1.19 jruoho int
245 1.19 jruoho acpi_quirks_osi_del(const char *str)
246 1.19 jruoho {
247 1.19 jruoho ACPI_STATUS rv;
248 1.19 jruoho
249 1.19 jruoho if (str == NULL || *str == '\0')
250 1.19 jruoho return EINVAL;
251 1.19 jruoho
252 1.19 jruoho rv = AcpiRemoveInterface(__UNCONST(str));
253 1.19 jruoho
254 1.19 jruoho return (rv != AE_OK) ? EIO : 0;
255 1.19 jruoho }
256 1.19 jruoho
257 1.19 jruoho #if 0
258 1.19 jruoho static void
259 1.19 jruoho acpi_quirks_osi_linux(void)
260 1.19 jruoho {
261 1.19 jruoho (void)acpi_quirks_osi_add("Linux");
262 1.19 jruoho }
263 1.19 jruoho
264 1.19 jruoho static void
265 1.19 jruoho acpi_quirks_osi_vista(void)
266 1.19 jruoho {
267 1.19 jruoho (void)acpi_quirks_osi_del("Windows 2006");
268 1.19 jruoho (void)acpi_quirks_osi_del("Windows 2006 SP1");
269 1.19 jruoho (void)acpi_quirks_osi_del("Windows 2006 SP2");
270 1.19 jruoho }
271 1.19 jruoho #endif
272