xref: /haiku/src/add-ons/kernel/bus_managers/acpi/EmbeddedController.cpp (revision 4d8811742fa447ec05b4993a16a0931bc29aafab)
1 /*
2  * Copyright 2013, Jérôme Duval, korli@users.berlios.de.
3  * Copyright (c) 2009 Clemens Zeidler
4  * Copyright (c) 2003-2007 Nate Lawson
5  * Copyright (c) 2000 Michael Smith
6  * Copyright (c) 2000 BSDi
7  * All rights reserved.
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  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 
32 #include "EmbeddedController.h"
33 
34 #include <kernel.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include <condition_variable.h>
40 #include <Errors.h>
41 #include <KernelExport.h>
42 #include <drivers/PCI.h>
43 
44 
45 #define ACPI_EC_DRIVER_NAME "drivers/power/acpi_embedded_controller/driver_v1"
46 
47 #define ACPI_EC_DEVICE_NAME "drivers/power/acpi_embedded_controller/device_v1"
48 
49 /* Base Namespace devices are published to */
50 #define ACPI_EC_BASENAME "power/embedded_controller/%d"
51 
52 // name of pnp generator of path ids
53 #define ACPI_EC_PATHID_GENERATOR "embedded_controller/path_id"
54 
55 
56 uint8
57 bus_space_read_1(int address)
58 {
59 	return gPCIManager->read_io_8(address);
60 }
61 
62 
63 void
64 bus_space_write_1(int address, uint8 value)
65 {
66 	gPCIManager->write_io_8(address, value);
67 }
68 
69 
70 status_t
71 acpi_GetInteger(acpi_device_module_info* acpi, acpi_device& acpiCookie,
72 	const char* path, int* number)
73 {
74 	acpi_data buf;
75 	acpi_object_type object;
76 	buf.pointer = &object;
77 	buf.length = sizeof(acpi_object_type);
78 
79 	// Assume that what we've been pointed at is an Integer object, or
80 	// a method that will return an Integer.
81 	status_t status = acpi->evaluate_method(acpiCookie, path, NULL, &buf);
82 	if (status == B_OK) {
83 		if (object.object_type == ACPI_TYPE_INTEGER)
84 			*number = object.integer.integer;
85 		else
86 			status = B_BAD_VALUE;
87 	}
88 	return status;
89 }
90 
91 
92 acpi_handle
93 acpi_GetReference(acpi_module_info* acpi, acpi_handle scope,
94 	acpi_object_type* obj)
95 {
96 	if (obj == NULL)
97 		return NULL;
98 
99 	switch (obj->object_type) {
100 		case ACPI_TYPE_LOCAL_REFERENCE:
101 		case ACPI_TYPE_ANY:
102 			return obj->reference.handle;
103 
104 		case ACPI_TYPE_STRING:
105 		{
106 			// The String object usually contains a fully-qualified path, so
107 			// scope can be NULL.
108 			// TODO: This may not always be the case.
109 			acpi_handle handle;
110 			if (acpi->get_handle(scope, obj->string.string, &handle)
111 					== B_OK)
112 				return handle;
113 		}
114 	}
115 
116 	return NULL;
117 }
118 
119 
120 status_t
121 acpi_PkgInt(acpi_object_type* res, int idx, int* dst)
122 {
123 	acpi_object_type* obj = &res->package.objects[idx];
124 	if (obj == NULL || obj->object_type != ACPI_TYPE_INTEGER)
125 		return B_BAD_VALUE;
126 	*dst = obj->integer.integer;
127 
128 	return B_OK;
129 }
130 
131 
132 status_t
133 acpi_PkgInt32(acpi_object_type* res, int idx, uint32* dst)
134 {
135 	int tmp;
136 
137 	status_t status = acpi_PkgInt(res, idx, &tmp);
138 	if (status == B_OK)
139 		*dst = (uint32) tmp;
140 
141 	return status;
142 }
143 
144 
145 acpi_status
146 embedded_controller_io_ports_parse_callback(ACPI_RESOURCE* resource,
147 	void* _context)
148 {
149 	acpi_ec_cookie* sc = (acpi_ec_cookie*)_context;
150 	if (resource->Type != ACPI_RESOURCE_TYPE_IO)
151 		return AE_OK;
152 	if (sc->ec_data_pci_address == 0) {
153 		sc->ec_data_pci_address = resource->Data.Io.Minimum;
154 	} else if (sc->ec_csr_pci_address == 0) {
155 		sc->ec_csr_pci_address = resource->Data.Io.Minimum;
156 	} else {
157 		return AE_CTRL_TERMINATE;
158 	}
159 
160 	return AE_OK;
161 }
162 
163 
164 // #pragma mark -
165 
166 
167 static status_t
168 embedded_controller_open(void* initCookie, const char* path, int flags,
169 	void** cookie)
170 {
171 	acpi_ec_cookie* device = (acpi_ec_cookie*) initCookie;
172 	*cookie = device;
173 
174 	return B_OK;
175 }
176 
177 
178 static status_t
179 embedded_controller_close(void* cookie)
180 {
181 	return B_OK;
182 }
183 
184 
185 static status_t
186 embedded_controller_read(void* _cookie, off_t position, void* buffer,
187 	size_t* numBytes)
188 {
189 	return B_IO_ERROR;
190 }
191 
192 
193 static status_t
194 embedded_controller_write(void* cookie, off_t position, const void* buffer,
195 	size_t* numBytes)
196 {
197 	return B_IO_ERROR;
198 }
199 
200 
201 status_t
202 embedded_controller_control(void* _cookie, uint32 op, void* arg, size_t len)
203 {
204 	return B_ERROR;
205 }
206 
207 
208 static status_t
209 embedded_controller_free(void* cookie)
210 {
211 	return B_OK;
212 }
213 
214 
215 //	#pragma mark - driver module API
216 
217 
218 static int32
219 acpi_get_type(device_node* dev)
220 {
221 	const char *bus;
222 	if (gDeviceManager->get_attr_string(dev, B_DEVICE_BUS, &bus, false))
223 		return -1;
224 
225 	if (strcmp(bus, "acpi"))
226 		return -1;
227 
228 	uint32 deviceType;
229 	if (gDeviceManager->get_attr_uint32(dev, ACPI_DEVICE_TYPE_ITEM,
230 			&deviceType, false) != B_OK)
231 		return -1;
232 
233 	return deviceType;
234 }
235 
236 
237 static float
238 embedded_controller_support(device_node* dev)
239 {
240 	TRACE("embedded_controller_support()\n");
241 
242 	// Check that this is a device
243 	if (acpi_get_type(dev) != ACPI_TYPE_DEVICE)
244 		return 0.0;
245 
246 	const char* name;
247 	if (gDeviceManager->get_attr_string(dev, ACPI_DEVICE_HID_ITEM, &name, false)
248 			!= B_OK)
249 		return 0.0;
250 
251 	// Test all known IDs
252 
253 	static const char* kEmbeddedControllerIDs[] = { "PNP0C09" };
254 
255 	for (size_t i = 0; i < sizeof(kEmbeddedControllerIDs)
256 			/ sizeof(kEmbeddedControllerIDs[0]); i++) {
257 		if (!strcmp(name, kEmbeddedControllerIDs[i])) {
258 			TRACE("supported device found %s\n", name);
259 			return 0.6;
260 		}
261 	}
262 
263 	return 0.0;
264 }
265 
266 
267 static status_t
268 embedded_controller_register_device(device_node* node)
269 {
270 	device_attr attrs[] = {
271 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
272 			{ string: "ACPI embedded controller" }},
273 		{ NULL }
274 	};
275 
276 	return gDeviceManager->register_node(node, ACPI_EC_DRIVER_NAME, attrs,
277 		NULL, NULL);
278 }
279 
280 
281 static status_t
282 embedded_controller_init_driver(device_node* dev, void** _driverCookie)
283 {
284 	TRACE("init driver\n");
285 
286 	acpi_ec_cookie* sc;
287 	sc = (acpi_ec_cookie*)malloc(sizeof(acpi_ec_cookie));
288 	if (sc == NULL)
289 		return B_NO_MEMORY;
290 
291 	memset(sc, 0, sizeof(acpi_ec_cookie));
292 
293 	*_driverCookie = sc;
294 	sc->ec_dev = dev;
295 
296 	sc->ec_condition_var.Init(NULL, "ec condition variable");
297 	mutex_init(&sc->ec_lock, "ec lock");
298 	device_node* parent = gDeviceManager->get_parent_node(dev);
299 	gDeviceManager->get_driver(parent, (driver_module_info**)&sc->ec_acpi,
300 		(void**)&sc->ec_handle);
301 	gDeviceManager->put_node(parent);
302 
303 	if (get_module(B_ACPI_MODULE_NAME, (module_info**)&sc->ec_acpi_module)
304 			!= B_OK)
305 		return B_ERROR;
306 
307 	acpi_data buf;
308 	buf.pointer = NULL;
309 	buf.length = ACPI_ALLOCATE_BUFFER;
310 
311 	// Read the unit ID to check for duplicate attach and the
312 	// global lock value to see if we should acquire it when
313 	// accessing the EC.
314 	status_t status = acpi_GetInteger(sc->ec_acpi, sc->ec_handle, "_UID",
315 		&sc->ec_uid);
316 	if (status != B_OK)
317 		sc->ec_uid = 0;
318 	status = acpi_GetInteger(sc->ec_acpi, sc->ec_handle, "_GLK", &sc->ec_glk);
319 	if (status != B_OK)
320 		sc->ec_glk = 0;
321 
322 	// Evaluate the _GPE method to find the GPE bit used by the EC to
323 	// signal status (SCI).  If it's a package, it contains a reference
324 	// and GPE bit, similar to _PRW.
325 	status = sc->ec_acpi->evaluate_method(sc->ec_handle, "_GPE", NULL, &buf);
326 	if (status != B_OK) {
327 		ERROR("can't evaluate _GPE\n");
328 		goto error;
329 	}
330 
331 	acpi_object_type* obj;
332 	obj = (acpi_object_type*)buf.pointer;
333 	if (obj == NULL)
334 		goto error;
335 
336 	switch (obj->object_type) {
337 		case ACPI_TYPE_INTEGER:
338 			sc->ec_gpehandle = NULL;
339 			sc->ec_gpebit = obj->integer.integer;
340 			break;
341 		case ACPI_TYPE_PACKAGE:
342 			if (!ACPI_PKG_VALID(obj, 2))
343 				goto error;
344 			sc->ec_gpehandle = acpi_GetReference(sc->ec_acpi_module, NULL,
345 				&obj->package.objects[0]);
346 			if (sc->ec_gpehandle == NULL
347 				|| acpi_PkgInt32(obj, 1, (uint32*)&sc->ec_gpebit) != B_OK)
348 				goto error;
349 			break;
350 		default:
351 			ERROR("_GPE has invalid type %i\n", int(obj->object_type));
352 			goto error;
353 	}
354 
355 	sc->ec_suspending = FALSE;
356 
357 	// Attach bus resources for data and command/status ports.
358 	status = sc->ec_acpi->walk_resources(sc->ec_handle, (ACPI_STRING)"_CRS",
359 		embedded_controller_io_ports_parse_callback, sc);
360 	if (status != B_OK) {
361 		ERROR("Error while getting IO ports addresses\n");
362 		goto error;
363 	}
364 
365 	// Install a handler for this EC's GPE bit.  We want edge-triggered
366 	// behavior.
367 	TRACE("attaching GPE handler\n");
368 	status = sc->ec_acpi_module->install_gpe_handler(sc->ec_gpehandle,
369 		sc->ec_gpebit, ACPI_GPE_EDGE_TRIGGERED, &EcGpeHandler, sc);
370 	if (status != B_OK) {
371 		TRACE("can't install ec GPE handler\n");
372 		goto error;
373 	}
374 
375 	// Install address space handler
376 	TRACE("attaching address space handler\n");
377 	status = sc->ec_acpi->install_address_space_handler(sc->ec_handle,
378 		ACPI_ADR_SPACE_EC, &EcSpaceHandler, &EcSpaceSetup, sc);
379 	if (status != B_OK) {
380 		ERROR("can't install address space handler\n");
381 		goto error;
382 	}
383 
384 	// Enable runtime GPEs for the handler.
385 	status = sc->ec_acpi_module->enable_gpe(sc->ec_gpehandle, sc->ec_gpebit);
386 	if (status != B_OK) {
387 		ERROR("AcpiEnableGpe failed.\n");
388 		goto error;
389 	}
390 
391 	return 0;
392 
393 error:
394 	free(buf.pointer);
395 
396 	sc->ec_acpi_module->remove_gpe_handler(sc->ec_gpehandle, sc->ec_gpebit,
397 		&EcGpeHandler);
398 	sc->ec_acpi->remove_address_space_handler(sc->ec_handle, ACPI_ADR_SPACE_EC,
399 		EcSpaceHandler);
400 
401 	return ENXIO;
402 }
403 
404 
405 static void
406 embedded_controller_uninit_driver(void* driverCookie)
407 {
408 	acpi_ec_cookie* sc = (struct acpi_ec_cookie*)driverCookie;
409 	mutex_destroy(&sc->ec_lock);
410 	free(sc);
411 	put_module(B_ACPI_MODULE_NAME);
412 }
413 
414 
415 static status_t
416 embedded_controller_register_child_devices(void* _cookie)
417 {
418 	device_node* node = ((acpi_ec_cookie*)_cookie)->ec_dev;
419 
420 	int pathID = gDeviceManager->create_id(ACPI_EC_PATHID_GENERATOR);
421 	if (pathID < 0) {
422 		TRACE("register_child_device couldn't create a path_id\n");
423 		return B_ERROR;
424 	}
425 
426 	char name[128];
427 	snprintf(name, sizeof(name), ACPI_EC_BASENAME, pathID);
428 
429 	return gDeviceManager->publish_device(node, name, ACPI_EC_DEVICE_NAME);
430 }
431 
432 
433 static status_t
434 embedded_controller_init_device(void* driverCookie, void** cookie)
435 {
436 	return B_ERROR;
437 }
438 
439 
440 static void
441 embedded_controller_uninit_device(void* _cookie)
442 {
443 	acpi_ec_cookie* device = (acpi_ec_cookie*)_cookie;
444 	free(device);
445 }
446 
447 
448 driver_module_info embedded_controller_driver_module = {
449 	{
450 		ACPI_EC_DRIVER_NAME,
451 		0,
452 		NULL
453 	},
454 
455 	embedded_controller_support,
456 	embedded_controller_register_device,
457 	embedded_controller_init_driver,
458 	embedded_controller_uninit_driver,
459 	embedded_controller_register_child_devices,
460 	NULL,	// rescan
461 	NULL,	// removed
462 };
463 
464 
465 struct device_module_info embedded_controller_device_module = {
466 	{
467 		ACPI_EC_DEVICE_NAME,
468 		0,
469 		NULL
470 	},
471 
472 	embedded_controller_init_device,
473 	embedded_controller_uninit_device,
474 	NULL,
475 
476 	embedded_controller_open,
477 	embedded_controller_close,
478 	embedded_controller_free,
479 	embedded_controller_read,
480 	embedded_controller_write,
481 	NULL,
482 	embedded_controller_control,
483 
484 	NULL,
485 	NULL
486 };
487 
488 
489 // #pragma mark -
490 
491 
492 static acpi_status
493 EcCheckStatus(struct acpi_ec_cookie* sc, const char* msg, EC_EVENT event)
494 {
495 	acpi_status status = AE_NO_HARDWARE_RESPONSE;
496 	EC_STATUS ec_status = EC_GET_CSR(sc);
497 
498 	if (sc->ec_burstactive && !(ec_status & EC_FLAG_BURST_MODE)) {
499 		TRACE("burst disabled in waitevent (%s)\n", msg);
500 		sc->ec_burstactive = false;
501 	}
502 	if (EVENT_READY(event, ec_status)) {
503 		TRACE("%s wait ready, status %#x\n", msg, ec_status);
504 		status = AE_OK;
505 	}
506 	return status;
507 }
508 
509 
510 static void
511 EcGpeQueryHandler(void* context)
512 {
513 	struct acpi_ec_cookie* sc = (struct acpi_ec_cookie*)context;
514 
515 	ASSERT(context != NULL);
516 
517 	// Serialize user access with EcSpaceHandler().
518 	status_t status = EcLock(sc);
519 	if (status != B_OK) {
520 		TRACE("GpeQuery lock error.\n");
521 		return;
522 	}
523 
524 	// Send a query command to the EC to find out which _Qxx call it
525 	// wants to make.  This command clears the SCI bit and also the
526 	// interrupt source since we are edge-triggered.  To prevent the GPE
527 	// that may arise from running the query from causing another query
528 	// to be queued, we clear the pending flag only after running it.
529 	int sci_enqueued = sc->ec_sci_pending;
530 	acpi_status acpi_status = AE_ERROR;
531 	for (uint8 retry = 0; retry < 2; retry++) {
532 		acpi_status = EcCommand(sc, EC_COMMAND_QUERY);
533 		if (acpi_status == AE_OK)
534 			break;
535 		if (EcCheckStatus(sc, "retr_check",
536 			EC_EVENT_INPUT_BUFFER_EMPTY) != AE_OK)
537 			break;
538 	}
539 
540 	sc->ec_sci_pending = FALSE;
541 	if (acpi_status != AE_OK) {
542 		EcUnlock(sc);
543 		TRACE("GPE query failed.\n");
544 		return;
545 	}
546 	uint8 data = EC_GET_DATA(sc);
547 
548 	// We have to unlock before running the _Qxx method below since that
549 	// method may attempt to read/write from EC address space, causing
550 	// recursive acquisition of the lock.
551 	EcUnlock(sc);
552 
553 	// Ignore the value for "no outstanding event". (13.3.5)
554 	TRACE("query ok,%s running _Q%02X\n", data ? "" : " not", data);
555 	if (data == 0)
556 		return;
557 
558 	// Evaluate _Qxx to respond to the controller.
559 	char qxx[5];
560 	snprintf(qxx, sizeof(qxx), "_Q%02X", data);
561 	AcpiUtStrupr(qxx);
562 	status = sc->ec_acpi->evaluate_method(sc->ec_handle, qxx, NULL, NULL);
563 	if (status != B_OK) {
564 		TRACE("evaluation of query method %s failed\n", qxx);
565 	}
566 
567     // Reenable runtime GPE if its execution was deferred.
568 	if (sci_enqueued) {
569 		status = sc->ec_acpi_module->finish_gpe(sc->ec_gpehandle, sc->ec_gpebit);
570 		if (status != B_OK)
571 			ERROR("reenabling runtime GPE failed.\n");
572 	}
573 
574 }
575 
576 
577 /*!	The GPE handler is called when IBE/OBF or SCI events occur.  We are
578 	called from an unknown lock context.
579 */
580 static uint32
581 EcGpeHandler(acpi_handle gpeDevice, uint32 gpeNumber, void* context)
582 {
583 	struct acpi_ec_cookie* sc = (acpi_ec_cookie*)context;
584 
585 	ASSERT(context != NULL);//, ("EcGpeHandler called with NULL"));
586 	TRACE("gpe handler start\n");
587 
588 	// Notify EcWaitEvent() that the status register is now fresh.  If we
589 	// didn't do this, it wouldn't be possible to distinguish an old IBE
590 	// from a new one, for example when doing a write transaction (writing
591 	// address and then data values.)
592 	atomic_add(&sc->ec_gencount, 1);
593 	sc->ec_condition_var.NotifyAll();
594 
595 	// If the EC_SCI bit of the status register is set, queue a query handler.
596 	// It will run the query and _Qxx method later, under the lock.
597 	EC_STATUS ecStatus = EC_GET_CSR(sc);
598 	if ((ecStatus & EC_EVENT_SCI) && !sc->ec_sci_pending) {
599 		TRACE("gpe queueing query handler\n");
600 		acpi_status status = AcpiOsExecute(OSL_GPE_HANDLER, EcGpeQueryHandler,
601 			context);
602 		if (status == AE_OK)
603 			sc->ec_sci_pending = TRUE;
604 		else
605 			dprintf("EcGpeHandler: queuing GPE query handler failed\n");
606 	}
607 	return ACPI_REENABLE_GPE;
608 }
609 
610 
611 static acpi_status
612 EcSpaceSetup(acpi_handle region, uint32 function, void* context,
613 	void** regionContext)
614 {
615 	// If deactivating a region, always set the output to NULL.  Otherwise,
616 	// just pass the context through.
617 	if (function == ACPI_REGION_DEACTIVATE)
618 		*regionContext = NULL;
619 	else
620 		*regionContext = context;
621 
622 	return AE_OK;
623 }
624 
625 
626 static acpi_status
627 EcSpaceHandler(uint32 function, acpi_physical_address address, uint32 width,
628 	int* value, void* context, void* regionContext)
629 {
630 	TRACE("enter EcSpaceHandler\n");
631 	struct acpi_ec_cookie* sc = (struct acpi_ec_cookie*)context;
632 
633 	if (function != ACPI_READ && function != ACPI_WRITE) return AE_BAD_PARAMETER;
634 	if (width % 8 != 0 || value == NULL || context == NULL)
635 		return AE_BAD_PARAMETER;
636 	if (address + width / 8 > 256)
637 		return AE_BAD_ADDRESS;
638 
639 	// If booting, check if we need to run the query handler.  If so, we
640 	// we call it directly here as scheduling and dpc might not be up yet.
641 	// (Not sure if it's needed)
642 
643 	if (gKernelStartup || gKernelShutdown || sc->ec_suspending) {
644 		if ((EC_GET_CSR(sc) & EC_EVENT_SCI)) {
645 			//CTR0(KTR_ACPI, "ec running gpe handler directly");
646 			EcGpeQueryHandler(sc);
647 		}
648 	}
649 
650 	// Serialize with EcGpeQueryHandler() at transaction granularity.
651 	acpi_status status = EcLock(sc);
652 	if (status != B_OK)
653 		return AE_NOT_ACQUIRED;
654 
655 	// If we can't start burst mode, continue anyway.
656 	status = EcCommand(sc, EC_COMMAND_BURST_ENABLE);
657 	if (status == B_OK) {
658 		if (EC_GET_DATA(sc) == EC_BURST_ACK) {
659 			TRACE("burst enabled.\n");
660 			sc->ec_burstactive = TRUE;
661 		}
662 	}
663 
664 	// Perform the transaction(s), based on width.
665 	acpi_physical_address ecAddr = address;
666 	uint8* ecData = (uint8 *) value;
667 	if (function == ACPI_READ)
668 		*value = 0;
669 	do {
670 		switch (function) {
671 			case ACPI_READ:
672 				status = EcRead(sc, ecAddr, ecData);
673 				break;
674 			case ACPI_WRITE:
675 				status = EcWrite(sc, ecAddr, *ecData);
676 				break;
677 		}
678 		if (status != AE_OK)
679 			break;
680 		ecAddr++;
681 		ecData++;
682 	} while (ecAddr < address + width / 8);
683 
684 	if (sc->ec_burstactive) {
685 		sc->ec_burstactive = FALSE;
686 		if (EcCommand(sc, EC_COMMAND_BURST_DISABLE) == AE_OK)
687 			TRACE("disabled burst ok.");
688 	}
689 
690 	EcUnlock(sc);
691 	return status;
692 }
693 
694 
695 static acpi_status
696 EcWaitEvent(struct acpi_ec_cookie* sc, EC_EVENT event, int32 generationCount)
697 {
698 	acpi_status status = AE_NO_HARDWARE_RESPONSE;
699 	int32 count, i;
700 
701 	// int need_poll = cold || rebooting || ec_polled_mode || sc->ec_suspending;
702 	int needPoll = ec_polled_mode || sc->ec_suspending || gKernelStartup || gKernelShutdown;
703 
704 	// Wait for event by polling or GPE (interrupt).
705 	// be "not ready" when we start waiting.  But if the main CPU is really
706 	// slow, it's possible we see the current "ready" response.  Since that
707 	// can't be distinguished from the previous response in polled mode,
708 	// this is a potential issue.  We really should have interrupts enabled
709 	// during boot so there is no ambiguity in polled mode.
710 	//
711 	// If this occurs, we add an additional delay before actually entering
712 	// the status checking loop, hopefully to allow the EC to go to work
713 	// and produce a non-stale status.
714 	if (needPoll) {
715 		static int once;
716 
717 		if (EcCheckStatus(sc, "pre-check", event) == B_OK) {
718 			if (!once) {
719 				TRACE("warning: EC done before starting event wait\n");
720 				once = 1;
721 			}
722 			spin(10);
723 		}
724 	}
725 
726 	// Wait for event by polling or GPE (interrupt).
727 	if (needPoll) {
728 		count = (ec_timeout * 1000) / EC_POLL_DELAY;
729 		if (count == 0)
730 			count = 1;
731 		for (i = 0; i < count; i++) {
732 			status = EcCheckStatus(sc, "poll", event);
733 			if (status == AE_OK)
734 				break;
735 			spin(EC_POLL_DELAY);
736 		}
737 	} else {
738 		bigtime_t sleepInterval = system_time() + ec_timeout * 1000;
739 
740 		// Wait for the GPE to signal the status changed, checking the
741 		// status register each time we get one.  It's possible to get a
742 		// GPE for an event we're not interested in here (i.e., SCI for
743 		// EC query).
744 		status_t waitStatus = B_NO_ERROR;
745 		while (waitStatus != B_TIMED_OUT) {
746 			if (generationCount != sc->ec_gencount) {
747 				// Record new generation count.  It's possible the GPE was
748 				// just to notify us that a query is needed and we need to
749 				// wait for a second GPE to signal the completion of the
750 				// event we are actually waiting for.
751 				generationCount = sc->ec_gencount;
752 				status = EcCheckStatus(sc, "sleep", event);
753 				if (status == AE_OK)
754 					break;
755 			}
756 			waitStatus = sc->ec_condition_var.Wait(B_ABSOLUTE_TIMEOUT,
757 				sleepInterval);
758 		}
759 
760 		// We finished waiting for the GPE and it never arrived.  Try to
761 		// read the register once and trust whatever value we got.  This is
762 		// the best we can do at this point.
763 		// since this system doesn't appear to generate GPEs.
764 		if (status != AE_OK) {
765 			status = EcCheckStatus(sc, "sleep_end", event);
766 			TRACE("wait timed out (%sresponse), forcing polled mode\n",
767 				status == AE_OK ? "" : "no ");
768 			ec_polled_mode = TRUE;
769 		}
770 	}
771 
772 
773 	if (status != AE_OK)
774 		TRACE("error: ec wait timed out\n");
775 
776 	return status;
777 }
778 
779 
780 static acpi_status
781 EcCommand(struct acpi_ec_cookie* sc, EC_COMMAND cmd)
782 {
783 	// Don't use burst mode if user disabled it.
784 	if (!ec_burst_mode && cmd == EC_COMMAND_BURST_ENABLE)
785 		return AE_ERROR;
786 
787 	// Decide what to wait for based on command type.
788 	EC_EVENT event;
789 	switch (cmd) {
790 		case EC_COMMAND_READ:
791 		case EC_COMMAND_WRITE:
792 		case EC_COMMAND_BURST_DISABLE:
793 			event = EC_EVENT_INPUT_BUFFER_EMPTY;
794 			break;
795 		case EC_COMMAND_QUERY:
796 		case EC_COMMAND_BURST_ENABLE:
797 			event = EC_EVENT_OUTPUT_BUFFER_FULL;
798 			break;
799 		default:
800 			TRACE("EcCommand: invalid command %#x\n", cmd);
801 			return AE_BAD_PARAMETER;
802 	}
803 
804 	// Ensure empty input buffer before issuing command.
805 	// Use generation count of zero to force a quick check.
806 	acpi_status status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY, 0);
807 	if (status != AE_OK)
808 		return status;
809 
810 	// Run the command and wait for the chosen event.
811 	TRACE("running command %#x\n", cmd);
812 	int32 generationCount = sc->ec_gencount;
813 	EC_SET_CSR(sc, cmd);
814 	status = EcWaitEvent(sc, event, generationCount);
815 	if (status == AE_OK) {
816 		// If we succeeded, burst flag should now be present.
817 		if (cmd == EC_COMMAND_BURST_ENABLE) {
818 			EC_STATUS ec_status = EC_GET_CSR(sc);
819 			if ((ec_status & EC_FLAG_BURST_MODE) == 0)
820 				status = AE_ERROR;
821 		}
822 	} else
823 		TRACE("EcCommand: no response to %#x\n", cmd);
824 
825 	return status;
826 }
827 
828 
829 static acpi_status
830 EcRead(struct acpi_ec_cookie* sc, uint8 address, uint8* readData)
831 {
832 	TRACE("read from %#x\n", address);
833 
834 	acpi_status status;
835 	for (uint8 retry = 0; retry < 2; retry++) {
836 		status = EcCommand(sc, EC_COMMAND_READ);
837 		if (status != AE_OK)
838 			return status;
839 
840 		int32 generationCount = sc->ec_gencount;
841 		EC_SET_DATA(sc, address);
842 		status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL, generationCount);
843 		if (status != AE_OK) {
844 			if (EcCheckStatus(sc, "retr_check",
845 				EC_EVENT_INPUT_BUFFER_EMPTY) == AE_OK)
846 				continue;
847 			else
848 				break;
849 		}
850 		*readData = EC_GET_DATA(sc);
851 		return AE_OK;
852 	}
853 
854 	TRACE("EcRead: failed waiting to get data\n");
855 	return status;
856 }
857 
858 
859 static acpi_status
860 EcWrite(struct acpi_ec_cookie* sc, uint8 address, uint8 writeData)
861 {
862 	acpi_status status = EcCommand(sc, EC_COMMAND_WRITE);
863 	if (status != AE_OK)
864 		return status;
865 
866 	int32 generationCount = sc->ec_gencount;
867 	EC_SET_DATA(sc, address);
868 	status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY, generationCount);
869 	if (status != AE_OK) {
870 		TRACE("EcWrite: failed waiting for sent address\n");
871 		return status;
872 	}
873 
874 	generationCount = sc->ec_gencount;
875 	EC_SET_DATA(sc, writeData);
876 	status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY, generationCount);
877 	if (status != AE_OK) {
878 		TRACE("EcWrite: failed waiting for sent data\n");
879 		return status;
880 	}
881 
882 	return AE_OK;
883 }
884