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