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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright 2011 Joyent, Inc.  All rights reserved.
  25  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  26  */
  27 /*
  28  * Solaris x86 ACPI CA Embedded Controller operation region handler
  29  */
  30 
  31 #include <sys/file.h>
  32 #include <sys/errno.h>
  33 #include <sys/conf.h>
  34 #include <sys/modctl.h>
  35 #include <sys/open.h>
  36 #include <sys/stat.h>
  37 #include <sys/ddi.h>
  38 #include <sys/sunddi.h>
  39 #include <sys/note.h>
  40 #include <sys/atomic.h>
  41 
  42 #include <sys/acpi/acpi.h>
  43 #include <sys/acpica.h>
  44 
  45 /*
  46  * EC status bits
  47  * Low to high
  48  *      Output buffer full?
  49  *      Input buffer full?
  50  *      <reserved>
  51  *      Data register is command byte?
  52  *      Burst mode enabled?
  53  *      SCI event?
  54  *      SMI event?
  55  *      <reserved>
  56  */
  57 #define EC_OBF  (0x01)
  58 #define EC_IBF  (0x02)
  59 #define EC_DRC  (0x08)
  60 #define EC_BME  (0x10)
  61 #define EC_SCI  (0x20)
  62 #define EC_SMI  (0x40)
  63 
  64 /*
  65  * EC commands
  66  */
  67 #define EC_RD   (0x80)
  68 #define EC_WR   (0x81)
  69 #define EC_BE   (0x82)
  70 #define EC_BD   (0x83)
  71 #define EC_QR   (0x84)
  72 
  73 #define IO_PORT_DES (0x47)
  74 
  75 /*
  76  * EC softstate
  77  */
  78 static struct ec_softstate {
  79         uint8_t  ec_ok;         /* != 0 if we have ec_base, ec_sc */
  80         uint16_t ec_base;       /* base of EC I/O port - data */
  81         uint16_t ec_sc;         /* EC status/command */
  82         ACPI_HANDLE ec_dev_hdl; /* EC device handle */
  83         ACPI_HANDLE ec_gpe_hdl; /* GPE info */
  84         ACPI_INTEGER ec_gpe_bit;
  85         kmutex_t    ec_mutex;   /* serialize access to EC */
  86 } ec;
  87 
  88 /* I/O port range descriptor */
  89 typedef struct io_port_des {
  90         uint8_t type;
  91         uint8_t decode;
  92         uint8_t min_base_lo;
  93         uint8_t min_base_hi;
  94         uint8_t max_base_lo;
  95         uint8_t max_base_hi;
  96         uint8_t align;
  97         uint8_t len;
  98 } io_port_des_t;
  99 
 100 /*
 101  * Patchable to ignore an ECDT, in case using that
 102  * causes problems on someone's system.
 103  */
 104 int ec_ignore_ecdt = 0;
 105 
 106 /*
 107  * Patchable timeout values for EC input-buffer-full-clear
 108  * and output-buffer-full-set. These are in 10uS units and
 109  * default to 1 second.
 110  */
 111 int ibf_clear_timeout = 100000;
 112 int obf_set_timeout = 100000;
 113 
 114 /*
 115  * ACPI CA EC address space handler support functions
 116  */
 117 
 118 /*
 119  * Busy-wait for IBF to clear
 120  * return < 0 for time out, 0 for no error
 121  */
 122 static int
 123 ec_wait_ibf_clear(int sc_addr)
 124 {
 125         int     cnt;
 126 
 127         cnt = ibf_clear_timeout;
 128         while (inb(sc_addr) & EC_IBF) {
 129                 if (cnt-- <= 0)
 130                         return (-1);
 131                 drv_usecwait(10);
 132         }
 133         return (0);
 134 }
 135 
 136 /*
 137  * Busy-wait for OBF to set
 138  * return < 0 for time out, 0 for no error
 139  */
 140 static int
 141 ec_wait_obf_set(int sc_addr)
 142 {
 143         int     cnt;
 144 
 145         cnt = obf_set_timeout;
 146         while (!(inb(sc_addr) & EC_OBF)) {
 147                 if (cnt-- <= 0)
 148                         return (-1);
 149                 drv_usecwait(10);
 150         }
 151         return (0);
 152 }
 153 
 154 /*
 155  * Only called from ec_handler(), which validates ec_ok
 156  */
 157 static int
 158 ec_rd(int addr)
 159 {
 160         int     cnt, rv;
 161         uint8_t sc;
 162 
 163         mutex_enter(&ec.ec_mutex);
 164         sc = inb(ec.ec_sc);
 165 
 166 #ifdef  DEBUG
 167         if (sc & EC_IBF) {
 168                 cmn_err(CE_NOTE, "!ec_rd: IBF already set");
 169         }
 170 
 171         if (sc & EC_OBF) {
 172                 cmn_err(CE_NOTE, "!ec_rd: OBF already set");
 173         }
 174 #endif
 175 
 176         outb(ec.ec_sc, EC_RD);  /* output a read command */
 177         if (ec_wait_ibf_clear(ec.ec_sc) < 0) {
 178                 cmn_err(CE_NOTE, "!ec_rd:1: timed-out waiting "
 179                     "for IBF to clear");
 180                 mutex_exit(&ec.ec_mutex);
 181                 return (-1);
 182         }
 183 
 184         outb(ec.ec_base, addr); /* output addr */
 185         if (ec_wait_ibf_clear(ec.ec_sc) < 0) {
 186                 cmn_err(CE_NOTE, "!ec_rd:2: timed-out waiting "
 187                     "for IBF to clear");
 188                 mutex_exit(&ec.ec_mutex);
 189                 return (-1);
 190         }
 191         if (ec_wait_obf_set(ec.ec_sc) < 0) {
 192                 cmn_err(CE_NOTE, "!ec_rd:1: timed-out waiting "
 193                     "for OBF to set");
 194                 mutex_exit(&ec.ec_mutex);
 195                 return (-1);
 196         }
 197 
 198         rv = inb(ec.ec_base);
 199         mutex_exit(&ec.ec_mutex);
 200         return (rv);
 201 }
 202 
 203 /*
 204  * Only called from ec_handler(), which validates ec_ok
 205  */
 206 static int
 207 ec_wr(int addr, uint8_t val)
 208 {
 209         int     cnt;
 210         uint8_t sc;
 211 
 212         mutex_enter(&ec.ec_mutex);
 213         sc = inb(ec.ec_sc);
 214 
 215 #ifdef  DEBUG
 216         if (sc & EC_IBF) {
 217                 cmn_err(CE_NOTE, "!ec_wr: IBF already set");
 218         }
 219 
 220         if (sc & EC_OBF) {
 221                 cmn_err(CE_NOTE, "!ec_wr: OBF already set");
 222         }
 223 #endif
 224 
 225         outb(ec.ec_sc, EC_WR);  /* output a write command */
 226         if (ec_wait_ibf_clear(ec.ec_sc) < 0) {
 227                 cmn_err(CE_NOTE, "!ec_wr:1: timed-out waiting "
 228                     "for IBF to clear");
 229                 mutex_exit(&ec.ec_mutex);
 230                 return (-1);
 231         }
 232 
 233         outb(ec.ec_base, addr); /* output addr */
 234         if (ec_wait_ibf_clear(ec.ec_sc) < 0) {
 235                 cmn_err(CE_NOTE, "!ec_wr:2: timed-out waiting "
 236                     "for IBF to clear");
 237                 mutex_exit(&ec.ec_mutex);
 238                 return (-1);
 239         }
 240 
 241         outb(ec.ec_base, val);  /* write data */
 242         if (ec_wait_ibf_clear(ec.ec_sc) < 0) {
 243                 cmn_err(CE_NOTE, "!ec_wr:3: timed-out waiting "
 244                     "for IBF to clear");
 245                 mutex_exit(&ec.ec_mutex);
 246                 return (-1);
 247         }
 248 
 249         mutex_exit(&ec.ec_mutex);
 250         return (0);
 251 }
 252 
 253 /*
 254  * Only called from ec_gpe_callback(), which validates ec_ok
 255  */
 256 static int
 257 ec_query(void)
 258 {
 259         int     cnt, rv;
 260         uint8_t sc;
 261 
 262         mutex_enter(&ec.ec_mutex);
 263         outb(ec.ec_sc, EC_QR);  /* output a query command */
 264         if (ec_wait_ibf_clear(ec.ec_sc) < 0) {
 265                 cmn_err(CE_NOTE, "!ec_query:1: timed-out waiting "
 266                     "for IBF to clear");
 267                 mutex_exit(&ec.ec_mutex);
 268                 return (-1);
 269         }
 270 
 271         if (ec_wait_obf_set(ec.ec_sc) < 0) {
 272                 cmn_err(CE_NOTE, "!ec_query:1: timed-out waiting "
 273                     "for OBF to set");
 274                 mutex_exit(&ec.ec_mutex);
 275                 return (-1);
 276         }
 277 
 278         rv = inb(ec.ec_base);
 279         mutex_exit(&ec.ec_mutex);
 280         return (rv);
 281 }
 282 
 283 /*
 284  * ACPI CA EC address space handler
 285  * Requires: ec.ec_sc, ec.ec_base
 286  */
 287 static ACPI_STATUS
 288 ec_handler(UINT32 func, ACPI_PHYSICAL_ADDRESS addr, UINT32 width,
 289         UINT64 *val, void *context, void *regcontext)
 290 {
 291         _NOTE(ARGUNUSED(context, regcontext))
 292         int i, tw, tmp;
 293 
 294         /* Guard against unexpected invocation */
 295         if (ec.ec_ok == 0)
 296                 return (AE_ERROR);
 297 
 298         /*
 299          * Add safety checks for BIOSes not strictly compliant
 300          * with ACPI spec
 301          */
 302         if ((width % 8) != 0) {
 303                 cmn_err(CE_NOTE, "!ec_handler: invalid width %d", width);
 304                 return (AE_BAD_PARAMETER);
 305         }
 306         if (val == NULL) {
 307                 cmn_err(CE_NOTE, "!ec_handler: NULL value pointer");
 308                 return (AE_BAD_PARAMETER);
 309         }
 310 
 311         while (width > 0) {
 312 
 313                 /* One UINT64 *val at a time. */
 314                 tw = min(width, 64);
 315 
 316                 if (func == ACPI_READ)
 317                         *val = 0;
 318 
 319                 /* Do I/O of up to 64 bits */
 320                 for (i = 0; i < tw; i += 8, addr++) {
 321                         switch (func) {
 322                         case ACPI_READ:
 323                                 tmp = ec_rd(addr);
 324                                 if (tmp < 0)
 325                                         return (AE_ERROR);
 326                                 *val |= ((UINT64)tmp) << i;
 327                                 break;
 328                         case ACPI_WRITE:
 329                                 tmp = ((*val) >> i) & 0xFF;
 330                                 if (ec_wr(addr, (uint8_t)tmp) < 0)
 331                                         return (AE_ERROR);
 332                                 break;
 333                         default:
 334                                 return (AE_ERROR);
 335                         }
 336                 }
 337                 val++;
 338                 width -= tw;
 339         }
 340 
 341         return (AE_OK);
 342 }
 343 
 344 /*
 345  * Called via taskq entry enqueued by ec_gpe_handler,
 346  * which validates ec_ok
 347  */
 348 static void
 349 ec_gpe_callback(void *ctx)
 350 {
 351         _NOTE(ARGUNUSED(ctx))
 352         char            query_str[5];
 353         int             query;
 354 
 355         if (!(inb(ec.ec_sc) & EC_SCI))
 356                 goto out;
 357 
 358         query = ec_query();
 359         if (query < 0)
 360                 goto out;
 361 
 362         (void) snprintf(query_str, 5, "_Q%02X", (uint8_t)query);
 363         (void) AcpiEvaluateObject(ec.ec_dev_hdl, query_str, NULL, NULL);
 364 
 365 out:
 366         AcpiFinishGpe(ec.ec_gpe_hdl, ec.ec_gpe_bit);
 367 }
 368 
 369 static UINT32
 370 ec_gpe_handler(ACPI_HANDLE GpeDevice, UINT32 GpeNumber, void *ctx)
 371 {
 372         _NOTE(ARGUNUSED(GpeDevice))
 373         _NOTE(ARGUNUSED(GpeNumber))
 374         _NOTE(ARGUNUSED(ctx))
 375 
 376         /*
 377          * With ec_ok==0, we will not install a GPE handler,
 378          * so this is just paranoia.  But if this were to
 379          * happen somehow, don't add the taskq entry, and
 380          * tell the caller we're done with this GPE call.
 381          */
 382         if (ec.ec_ok == 0)
 383                 return (ACPI_REENABLE_GPE);
 384 
 385         AcpiOsExecute(OSL_GPE_HANDLER, ec_gpe_callback, NULL);
 386 
 387         /*
 388          * Returning zero tells the ACPI system that we will
 389          * handle this event asynchronously.
 390          */
 391         return (0);
 392 }
 393 
 394 /*
 395  * Some systems describe the EC using an "ECDT" (table).
 396  * If we find one use it (unless ec_ignore_ecdt is set).
 397  * Modern systems don't provide an ECDT.
 398  */
 399 static ACPI_STATUS
 400 ec_probe_ecdt(void)
 401 {
 402         ACPI_TABLE_HEADER *th;
 403         ACPI_TABLE_ECDT *ecdt;
 404         ACPI_HANDLE     dev_hdl;
 405         ACPI_STATUS     status;
 406 
 407         status = AcpiGetTable(ACPI_SIG_ECDT, 1, &th);
 408 #ifndef DEBUG
 409         if (status == AE_NOT_FOUND)
 410                 return (status);
 411 #endif
 412         if (ACPI_FAILURE(status)) {
 413                 cmn_err(CE_NOTE, "!acpica: ECDT not found");
 414                 return (status);
 415         }
 416         if (ec_ignore_ecdt) {
 417                 /* pretend it was not found */
 418                 cmn_err(CE_NOTE, "!acpica: ECDT ignored");
 419                 return (AE_NOT_FOUND);
 420         }
 421 
 422         ecdt = (ACPI_TABLE_ECDT *)th;
 423         if (ecdt->Control.BitWidth != 8 ||
 424             ecdt->Data.BitWidth != 8) {
 425                 cmn_err(CE_NOTE, "!acpica: bad ECDT I/O width");
 426                 return (AE_BAD_VALUE);
 427         }
 428         status = AcpiGetHandle(NULL, (char *)ecdt->Id, &dev_hdl);
 429         if (ACPI_FAILURE(status)) {
 430                 cmn_err(CE_NOTE, "!acpica: no ECDT device handle");
 431                 return (status);
 432         }
 433 
 434         /*
 435          * Success.  Save info for attach.
 436          */
 437         ec.ec_base = ecdt->Data.Address;
 438         ec.ec_sc = ecdt->Control.Address;
 439         ec.ec_dev_hdl = dev_hdl;
 440         ec.ec_gpe_hdl = NULL;
 441         ec.ec_gpe_bit = ecdt->Gpe;
 442         ec.ec_ok = 1;
 443 
 444 #ifdef DEBUG
 445         cmn_err(CE_NOTE, "!acpica:ec_probe_ecdt: success");
 446 #endif
 447         return (0);
 448 }
 449 
 450 /*
 451  * Called from AcpiWalkDevices() when an EC device is found
 452  */
 453 static ACPI_STATUS
 454 ec_find(ACPI_HANDLE obj, UINT32 nest, void *context, void **rv)
 455 {
 456         _NOTE(ARGUNUSED(nest, rv))
 457 
 458         *((ACPI_HANDLE *)context) = obj;
 459         return (AE_OK);
 460 }
 461 
 462 /*
 463  * Normal way to get the details about the EC,
 464  * by searching the name space.
 465  */
 466 static ACPI_STATUS
 467 ec_probe_ns(void)
 468 {
 469         ACPI_HANDLE dev_hdl;
 470         ACPI_BUFFER buf, crs;
 471         ACPI_OBJECT *gpe_obj;
 472         ACPI_HANDLE gpe_hdl;
 473         ACPI_INTEGER gpe_bit;
 474         ACPI_STATUS status;
 475         int i, io_port_cnt;
 476         uint16_t ec_sc, ec_base;
 477 
 478         dev_hdl = NULL;
 479         (void) AcpiGetDevices("PNP0C09", &ec_find, (void *)&dev_hdl, NULL);
 480         if (dev_hdl == NULL) {
 481 #ifdef DEBUG
 482                 /* Not an error, just no EC on this machine. */
 483                 cmn_err(CE_WARN, "!acpica:ec_probe_ns: "
 484                     "PNP0C09 not found");
 485 #endif
 486                 return (AE_NOT_FOUND);
 487         }
 488 
 489         /*
 490          * Find ec_base and ec_sc addresses
 491          */
 492         crs.Length = ACPI_ALLOCATE_BUFFER;
 493         status = AcpiEvaluateObjectTyped(dev_hdl, "_CRS", NULL, &crs,
 494             ACPI_TYPE_BUFFER);
 495         if (ACPI_FAILURE(status)) {
 496                 cmn_err(CE_WARN, "!acpica:ec_probe_ns: "
 497                     "_CRS object evaluate failed");
 498                 return (status);
 499         }
 500 
 501         for (i = 0, io_port_cnt = 0;
 502             i < ((ACPI_OBJECT *)crs.Pointer)->Buffer.Length; i++) {
 503                 io_port_des_t *io_port;
 504                 uint8_t *tmp;
 505 
 506                 tmp = ((ACPI_OBJECT *)crs.Pointer)->Buffer.Pointer + i;
 507                 if (*tmp != IO_PORT_DES)
 508                         continue;
 509                 io_port = (io_port_des_t *)tmp;
 510                 /*
 511                  * first port is ec_base and second is ec_sc
 512                  */
 513                 if (io_port_cnt == 0)
 514                         ec_base = (io_port->min_base_hi << 8) |
 515                             io_port->min_base_lo;
 516                 if (io_port_cnt == 1)
 517                         ec_sc = (io_port->min_base_hi << 8) |
 518                             io_port->min_base_lo;
 519 
 520                 io_port_cnt++;
 521                 /*
 522                  * Increment ahead to next struct.
 523                  */
 524                 i += 7;
 525         }
 526         AcpiOsFree(crs.Pointer);
 527         if (io_port_cnt < 2) {
 528                 cmn_err(CE_WARN, "!acpica:ec_probe_ns: "
 529                     "_CRS parse failed");
 530                 return (AE_BAD_VALUE);
 531         }
 532 
 533         /*
 534          * Get the GPE info.
 535          */
 536         buf.Length = ACPI_ALLOCATE_BUFFER;
 537         status = AcpiEvaluateObject(dev_hdl, "_GPE", NULL, &buf);
 538         if (ACPI_FAILURE(status)) {
 539                 cmn_err(CE_WARN, "!acpica:ec_probe_ns: "
 540                     "_GPE object evaluate");
 541                 return (status);
 542         }
 543         gpe_obj = (ACPI_OBJECT *)buf.Pointer;
 544         /*
 545          * process the GPE description
 546          */
 547         switch (gpe_obj->Type) {
 548         case ACPI_TYPE_INTEGER:
 549                 gpe_hdl = NULL;
 550                 gpe_bit = gpe_obj->Integer.Value;
 551                 break;
 552         case ACPI_TYPE_PACKAGE:
 553                 if (gpe_obj->Package.Count != 2)
 554                         goto bad_gpe;
 555                 gpe_obj = gpe_obj->Package.Elements;
 556                 if (gpe_obj[1].Type != ACPI_TYPE_INTEGER)
 557                         goto bad_gpe;
 558                 gpe_hdl = gpe_obj[0].Reference.Handle;
 559                 gpe_bit = gpe_obj[1].Integer.Value;
 560                 break;
 561         bad_gpe:
 562         default:
 563                 status = AE_BAD_VALUE;
 564                 break;
 565         }
 566         AcpiOsFree(buf.Pointer);
 567         if (ACPI_FAILURE(status)) {
 568                 cmn_err(CE_WARN, "!acpica:ec_probe_ns: "
 569                     "_GPE parse failed");
 570                 return (status);
 571         }
 572 
 573         /*
 574          * Success.  Save info for attach.
 575          */
 576         ec.ec_base = ec_base;
 577         ec.ec_sc = ec_sc;
 578         ec.ec_dev_hdl = dev_hdl;
 579         ec.ec_gpe_hdl = gpe_hdl;
 580         ec.ec_gpe_bit = gpe_bit;
 581         ec.ec_ok = 1;
 582 
 583 #ifdef DEBUG
 584         cmn_err(CE_NOTE, "!acpica:ec_probe_ns: success");
 585 #endif
 586         return (0);
 587 }
 588 
 589 /*
 590  * Setup the Embedded Controller (EC) address space handler.
 591  * Entered only if one of the EC probe methods found an EC.
 592  */
 593 static void
 594 ec_init(void)
 595 {
 596         ACPI_STATUS rc;
 597         int x;
 598 
 599         /* paranoia */
 600         if (ec.ec_ok == 0)
 601                 return;
 602 
 603         /*
 604          * Drain the EC data register if something is left over from
 605          * legacy mode
 606          */
 607         if (inb(ec.ec_sc) & EC_OBF) {
 608                 x = inb(ec.ec_base);    /* read and discard value */
 609 #ifdef  DEBUG
 610                 cmn_err(CE_NOTE, "!EC had something: 0x%x", x);
 611 #endif
 612         }
 613 
 614         /*
 615          * Install an "EC address space" handler.
 616          *
 617          * This call does a name space walk under the passed
 618          * object looking for child objects with an EC space
 619          * region for which to install this handler.  Using
 620          * the ROOT object makes sure we find them all.
 621          *
 622          * XXX: Some systems return an error from this call
 623          * after a partial success, i.e. where the NS walk
 624          * installs on some nodes and fails on other nodes.
 625          * In such cases, disabling the EC and GPE handlers
 626          * makes things worse, so just report the error and
 627          * leave the EC handler enabled.
 628          *
 629          * At one point, it seemed that doing this part of
 630          * EC setup earlier may help, which is why this is
 631          * now a separate function from ec_attach.  Someone
 632          * needs to figure our why some systems give us an
 633          * error return from this call.  (TODO)
 634          */
 635         rc = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
 636             ACPI_ADR_SPACE_EC, &ec_handler, NULL, NULL);
 637         if (rc != AE_OK) {
 638                 cmn_err(CE_WARN, "!acpica:ec_init: "
 639                     "install AS handler, rc=0x%x", rc);
 640                 return;
 641         }
 642 #ifdef DEBUG
 643         cmn_err(CE_NOTE, "!acpica:ec_init: success");
 644 #endif
 645 }
 646 
 647 /*
 648  * Attach the EC General-Purpose Event (GPE) handler.
 649  */
 650 static void
 651 ec_attach(void)
 652 {
 653         ACPI_STATUS rc;
 654 
 655         /*
 656          * Guard against call without probe results.
 657          */
 658         if (ec.ec_ok == 0) {
 659                 cmn_err(CE_WARN, "!acpica:ec_attach: "
 660                     "no EC device found");
 661                 return;
 662         }
 663 
 664         /*
 665          * Install the GPE handler and enable it.
 666          */
 667         rc = AcpiInstallGpeHandler(ec.ec_gpe_hdl, ec.ec_gpe_bit,
 668             ACPI_GPE_EDGE_TRIGGERED, ec_gpe_handler, NULL);
 669         if (rc != AE_OK) {
 670                 cmn_err(CE_WARN, "!acpica:ec_attach: "
 671                     "install GPE handler, rc=0x%x", rc);
 672                 goto errout;
 673         }
 674 
 675         rc = AcpiEnableGpe(ec.ec_gpe_hdl, ec.ec_gpe_bit);
 676         if (rc != AE_OK) {
 677                 cmn_err(CE_WARN, "!acpica:ec_attach: "
 678                     "enable GPE handler, rc=0x%x", rc);
 679                 goto errout;
 680         }
 681 
 682 #ifdef DEBUG
 683         cmn_err(CE_NOTE, "!acpica:ec_attach: success");
 684 #endif
 685         return;
 686 
 687 errout:
 688         AcpiRemoveGpeHandler(ec.ec_gpe_hdl, ec.ec_gpe_bit,
 689             ec_gpe_handler);
 690 }
 691 
 692 /*
 693  * System Management Bus Controller (SMBC)
 694  * These also go through the EC.
 695  * (not yet supported)
 696  */
 697 static void
 698 smbus_attach(void)
 699 {
 700 #ifdef  DEBUG
 701         ACPI_HANDLE obj;
 702 
 703         obj = NULL;
 704         (void) AcpiGetDevices("ACPI0001", &ec_find, (void *)&obj, NULL);
 705         if (obj != NULL) {
 706                 cmn_err(CE_NOTE, "!acpica: found an SMBC Version 1.0");
 707         }
 708 
 709         obj = NULL;
 710         (void) AcpiGetDevices("ACPI0005", &ec_find, (void *)&obj, NULL);
 711         if (obj != NULL) {
 712                 cmn_err(CE_NOTE, "!acpica: found an SMBC Version 2.0");
 713         }
 714 #endif  /* DEBUG */
 715 }
 716 
 717 /*
 718  * Initialize the EC, if present.
 719  */
 720 void
 721 acpica_ec_init(void)
 722 {
 723         ACPI_STATUS rc;
 724 
 725         /*
 726          * Initialize EC mutex here
 727          */
 728         mutex_init(&ec.ec_mutex, NULL, MUTEX_DRIVER, NULL);
 729 
 730         /*
 731          * First search the ACPI tables for an ECDT, and
 732          * if not found, search the name space for it.
 733          */
 734         rc = ec_probe_ecdt();
 735         if (ACPI_FAILURE(rc))
 736                 rc = ec_probe_ns();
 737         if (ACPI_SUCCESS(rc)) {
 738                 ec_init();
 739                 ec_attach();
 740         }
 741         smbus_attach();
 742 }