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