xref: /illumos-gate/usr/src/uts/intel/io/acpica/acpica.c (revision 34e8da7bb80a19606c8d37c60d6cf4e0cb9ad163)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /*
26  * Solaris x86 ACPI CA services
27  */
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 
32 #include <sys/file.h>
33 #include <sys/errno.h>
34 #include <sys/conf.h>
35 #include <sys/modctl.h>
36 #include <sys/open.h>
37 #include <sys/stat.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 #include <sys/esunddi.h>
41 
42 #include <sys/acpi/acpi.h>
43 #include <sys/acpica.h>
44 
45 /*
46  *
47  */
48 static	struct modlmisc modlmisc = {
49 	&mod_miscops,
50 	"ACPI interpreter %I%",
51 };
52 
53 static	struct modlinkage modlinkage = {
54 	MODREV_1,		/* MODREV_1 manual */
55 	(void *)&modlmisc,	/* module linkage */
56 	NULL,			/* list terminator */
57 };
58 
59 /*
60  * Local data
61  */
62 
63 static kmutex_t	acpica_module_lock;
64 
65 /*
66  * State of acpica subsystem
67  * After successful initialization, will be ACPICA_INITIALIZED
68  */
69 int acpica_init_state = ACPICA_NOT_INITIALIZED;
70 
71 /*
72  * Following are set by acpica_process_user_options()
73  *
74  * acpica_enable = FALSE prevents initialization of ACPI CA
75  * completely
76  *
77  * acpi_init_level determines level of ACPI CA functionality
78  * enabled in acpica_init()
79  */
80 int	acpica_enable;
81 UINT32	acpi_init_level;
82 
83 /*
84  * Non-zero enables lax behavior with respect to some
85  * common ACPI BIOS issues; see ACPI CA documentation
86  * Setting this to zero causes ACPI CA to enforce strict
87  * compliance with ACPI specification
88  */
89 int acpica_enable_interpreter_slack = 1;
90 
91 /*
92  * For non-DEBUG builds, set the ACPI CA debug level to 0
93  * to quiet chatty BIOS output into /var/adm/messages
94  * Field-patchable for diagnostic use.
95  */
96 #ifdef  DEBUG
97 int acpica_muzzle_debug_output = 0;
98 #else
99 int acpica_muzzle_debug_output = 1;
100 #endif
101 
102 
103 int
104 _init(void)
105 {
106 	int error = EBUSY;
107 	int	status;
108 
109 	mutex_init(&acpica_module_lock, NULL, MUTEX_DRIVER, NULL);
110 
111 	if ((error = mod_install(&modlinkage)) != 0) {
112 		mutex_destroy(&acpica_module_lock);
113 	}
114 
115 	AcpiGbl_EnableInterpreterSlack = (acpica_enable_interpreter_slack != 0);
116 
117 	if ((status = AcpiInitializeSubsystem()) != AE_OK) {
118 		cmn_err(CE_WARN, "!acpica: error pre-init:1:%d", status);
119 	}
120 
121 	return (error);
122 }
123 
124 int
125 _info(struct modinfo *modinfop)
126 {
127 	return (mod_info(&modlinkage, modinfop));
128 }
129 
130 int
131 _fini(void)
132 {
133 	/*
134 	 * acpica module is never unloaded at run-time; there's always
135 	 * a PSM depending on it, at the very least
136 	 */
137 	return (EBUSY);
138 }
139 
140 /*
141  * Install acpica-provided address-space handlers
142  */
143 static int
144 acpica_install_handlers()
145 {
146 	ACPI_STATUS	rv = AE_OK;
147 
148 	/*
149 	 * Install ACPI CA default handlers
150 	 */
151 	if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
152 	    ACPI_ADR_SPACE_SYSTEM_MEMORY,
153 	    ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) {
154 		cmn_err(CE_WARN, "!acpica: no default handler for"
155 		    " system memory");
156 		rv = AE_ERROR;
157 	}
158 
159 	if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
160 	    ACPI_ADR_SPACE_SYSTEM_IO,
161 	    ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) {
162 		cmn_err(CE_WARN, "!acpica: no default handler for"
163 		    " system I/O");
164 		rv = AE_ERROR;
165 	}
166 
167 	if (AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
168 	    ACPI_ADR_SPACE_PCI_CONFIG,
169 	    ACPI_DEFAULT_HANDLER, NULL, NULL) != AE_OK) {
170 		cmn_err(CE_WARN, "!acpica: no default handler for"
171 		    " PCI Config");
172 		rv = AE_ERROR;
173 	}
174 
175 
176 	return (rv);
177 }
178 
179 /*
180  * Find the BIOS date, and return TRUE if supplied
181  * date is same or later than the BIOS date, or FALSE
182  * if the BIOS date can't be fetched for any reason
183  */
184 static int
185 acpica_check_bios_date(int yy, int mm, int dd)
186 {
187 
188 	char *datep;
189 	int bios_year, bios_month, bios_day;
190 
191 	/* If firmware has no bios, skip the check */
192 	if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(), 0, "bios-free"))
193 		return (TRUE);
194 
195 	/*
196 	 * PC BIOSes contain a string in the form of
197 	 * "mm/dd/yy" at absolute address 0xffff5,
198 	 * where mm, dd and yy are all ASCII digits.
199 	 * We map the string, pluck out the values,
200 	 * and accept all BIOSes from 1 Jan 1999 on
201 	 * as valid.
202 	 */
203 
204 	if ((int)AcpiOsMapMemory(0xffff5, 8, (void **) &datep) != AE_OK)
205 		return (FALSE);
206 
207 	/* year */
208 	bios_year = ((int)(*(datep + 6) - '0') * 10) + (*(datep + 7) - '0');
209 	/* month */
210 	bios_month = ((int)(*datep - '0') * 10) + (*(datep + 1) - '0');
211 	/* day */
212 	bios_day = ((int)(*(datep + 3) - '0') * 10) + (*(datep + 4) - '0');
213 
214 	AcpiOsUnmapMemory((void *) datep, 8);
215 
216 	if (bios_year < 0 || bios_year > 99 || bios_month < 0 ||
217 	    bios_month > 99 || bios_day < 0 || bios_day > 99) {
218 		/* non-digit chars in BIOS date */
219 		return (FALSE);
220 	}
221 
222 	/*
223 	 * Adjust for 2-digit year; note to grand-children:
224 	 * need a new scheme before 2080 rolls around
225 	 */
226 	bios_year += (bios_year >= 80 && bios_year <= 99) ?
227 	    1900 : 2000;
228 
229 	if (bios_year < yy)
230 		return (FALSE);
231 	else if (bios_year > yy)
232 		return (TRUE);
233 
234 	if (bios_month < mm)
235 		return (FALSE);
236 	else if (bios_month > mm)
237 		return (TRUE);
238 
239 	if (bios_day < dd)
240 		return (FALSE);
241 
242 	return (TRUE);
243 }
244 
245 /*
246  * Check for Metropolis systems with BIOSes older than 10/12/04
247  * return TRUE if BIOS requires legacy mode, FALSE otherwise
248  */
249 static int
250 acpica_metro_old_bios()
251 {
252 	ACPI_TABLE_HEADER *fadt;
253 
254 	/* get the FADT */
255 	if (AcpiGetFirmwareTable(FADT_SIG, 1, ACPI_LOGICAL_ADDRESSING,
256 	    (ACPI_TABLE_HEADER **)&fadt) != AE_OK)
257 		return (FALSE);
258 
259 	/* compare OEM Table ID to "SUNmetro" - no match, return false */
260 	if (strncmp("SUNmetro", fadt->OemTableId, 8))
261 		return (FALSE);
262 
263 	/* On a Metro - return FALSE if later than 10/12/04 */
264 	return (!acpica_check_bios_date(2004, 10, 12));
265 }
266 
267 
268 /*
269  * Process acpi-user-options property  if present
270  */
271 static void
272 acpica_process_user_options()
273 {
274 	static int processed = 0;
275 	int acpi_user_options;
276 	char *acpi_prop;
277 
278 	/*
279 	 * return if acpi-user-options has already been processed
280 	 */
281 	if (processed)
282 		return;
283 	else
284 		processed = 1;
285 
286 	/* converts acpi-user-options from type string to int, if any */
287 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
288 	    DDI_PROP_DONTPASS, "acpi-user-options", &acpi_prop) ==
289 	    DDI_PROP_SUCCESS) {
290 		long data;
291 		int ret;
292 		ret = ddi_strtol(acpi_prop, NULL, 0, &data);
293 		if (ret == 0) {
294 			e_ddi_prop_remove(DDI_DEV_T_NONE, ddi_root_node(),
295 			    "acpi-user-options");
296 			e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(),
297 			    "acpi-user-options", data);
298 		}
299 		ddi_prop_free(acpi_prop);
300 	}
301 
302 	/*
303 	 * fetch the optional options property
304 	 */
305 	acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 0,
306 	    "acpi-user-options", 0);
307 
308 	/*
309 	 * Note that 'off' has precedence over 'on'
310 	 * Also note - all cases of ACPI_OUSER_MASK
311 	 * provided here, no default: case is present
312 	 */
313 	switch (acpi_user_options & ACPI_OUSER_MASK) {
314 	case ACPI_OUSER_DFLT:
315 		acpica_enable = acpica_check_bios_date(1999, 1, 1);
316 		break;
317 	case ACPI_OUSER_ON:
318 		acpica_enable = TRUE;
319 		break;
320 	case ACPI_OUSER_OFF:
321 	case ACPI_OUSER_OFF | ACPI_OUSER_ON:
322 		acpica_enable = FALSE;
323 		break;
324 	}
325 
326 	acpi_init_level = ACPI_FULL_INITIALIZATION;
327 
328 	/*
329 	 * special test here; may be generalized in the
330 	 * future - test for a machines that are known to
331 	 * work only in legacy mode, and set OUSER_LEGACY if
332 	 * we're on one
333 	 */
334 	if (acpica_metro_old_bios())
335 		acpi_user_options |= ACPI_OUSER_LEGACY;
336 
337 	/*
338 	 * If legacy mode is specified, set initialization
339 	 * options to avoid entering ACPI mode and hooking SCI
340 	 * - basically try to act like legacy acpi_intp
341 	 */
342 	if ((acpi_user_options & ACPI_OUSER_LEGACY) != 0)
343 		acpi_init_level |= (ACPI_NO_ACPI_ENABLE | ACPI_NO_HANDLER_INIT);
344 
345 	/*
346 	 * modify default ACPI CA debug output level for non-DEBUG builds
347 	 * (to avoid BIOS debug chatter in /var/adm/messages)
348 	 */
349 	if (acpica_muzzle_debug_output)
350 		AcpiDbgLevel = 0;
351 }
352 
353 /*
354  * Initialize the CA subsystem if it hasn't been done already
355  */
356 int
357 acpica_init()
358 {
359 	ACPI_STATUS status;
360 
361 	/*
362 	 * Make sure user options are processed,
363 	 * then fail to initialize if ACPI CA has been
364 	 * disabled
365 	 */
366 	acpica_process_user_options();
367 	if (!acpica_enable)
368 		return (AE_ERROR);
369 
370 	mutex_enter(&acpica_module_lock);
371 
372 	if (acpica_init_state == ACPICA_NOT_INITIALIZED) {
373 		if ((status = AcpiLoadTables()) != AE_OK) {
374 			goto error;
375 		}
376 		if ((status = acpica_install_handlers()) != AE_OK) {
377 			goto error;
378 		}
379 		if ((status = AcpiEnableSubsystem(acpi_init_level)) != AE_OK) {
380 			goto error;
381 		}
382 		if ((status = AcpiInitializeObjects(0)) != AE_OK) {
383 			goto error;
384 		}
385 		/*
386 		 * Initialize EC
387 		 */
388 		acpica_ec_init();
389 
390 		acpica_init_state = ACPICA_INITIALIZED;
391 error:
392 		if (acpica_init_state != ACPICA_INITIALIZED) {
393 			cmn_err(CE_NOTE, "!failed to initialize"
394 			    " ACPI services");
395 		}
396 	} else
397 		status = AE_OK;
398 
399 	/*
400 	 * Set acpi-status to 13 if acpica has been initialized successfully.
401 	 * This indicates that acpica is up and running.  This variable name
402 	 * and value were chosen in order to remain compatible with acpi_intp.
403 	 */
404 	e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(), "acpi-status",
405 		(status == AE_OK) ? (ACPI_BOOT_INIT | ACPI_BOOT_ENABLE |
406 		ACPI_BOOT_BOOTCONF) : 0);
407 
408 	mutex_exit(&acpica_module_lock);
409 	return (status);
410 }
411 
412 /*
413  * SCI handling
414  */
415 
416 ACPI_STATUS
417 acpica_get_sci(int *sci_irq, iflag_t *sci_flags)
418 {
419 	APIC_HEADER		*ap;
420 	MULTIPLE_APIC_TABLE	*mat;
421 	MADT_INTERRUPT_OVERRIDE	*mio;
422 	FADT_DESCRIPTOR		*fadt;
423 	int			madt_seen, madt_size;
424 
425 
426 	/*
427 	 * Make sure user options are processed,
428 	 * then return error if ACPI CA has been
429 	 * disabled or system is not running in ACPI
430 	 * and won't need/understand SCI
431 	 */
432 	acpica_process_user_options();
433 	if ((!acpica_enable) || (acpi_init_level & ACPI_NO_ACPI_ENABLE))
434 		return (AE_ERROR);
435 
436 	/*
437 	 * according to Intel ACPI developers, SCI
438 	 * conforms to PCI bus conventions; level/low
439 	 * unless otherwise directed by overrides.
440 	 */
441 	sci_flags->intr_el = INTR_EL_LEVEL;
442 	sci_flags->intr_po = INTR_PO_ACTIVE_LOW;
443 	sci_flags->bustype = BUS_PCI;	/*  we *do* conform to PCI */
444 
445 	/* get the SCI from the FADT */
446 	if (AcpiGetFirmwareTable(FADT_SIG, 1, ACPI_LOGICAL_ADDRESSING,
447 	    (ACPI_TABLE_HEADER **)&fadt) != AE_OK)
448 		return (AE_ERROR);
449 
450 	*sci_irq = fadt->SciInt;
451 
452 	/* search for ISOs that modify it */
453 	/* if we don't find a MADT, that's OK; no ISOs then */
454 	if (AcpiGetFirmwareTable(APIC_SIG, 1, ACPI_LOGICAL_ADDRESSING,
455 			    (ACPI_TABLE_HEADER **) &mat) != AE_OK) {
456 		return (AE_OK);
457 	}
458 
459 	ap = (APIC_HEADER *) (mat + 1);
460 	madt_size = mat->Length;
461 	madt_seen = sizeof (*mat);
462 
463 	while (madt_seen < madt_size) {
464 		switch (ap->Type) {
465 		case APIC_XRUPT_OVERRIDE:
466 			mio = (MADT_INTERRUPT_OVERRIDE *) ap;
467 			if (mio->Source == *sci_irq) {
468 				*sci_irq = mio->Interrupt;
469 				sci_flags->intr_el = mio->TriggerMode;
470 				sci_flags->intr_po = mio->Polarity;
471 			}
472 			break;
473 		}
474 
475 		/* advance to next entry */
476 		madt_seen += ap->Length;
477 		ap = (APIC_HEADER *)(((char *)ap) + ap->Length);
478 	}
479 
480 	/*
481 	 * One more check; if ISO said "conform", revert to default
482 	 */
483 	if (sci_flags->intr_el == INTR_EL_CONFORM)
484 		sci_flags->intr_el = INTR_EL_LEVEL;
485 	if (sci_flags->intr_po == INTR_PO_CONFORM)
486 		sci_flags->intr_po = INTR_PO_ACTIVE_LOW;
487 
488 	return (AE_OK);
489 }
490