2 * Copyright (c) 2009 Clemens Zeidler
3 * Copyright (c) 2003-2007 Nate Lawson
4 * Copyright (c) 2000 Michael Smith
5 * Copyright (c) 2000 BSDi
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include "acpi_embedded_controller.h"
38 #include <condition_variable.h>
40 #include <KernelExport.h>
41 #include <drivers/PCI.h>
43 #include "SmallResourceData.h"
46 #define ACPI_EC_DRIVER_NAME "drivers/power/acpi_embedded_controller/driver_v1"
48 #define ACPI_EC_DEVICE_NAME "drivers/power/acpi_embedded_controller/device_v1"
50 /* Base Namespace devices are published to */
51 #define ACPI_EC_BASENAME "power/embedded_controller/%d"
53 // name of pnp generator of path ids
54 #define ACPI_EC_PATHID_GENERATOR "embedded_controller/path_id"
58 bus_space_read_1(int address
)
60 return gPCIManager
->read_io_8(address
);
65 bus_space_write_1(int address
, uint8 value
)
67 gPCIManager
->write_io_8(address
, value
);
72 acpi_GetInteger(acpi_device_module_info
* acpi
, acpi_device
& acpiCookie
,
73 const char* path
, int* number
)
76 acpi_object_type object
;
77 buf
.pointer
= &object
;
78 buf
.length
= sizeof(acpi_object_type
);
80 // Assume that what we've been pointed at is an Integer object, or
81 // a method that will return an Integer.
82 status_t status
= acpi
->evaluate_method(acpiCookie
, path
, NULL
, &buf
);
84 if (object
.object_type
== ACPI_TYPE_INTEGER
)
85 *number
= object
.data
.integer
;
94 acpi_GetReference(acpi_module_info
* acpi
, acpi_handle scope
,
95 acpi_object_type
* obj
)
100 switch (obj
->object_type
) {
101 case ACPI_TYPE_LOCAL_REFERENCE
:
103 return obj
->data
.reference
.handle
;
105 case ACPI_TYPE_STRING
:
107 // The String object usually contains a fully-qualified path, so
108 // scope can be NULL.
109 // TODO: This may not always be the case.
111 if (acpi
->get_handle(scope
, obj
->data
.string
.string
, &handle
)
122 acpi_PkgInt(acpi_object_type
* res
, int idx
, int* dst
)
124 acpi_object_type
* obj
= &res
->data
.package
.objects
[idx
];
125 if (obj
== NULL
|| obj
->object_type
!= ACPI_TYPE_INTEGER
)
127 *dst
= obj
->data
.integer
;
134 acpi_PkgInt32(acpi_object_type
* res
, int idx
, uint32
* dst
)
138 status_t status
= acpi_PkgInt(res
, idx
, &tmp
);
150 embedded_controller_open(void* initCookie
, const char* path
, int flags
,
153 acpi_ec_cookie
* device
= (acpi_ec_cookie
*) initCookie
;
161 embedded_controller_close(void* cookie
)
168 embedded_controller_read(void* _cookie
, off_t position
, void* buffer
,
176 embedded_controller_write(void* cookie
, off_t position
, const void* buffer
,
184 embedded_controller_control(void* _cookie
, uint32 op
, void* arg
, size_t len
)
191 embedded_controller_free(void* cookie
)
197 // #pragma mark - driver module API
201 acpi_get_type(device_node
* dev
)
204 if (gDeviceManager
->get_attr_string(dev
, B_DEVICE_BUS
, &bus
, false))
207 if (strcmp(bus
, "acpi"))
211 if (gDeviceManager
->get_attr_uint32(dev
, ACPI_DEVICE_TYPE_ITEM
,
212 &deviceType
, false) != B_OK
)
220 embedded_controller_support(device_node
* dev
)
222 TRACE("embedded_controller_support()\n");
224 // Check that this is a device
225 if (acpi_get_type(dev
) != ACPI_TYPE_DEVICE
)
229 if (gDeviceManager
->get_attr_string(dev
, ACPI_DEVICE_HID_ITEM
, &name
, false)
233 // Test all known IDs
235 static const char* kEmbeddedControllerIDs
[] = { "PNP0C09" };
237 for (size_t i
= 0; i
< sizeof(kEmbeddedControllerIDs
)
238 / sizeof(kEmbeddedControllerIDs
[0]); i
++) {
239 if (!strcmp(name
, kEmbeddedControllerIDs
[i
])) {
240 TRACE("supported device found %s\n", name
);
250 embedded_controller_register_device(device_node
* node
)
252 device_attr attrs
[] = {
253 { B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
,
254 { string
: "ACPI embedded controller" }},
258 return gDeviceManager
->register_node(node
, ACPI_EC_DRIVER_NAME
, attrs
,
264 embedded_controller_init_driver(device_node
* dev
, void** _driverCookie
)
266 TRACE("init driver\n");
269 sc
= (acpi_ec_cookie
*)malloc(sizeof(acpi_ec_cookie
));
273 memset(sc
, 0, sizeof(acpi_ec_cookie
));
278 sc
->ec_condition_var
.Init(NULL
, "ec condition variable");
279 mutex_init(&sc
->ec_lock
, "ec lock");
280 device_node
* parent
= gDeviceManager
->get_parent_node(dev
);
281 gDeviceManager
->get_driver(parent
, (driver_module_info
**)&sc
->ec_acpi
,
282 (void**)&sc
->ec_handle
);
283 gDeviceManager
->put_node(parent
);
285 SmallResourceData
resourceData(sc
->ec_acpi
, sc
->ec_handle
, "_CRS");
286 if (resourceData
.InitCheck() != B_OK
) {
287 TRACE("failed to read _CRS resource\n") ;
292 if (get_module(B_ACPI_MODULE_NAME
, (module_info
**)&sc
->ec_acpi_module
)
298 buf
.length
= ACPI_ALLOCATE_BUFFER
;
300 // Read the unit ID to check for duplicate attach and the
301 // global lock value to see if we should acquire it when
303 status_t status
= acpi_GetInteger(sc
->ec_acpi
, sc
->ec_handle
, "_UID",
307 status
= acpi_GetInteger(sc
->ec_acpi
, sc
->ec_handle
, "_GLK", &sc
->ec_glk
);
311 // Evaluate the _GPE method to find the GPE bit used by the EC to
312 // signal status (SCI). If it's a package, it contains a reference
313 // and GPE bit, similar to _PRW.
314 status
= sc
->ec_acpi
->evaluate_method(sc
->ec_handle
, "_GPE", NULL
, &buf
);
315 if (status
!= B_OK
) {
316 TRACE("can't evaluate _GPE\n");
320 acpi_object_type
* obj
;
321 obj
= (acpi_object_type
*)buf
.pointer
;
325 switch (obj
->object_type
) {
326 case ACPI_TYPE_INTEGER
:
327 sc
->ec_gpehandle
= NULL
;
328 sc
->ec_gpebit
= obj
->data
.integer
;
330 case ACPI_TYPE_PACKAGE
:
331 if (!ACPI_PKG_VALID(obj
, 2))
333 sc
->ec_gpehandle
= acpi_GetReference(sc
->ec_acpi_module
, NULL
,
334 &obj
->data
.package
.objects
[0]);
335 if (sc
->ec_gpehandle
== NULL
336 || acpi_PkgInt32(obj
, 1, (uint32
*)&sc
->ec_gpebit
) != B_OK
)
340 TRACE("_GPE has invalid type %i\n", int(obj
->object_type
));
344 sc
->ec_suspending
= FALSE
;
346 // Attach bus resources for data and command/status ports.
347 if (resourceData
.ReadIOPort(&portData
) != B_OK
)
350 sc
->ec_data_pci_address
= portData
.minimumBase
;
352 if (resourceData
.ReadIOPort(&portData
) != B_OK
)
355 sc
->ec_csr_pci_address
= portData
.minimumBase
;
357 // Install a handler for this EC's GPE bit. We want edge-triggered
359 TRACE("attaching GPE handler\n");
360 status
= sc
->ec_acpi_module
->install_gpe_handler(sc
->ec_gpehandle
,
361 sc
->ec_gpebit
, ACPI_GPE_EDGE_TRIGGERED
, &EcGpeHandler
, sc
);
362 if (status
!= B_OK
) {
363 TRACE("can't install ec GPE handler\n");
367 // Install address space handler
368 TRACE("attaching address space handler\n");
369 status
= sc
->ec_acpi
->install_address_space_handler(sc
->ec_handle
,
370 ACPI_ADR_SPACE_EC
, &EcSpaceHandler
, &EcSpaceSetup
, sc
);
371 if (status
!= B_OK
) {
372 TRACE("can't install address space handler\n");
376 // Enable runtime GPEs for the handler.
377 status
= sc
->ec_acpi_module
->enable_gpe(sc
->ec_gpehandle
, sc
->ec_gpebit
);
378 if (status
!= B_OK
) {
379 TRACE("AcpiEnableGpe failed.\n");
388 sc
->ec_acpi_module
->remove_gpe_handler(sc
->ec_gpehandle
, sc
->ec_gpebit
,
390 sc
->ec_acpi
->remove_address_space_handler(sc
->ec_handle
, ACPI_ADR_SPACE_EC
,
398 embedded_controller_uninit_driver(void* driverCookie
)
400 acpi_ec_cookie
* sc
= (struct acpi_ec_cookie
*)driverCookie
;
401 mutex_destroy(&sc
->ec_lock
);
403 put_module(B_ACPI_MODULE_NAME
);
408 embedded_controller_register_child_devices(void* _cookie
)
410 device_node
* node
= ((acpi_ec_cookie
*)_cookie
)->ec_dev
;
412 int pathID
= gDeviceManager
->create_id(ACPI_EC_PATHID_GENERATOR
);
414 TRACE("register_child_device couldn't create a path_id\n");
419 snprintf(name
, sizeof(name
), ACPI_EC_BASENAME
, pathID
);
421 return gDeviceManager
->publish_device(node
, name
, ACPI_EC_DEVICE_NAME
);
426 embedded_controller_init_device(void* driverCookie
, void** cookie
)
433 embedded_controller_uninit_device(void* _cookie
)
435 acpi_ec_cookie
* device
= (acpi_ec_cookie
*)_cookie
;
440 driver_module_info embedded_controller_driver_module
= {
447 embedded_controller_support
,
448 embedded_controller_register_device
,
449 embedded_controller_init_driver
,
450 embedded_controller_uninit_driver
,
451 embedded_controller_register_child_devices
,
457 struct device_module_info embedded_controller_device_module
= {
464 embedded_controller_init_device
,
465 embedded_controller_uninit_device
,
468 embedded_controller_open
,
469 embedded_controller_close
,
470 embedded_controller_free
,
471 embedded_controller_read
,
472 embedded_controller_write
,
474 embedded_controller_control
,
485 EcCheckStatus(struct acpi_ec_cookie
* sc
, const char* msg
, EC_EVENT event
)
487 acpi_status status
= AE_NO_HARDWARE_RESPONSE
;
488 EC_STATUS ec_status
= EC_GET_CSR(sc
);
490 if (sc
->ec_burstactive
&& !(ec_status
& EC_FLAG_BURST_MODE
)) {
491 TRACE("burst disabled in waitevent (%s)\n", msg
);
492 sc
->ec_burstactive
= false;
494 if (EVENT_READY(event
, ec_status
)) {
495 TRACE("%s wait ready, status %#x\n", msg
, ec_status
);
503 EcGpeQueryHandler(void* context
)
505 struct acpi_ec_cookie
* sc
= (struct acpi_ec_cookie
*)context
;
507 ASSERT(context
!= NULL
);
509 // Serialize user access with EcSpaceHandler().
510 status_t status
= EcLock(sc
);
511 if (status
!= B_OK
) {
512 TRACE("GpeQuery lock error.\n");
516 // Send a query command to the EC to find out which _Qxx call it
517 // wants to make. This command clears the SCI bit and also the
518 // interrupt source since we are edge-triggered. To prevent the GPE
519 // that may arise from running the query from causing another query
520 // to be queued, we clear the pending flag only after running it.
521 int sci_enqueued
= sc
->ec_sci_pending
;
522 acpi_status acpi_status
;
523 for (uint8 retry
= 0; retry
< 2; retry
++) {
524 acpi_status
= EcCommand(sc
, EC_COMMAND_QUERY
);
525 if (acpi_status
== AE_OK
)
527 if (EcCheckStatus(sc
, "retr_check",
528 EC_EVENT_INPUT_BUFFER_EMPTY
) != AE_OK
)
532 sc
->ec_sci_pending
= FALSE
;
533 if (acpi_status
!= AE_OK
) {
535 TRACE("GPE query failed.\n");
538 uint8 data
= EC_GET_DATA(sc
);
540 // We have to unlock before running the _Qxx method below since that
541 // method may attempt to read/write from EC address space, causing
542 // recursive acquisition of the lock.
545 // Ignore the value for "no outstanding event". (13.3.5)
546 TRACE("query ok,%s running _Q%02X\n", data
? "" : " not", data
);
550 // Evaluate _Qxx to respond to the controller.
552 snprintf(qxx
, sizeof(qxx
), "_Q%02X", data
);
554 status
= sc
->ec_acpi
->evaluate_method(sc
->ec_handle
, qxx
, NULL
, NULL
);
555 if (status
!= B_OK
) {
556 TRACE("evaluation of query method %s failed\n", qxx
);
559 // Reenable runtime GPE if its execution was deferred.
561 status
= sc
->ec_acpi_module
->finish_gpe(sc
->ec_gpehandle
, sc
->ec_gpebit
);
563 ERROR("reenabling runtime GPE failed.\n");
569 /*! The GPE handler is called when IBE/OBF or SCI events occur. We are
570 called from an unknown lock context.
573 EcGpeHandler(acpi_handle gpeDevice
, uint32 gpeNumber
, void* context
)
575 struct acpi_ec_cookie
* sc
= (acpi_ec_cookie
*)context
;
577 ASSERT(context
!= NULL
);//, ("EcGpeHandler called with NULL"));
578 TRACE("gpe handler start\n");
580 // Notify EcWaitEvent() that the status register is now fresh. If we
581 // didn't do this, it wouldn't be possible to distinguish an old IBE
582 // from a new one, for example when doing a write transaction (writing
583 // address and then data values.)
584 atomic_add(&sc
->ec_gencount
, 1);
585 sc
->ec_condition_var
.NotifyAll();
587 // If the EC_SCI bit of the status register is set, queue a query handler.
588 // It will run the query and _Qxx method later, under the lock.
589 EC_STATUS ecStatus
= EC_GET_CSR(sc
);
590 if ((ecStatus
& EC_EVENT_SCI
) && !sc
->ec_sci_pending
) {
591 TRACE("gpe queueing query handler\n");
592 acpi_status status
= AcpiOsExecute(OSL_GPE_HANDLER
, EcGpeQueryHandler
,
595 sc
->ec_sci_pending
= TRUE
;
597 dprintf("EcGpeHandler: queuing GPE query handler failed\n");
599 return B_INVOKE_SCHEDULER
;
604 EcSpaceSetup(acpi_handle region
, uint32 function
, void* context
,
605 void** regionContext
)
607 // If deactivating a region, always set the output to NULL. Otherwise,
608 // just pass the context through.
609 if (function
== ACPI_REGION_DEACTIVATE
)
610 *regionContext
= NULL
;
612 *regionContext
= context
;
619 EcSpaceHandler(uint32 function
, acpi_physical_address address
, uint32 width
,
620 int* value
, void* context
, void* regionContext
)
622 TRACE("enter EcSpaceHandler\n");
623 struct acpi_ec_cookie
* sc
= (struct acpi_ec_cookie
*)context
;
625 if (function
!= ACPI_READ
&& function
!= ACPI_WRITE
) return AE_BAD_PARAMETER
;
626 if (width
% 8 != 0 || value
== NULL
|| context
== NULL
)
627 return AE_BAD_PARAMETER
;
628 if (address
+ width
/ 8 > 256)
629 return AE_BAD_ADDRESS
;
631 // If booting, check if we need to run the query handler. If so, we
632 // we call it directly here as scheduling and dpc might not be up yet.
633 // (Not sure if it's needed)
635 if (gKernelStartup
|| gKernelShutdown
|| sc
->ec_suspending
) {
636 if ((EC_GET_CSR(sc
) & EC_EVENT_SCI
)) {
637 //CTR0(KTR_ACPI, "ec running gpe handler directly");
638 EcGpeQueryHandler(sc
);
642 // Serialize with EcGpeQueryHandler() at transaction granularity.
643 acpi_status status
= EcLock(sc
);
645 return AE_NOT_ACQUIRED
;
647 // If we can't start burst mode, continue anyway.
648 status
= EcCommand(sc
, EC_COMMAND_BURST_ENABLE
);
649 if (status
== B_OK
) {
650 if (EC_GET_DATA(sc
) == EC_BURST_ACK
) {
651 TRACE("burst enabled.\n");
652 sc
->ec_burstactive
= TRUE
;
656 // Perform the transaction(s), based on width.
657 acpi_physical_address ecAddr
= address
;
658 uint8
* ecData
= (uint8
*) value
;
659 if (function
== ACPI_READ
)
664 status
= EcRead(sc
, ecAddr
, ecData
);
667 status
= EcWrite(sc
, ecAddr
, *ecData
);
674 } while (ecAddr
< address
+ width
/ 8);
676 if (sc
->ec_burstactive
) {
677 sc
->ec_burstactive
= FALSE
;
678 if (EcCommand(sc
, EC_COMMAND_BURST_DISABLE
) == AE_OK
)
679 TRACE("disabled burst ok.");
688 EcWaitEvent(struct acpi_ec_cookie
* sc
, EC_EVENT event
, int32 generationCount
)
690 acpi_status status
= AE_NO_HARDWARE_RESPONSE
;
693 // int need_poll = cold || rebooting || ec_polled_mode || sc->ec_suspending;
694 int needPoll
= ec_polled_mode
|| sc
->ec_suspending
|| gKernelStartup
|| gKernelShutdown
;
696 // Wait for event by polling or GPE (interrupt).
697 // be "not ready" when we start waiting. But if the main CPU is really
698 // slow, it's possible we see the current "ready" response. Since that
699 // can't be distinguished from the previous response in polled mode,
700 // this is a potential issue. We really should have interrupts enabled
701 // during boot so there is no ambiguity in polled mode.
703 // If this occurs, we add an additional delay before actually entering
704 // the status checking loop, hopefully to allow the EC to go to work
705 // and produce a non-stale status.
709 if (EcCheckStatus(sc
, "pre-check", event
) == B_OK
) {
711 TRACE("warning: EC done before starting event wait\n");
718 // Wait for event by polling or GPE (interrupt).
720 count
= (ec_timeout
* 1000) / EC_POLL_DELAY
;
723 for (i
= 0; i
< count
; i
++) {
724 status
= EcCheckStatus(sc
, "poll", event
);
730 bigtime_t sleepInterval
= system_time() + ec_timeout
* 1000;
732 // Wait for the GPE to signal the status changed, checking the
733 // status register each time we get one. It's possible to get a
734 // GPE for an event we're not interested in here (i.e., SCI for
736 status_t waitStatus
= B_NO_ERROR
;
737 while (waitStatus
!= B_TIMED_OUT
) {
738 if (generationCount
!= sc
->ec_gencount
) {
739 // Record new generation count. It's possible the GPE was
740 // just to notify us that a query is needed and we need to
741 // wait for a second GPE to signal the completion of the
742 // event we are actually waiting for.
743 generationCount
= sc
->ec_gencount
;
744 status
= EcCheckStatus(sc
, "sleep", event
);
748 waitStatus
= sc
->ec_condition_var
.Wait(B_ABSOLUTE_TIMEOUT
,
752 // We finished waiting for the GPE and it never arrived. Try to
753 // read the register once and trust whatever value we got. This is
754 // the best we can do at this point.
755 // since this system doesn't appear to generate GPEs.
756 if (status
!= AE_OK
) {
757 status
= EcCheckStatus(sc
, "sleep_end", event
);
758 TRACE("wait timed out (%sresponse), forcing polled mode\n",
759 status
== AE_OK
? "" : "no ");
760 ec_polled_mode
= TRUE
;
766 TRACE("error: ec wait timed out\n");
773 EcCommand(struct acpi_ec_cookie
* sc
, EC_COMMAND cmd
)
775 // Don't use burst mode if user disabled it.
776 if (!ec_burst_mode
&& cmd
== EC_COMMAND_BURST_ENABLE
)
779 // Decide what to wait for based on command type.
782 case EC_COMMAND_READ
:
783 case EC_COMMAND_WRITE
:
784 case EC_COMMAND_BURST_DISABLE
:
785 event
= EC_EVENT_INPUT_BUFFER_EMPTY
;
787 case EC_COMMAND_QUERY
:
788 case EC_COMMAND_BURST_ENABLE
:
789 event
= EC_EVENT_OUTPUT_BUFFER_FULL
;
792 TRACE("EcCommand: invalid command %#x\n", cmd
);
793 return AE_BAD_PARAMETER
;
796 // Ensure empty input buffer before issuing command.
797 // Use generation count of zero to force a quick check.
798 acpi_status status
= EcWaitEvent(sc
, EC_EVENT_INPUT_BUFFER_EMPTY
, 0);
802 // Run the command and wait for the chosen event.
803 TRACE("running command %#x\n", cmd
);
804 int32 generationCount
= sc
->ec_gencount
;
806 status
= EcWaitEvent(sc
, event
, generationCount
);
807 if (status
== AE_OK
) {
808 // If we succeeded, burst flag should now be present.
809 if (cmd
== EC_COMMAND_BURST_ENABLE
) {
810 EC_STATUS ec_status
= EC_GET_CSR(sc
);
811 if ((ec_status
& EC_FLAG_BURST_MODE
) == 0)
815 TRACE("EcCommand: no response to %#x\n", cmd
);
822 EcRead(struct acpi_ec_cookie
* sc
, uint8 address
, uint8
* readData
)
824 TRACE("read from %#x\n", address
);
827 for (uint8 retry
= 0; retry
< 2; retry
++) {
828 status
= EcCommand(sc
, EC_COMMAND_READ
);
832 int32 generationCount
= sc
->ec_gencount
;
833 EC_SET_DATA(sc
, address
);
834 status
= EcWaitEvent(sc
, EC_EVENT_OUTPUT_BUFFER_FULL
, generationCount
);
835 if (status
!= AE_OK
) {
836 if (EcCheckStatus(sc
, "retr_check",
837 EC_EVENT_INPUT_BUFFER_EMPTY
) == AE_OK
)
842 *readData
= EC_GET_DATA(sc
);
846 TRACE("EcRead: failed waiting to get data\n");
852 EcWrite(struct acpi_ec_cookie
* sc
, uint8 address
, uint8 writeData
)
854 acpi_status status
= EcCommand(sc
, EC_COMMAND_WRITE
);
858 int32 generationCount
= sc
->ec_gencount
;
859 EC_SET_DATA(sc
, address
);
860 status
= EcWaitEvent(sc
, EC_EVENT_INPUT_BUFFER_EMPTY
, generationCount
);
861 if (status
!= AE_OK
) {
862 TRACE("EcWrite: failed waiting for sent address\n");
866 generationCount
= sc
->ec_gencount
;
867 EC_SET_DATA(sc
, writeData
);
868 status
= EcWaitEvent(sc
, EC_EVENT_INPUT_BUFFER_EMPTY
, generationCount
);
869 if (status
!= AE_OK
) {
870 TRACE("EcWrite: failed waiting for sent data\n");