Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/io/acpi_drv/acpi_drv.c
+++ new/usr/src/uts/i86pc/io/acpi_drv/acpi_drv.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
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 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26 /*
27 27 * Copyright 2015 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
28 28 */
29 29
30 30 /*
31 31 * Driver for ACPI Battery, Lid, and Hotkey Control
32 32 */
33 33 #include <sys/hotkey_drv.h>
34 34 #include <sys/sysevent/pwrctl.h>
35 35
36 36
37 37 #define ACPI_DRV_MOD_STRING "ACPI driver"
38 38
39 39 #define ACPI_DRV_MAX_BAT_NUM 8
40 40 #define ACPI_DRV_MAX_AC_NUM 10
41 41
42 42 #define BST_FLAG_DISCHARGING (0x1)
43 43 #define BST_FLAG_CHARGING (0x2)
44 44 #define BST_FLAG_CRITICAL (0x4)
45 45
46 46 /* Set if the battery is present */
47 47 #define STA_FLAG_BATT_PRESENT (0x10)
48 48
49 49 #define ACPI_DEVNAME_CBAT "PNP0C0A"
50 50 #define ACPI_DEVNAME_AC "ACPI0003"
51 51 #define ACPI_DEVNAME_LID "PNP0C0D"
52 52
53 53 #define ACPI_DRV_EVENTS (POLLIN | POLLRDNORM)
54 54
55 55 #ifdef DEBUG
56 56
57 57 #define ACPI_DRV_PRINT_BUFFER_SIZE 512
58 58 static char acpi_drv_prt_buf[ACPI_DRV_PRINT_BUFFER_SIZE];
59 59 static kmutex_t acpi_drv_prt_mutex;
60 60
61 61 static int acpi_drv_debug = 0;
62 62 #define ACPI_DRV_DBG(lev, devp, ...) \
63 63 do { \
64 64 if (acpi_drv_debug) acpi_drv_printf((devp), \
65 65 (lev), __VA_ARGS__); \
66 66 _NOTE(CONSTCOND) } while (0)
67 67 #define ACPI_DRV_PRT_NOTIFY(hdl, val) \
68 68 do { \
69 69 if (acpi_drv_debug) acpi_drv_prt_notify((hdl), (val)); \
70 70 _NOTE(CONSTCOND) } while (0)
71 71
72 72 #else
73 73
74 74 #define ACPI_DRV_DBG(lev, devp, ...)
75 75 #define ACPI_DRV_PRT_NOTIFY(hdl, val)
76 76
77 77 #endif /* DEBUG */
78 78
79 79 /* ACPI notify types */
80 80 enum acpi_drv_notify {
81 81 ACPI_DRV_NTF_UNKNOWN = -1, /* No notifications seen, ever. */
82 82 ACPI_DRV_NTF_CHANGED,
83 83 ACPI_DRV_NTF_OK
84 84 };
85 85
86 86 static int acpi_drv_dev_present(struct acpi_drv_dev *);
87 87 #define acpi_drv_ac_present(a) (((a)->dev.type == ACPI_DRV_TYPE_AC) ? \
88 88 acpi_drv_dev_present(&(a)->dev) : -1)
89 89 #define acpi_drv_cbat_present(a) (((a)->dev.type == ACPI_DRV_TYPE_CBAT) \
90 90 ? acpi_drv_dev_present(&(a)->dev) : -1)
91 91
92 92 static dev_info_t *acpi_drv_dip = NULL;
93 93 static kmutex_t acpi_drv_mutex;
94 94 static struct pollhead acpi_drv_pollhead;
95 95 static timeout_id_t acpi_drv_cbat_rescan_timeout;
96 96
97 97 /* Control Method Battery state */
98 98 struct acpi_drv_cbat_state {
99 99 struct acpi_drv_dev dev;
100 100 /* Caches of _BST and _BIF */
101 101 enum acpi_drv_notify bat_bifok;
102 102 acpi_bif_t bif_cache;
103 103 enum acpi_drv_notify bat_bstok;
104 104 acpi_bst_t bst_cache;
105 105
106 106 uint32_t charge_warn;
107 107 uint32_t charge_low;
108 108
109 109 kstat_t *bat_bif_ksp;
110 110 kstat_t *bat_bst_ksp;
111 111 } acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
112 112 static int nbat = 0;
113 113
114 114 /*
115 115 * Synthesis battery state
116 116 * When there are multiple batteries present, the battery subsystem
117 117 * is not required to perform any synthesis of a composite battery
118 118 * from the data of the separate batteries. In cases where the
119 119 * battery subsystem does not synthesize a composite battery from
120 120 * the separate battery's data, the OS must provide that synthesis.
121 121 */
122 122 static uint32_t acpi_drv_syn_rem_cap;
123 123 static uint32_t acpi_drv_syn_last_cap;
124 124 static uint32_t acpi_drv_syn_oem_warn_cap;
125 125 static uint32_t acpi_drv_syn_oem_low_cap;
126 126
127 127 static int acpi_drv_warn_enabled;
128 128 static uint32_t acpi_drv_syn_warn_per;
129 129 static uint32_t acpi_drv_syn_low_per;
130 130 static uint32_t acpi_drv_syn_warn_cap;
131 131 static uint32_t acpi_drv_syn_low_cap;
132 132 /* Tracking boundery passing of _BST charge levels */
133 133 static uint32_t acpi_drv_syn_last_level;
134 134
135 135 /* AC state */
136 136 static struct acpi_drv_ac_state {
137 137 struct acpi_drv_dev dev;
138 138 } acpi_drv_ac[ACPI_DRV_MAX_AC_NUM];
139 139 static int nac = 0;
140 140
141 141 /*
142 142 * Current power source device
143 143 * Note: assume only one device can be the power source device.
144 144 */
145 145 static int acpi_drv_psr_type = ACPI_DRV_TYPE_UNKNOWN;
146 146 static struct acpi_drv_dev *acpi_drv_psr_devp = NULL;
147 147
148 148 struct obj_desc {
149 149 char *name;
150 150 int offset;
151 151 int size;
152 152 int type;
153 153 };
154 154
155 155 /* Object copy definitions */
156 156 #define OFFSETOF(s, m) ((size_t)(&(((s *)0)->m)))
157 157 #define SIZEOF(s, m) (sizeof (((s *)0)->m))
158 158 #define FIELD(n, s, m, t) \
159 159 { n, OFFSETOF(s, m), SIZEOF(s, m), t }
160 160 #define FIELD_NULL { NULL, -1, 0, ACPI_TYPE_ANY }
161 161
162 162 static struct obj_desc bif_desc[] = {
163 163 FIELD("bif_unit", acpi_bif_t, bif_unit, ACPI_TYPE_INTEGER),
164 164 FIELD("bif_design_cap", acpi_bif_t, bif_design_cap, ACPI_TYPE_INTEGER),
165 165 FIELD("bif_last_cap", acpi_bif_t, bif_last_cap, ACPI_TYPE_INTEGER),
166 166 FIELD("bif_tech", acpi_bif_t, bif_tech, ACPI_TYPE_INTEGER),
167 167 FIELD("bif_voltage", acpi_bif_t, bif_voltage, ACPI_TYPE_INTEGER),
168 168 FIELD("bif_warn_cap", acpi_bif_t, bif_warn_cap, ACPI_TYPE_INTEGER),
169 169 FIELD("bif_low_cap", acpi_bif_t, bif_low_cap, ACPI_TYPE_INTEGER),
170 170 FIELD("bif_gran1_cap", acpi_bif_t, bif_gran1_cap, ACPI_TYPE_INTEGER),
171 171 FIELD("bif_gran2_cap", acpi_bif_t, bif_gran2_cap, ACPI_TYPE_INTEGER),
172 172 FIELD("bif_model", acpi_bif_t, bif_model, ACPI_TYPE_STRING),
173 173 FIELD("bif_serial", acpi_bif_t, bif_serial, ACPI_TYPE_STRING),
174 174 FIELD("bif_type", acpi_bif_t, bif_type, ACPI_TYPE_STRING),
175 175 FIELD("bif_oem_info", acpi_bif_t, bif_oem_info, ACPI_TYPE_STRING),
176 176 FIELD_NULL
177 177 };
178 178
179 179 static struct obj_desc bst_desc[] = {
180 180 FIELD("bst_state", acpi_bst_t, bst_state, ACPI_TYPE_INTEGER),
181 181 FIELD("bst_rate", acpi_bst_t, bst_rate, ACPI_TYPE_INTEGER),
182 182 FIELD("bst_rem_cap", acpi_bst_t, bst_rem_cap, ACPI_TYPE_INTEGER),
183 183 FIELD("bst_voltage", acpi_bst_t, bst_voltage, ACPI_TYPE_INTEGER),
184 184 FIELD_NULL
185 185 };
186 186
187 187 /* kstat definitions */
188 188 static kstat_t *acpi_drv_power_ksp;
189 189 static kstat_t *acpi_drv_warn_ksp;
190 190
191 191 acpi_drv_power_kstat_t acpi_drv_power_kstat = {
192 192 { SYSTEM_POWER, KSTAT_DATA_STRING },
193 193 { SUPPORTED_BATTERY_COUNT, KSTAT_DATA_UINT32 },
194 194 };
195 195
196 196 acpi_drv_warn_kstat_t acpi_drv_warn_kstat = {
197 197 { BW_ENABLED, KSTAT_DATA_UINT32 },
198 198 { BW_POWEROFF_THRESHOLD, KSTAT_DATA_UINT32 },
199 199 { BW_SHUTDOWN_THRESHOLD, KSTAT_DATA_UINT32 },
200 200 };
201 201
202 202 /* BIF */
203 203 acpi_drv_bif_kstat_t acpi_drv_bif_kstat = {
204 204 { BIF_UNIT, KSTAT_DATA_UINT32 },
205 205 { BIF_DESIGN_CAP, KSTAT_DATA_UINT32 },
206 206 { BIF_LAST_CAP, KSTAT_DATA_UINT32 },
207 207 { BIF_TECH, KSTAT_DATA_UINT32 },
208 208 { BIF_VOLTAGE, KSTAT_DATA_UINT32 },
209 209 { BIF_WARN_CAP, KSTAT_DATA_UINT32 },
210 210 { BIF_LOW_CAP, KSTAT_DATA_UINT32 },
211 211 { BIF_GRAN1_CAP, KSTAT_DATA_UINT32 },
212 212 { BIF_GRAN2_CAP, KSTAT_DATA_UINT32 },
213 213 { BIF_MODEL, KSTAT_DATA_STRING },
214 214 { BIF_SERIAL, KSTAT_DATA_STRING },
215 215 { BIF_TYPE, KSTAT_DATA_STRING },
216 216 { BIF_OEM_INFO, KSTAT_DATA_STRING },
217 217 };
218 218
219 219 /* BST */
220 220 acpi_drv_bst_kstat_t acpi_drv_bst_kstat = {
221 221 { BST_STATE, KSTAT_DATA_UINT32 },
222 222 { BST_RATE, KSTAT_DATA_UINT32 },
223 223 { BST_REM_CAP, KSTAT_DATA_UINT32 },
224 224 { BST_VOLTAGE, KSTAT_DATA_UINT32 },
225 225 };
226 226
227 227 struct acpi_drv_lid_state {
228 228 struct acpi_drv_dev dev;
229 229 enum acpi_drv_notify state_ok;
230 230 int state;
231 231 } lid;
232 232 static int nlid = 0;
233 233
234 234 struct hotkey_drv acpi_hotkey;
235 235
236 236 static int acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
237 237 static int acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
238 238 static int acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
239 239 void **resultp);
240 240 static int acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp);
241 241 static int acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp);
242 242 static int acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
243 243 cred_t *cr, int *rval);
244 244 static int acpi_drv_chpoll(dev_t dev, short events, int anyyet,
245 245 short *reventsp, struct pollhead **phpp);
246 246 static int acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode,
247 247 cred_t *cr, int *rval);
248 248 static int acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode,
249 249 cred_t *cr, int *rval);
250 250 static int acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode,
251 251 cred_t *cr, int *rval);
252 252 #ifdef DEBUG
253 253 static void acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev,
254 254 const char *fmt, ...);
255 255 #endif
256 256
257 257 static int acpi_drv_update_bif(struct acpi_drv_cbat_state *bp);
258 258 static int acpi_drv_update_bst(struct acpi_drv_cbat_state *bp);
259 259 static int acpi_drv_update_lid(struct acpi_drv_dev *bp);
260 260 static int acpi_drv_set_warn(acpi_drv_warn_t *bwp);
261 261 static struct acpi_drv_cbat_state *acpi_drv_idx2cbat(int idx);
262 262 static struct acpi_drv_ac_state *acpi_drv_idx2ac(int idx);
263 263 static int acpi_drv_acpi_init(void);
264 264 static void acpi_drv_acpi_fini(void);
265 265 static int acpi_drv_kstat_init(void);
266 266 static void acpi_drv_kstat_fini(void);
267 267
268 268 static int acpi_drv_kstat_bif_update(kstat_t *, int);
269 269 static int acpi_drv_kstat_bst_update(kstat_t *, int);
270 270
271 271 static void acpi_drv_cbat_rescan(void *);
272 272
273 273 static struct cb_ops acpi_drv_cb_ops = {
274 274 acpi_drv_open, /* open */
275 275 acpi_drv_close, /* close */
276 276 nodev, /* strategy */
277 277 nodev, /* print */
278 278 nodev, /* dump */
279 279 nodev, /* read */
280 280 nodev, /* write */
281 281 acpi_drv_ioctl, /* ioctl */
282 282 nodev, /* devmap */
283 283 nodev, /* mmap */
284 284 nodev, /* segmap */
285 285 acpi_drv_chpoll, /* chpoll */
286 286 ddi_prop_op, /* prop_op */
287 287 NULL, /* streamtab */
288 288 D_NEW | D_MP,
289 289 CB_REV,
290 290 nodev,
291 291 nodev
292 292 };
293 293
294 294 static struct dev_ops acpi_drv_dev_ops = {
295 295 DEVO_REV,
296 296 0, /* refcnt */
297 297 acpi_drv_getinfo, /* getinfo */
298 298 nulldev, /* identify */
299 299 nulldev, /* probe */
300 300 acpi_drv_attach, /* attach */
301 301 acpi_drv_detach, /* detach */
302 302 nodev, /* reset */
303 303 &acpi_drv_cb_ops,
304 304 NULL, /* no bus operations */
305 305 NULL, /* power */
306 306 ddi_quiesce_not_needed, /* quiesce */
↓ open down ↓ |
306 lines elided |
↑ open up ↑ |
307 307 };
308 308
309 309 static struct modldrv modldrv1 = {
310 310 &mod_driverops,
311 311 ACPI_DRV_MOD_STRING,
312 312 &acpi_drv_dev_ops
313 313 };
314 314
315 315 static struct modlinkage modlinkage = {
316 316 MODREV_1,
317 - (void *)&modldrv1,
318 - NULL,
317 + { (void *)&modldrv1, NULL }
319 318 };
320 319
321 320 int
322 321 _init(void)
323 322 {
324 323 int ret;
325 324
326 325 mutex_init(&acpi_drv_mutex, NULL, MUTEX_DRIVER, NULL);
327 326 #ifdef DEBUG
328 327 mutex_init(&acpi_drv_prt_mutex, NULL, MUTEX_DRIVER, NULL);
329 328 #endif
330 329
331 330 if ((ret = mod_install(&modlinkage)) != 0) {
332 331 mutex_destroy(&acpi_drv_mutex);
333 332 #ifdef DEBUG
334 333 mutex_destroy(&acpi_drv_prt_mutex);
335 334 #endif
336 335 }
337 336 return (ret);
338 337 }
339 338
340 339 int
341 340 _fini(void)
342 341 {
343 342 int ret;
344 343
345 344 if ((ret = mod_remove(&modlinkage)) == 0) {
346 345 #ifdef DEBUG
347 346 mutex_destroy(&acpi_drv_prt_mutex);
348 347 #endif
349 348 mutex_destroy(&acpi_drv_mutex);
350 349 }
351 350
352 351 return (ret);
353 352 }
354 353
355 354 int
356 355 _info(struct modinfo *mp)
357 356 {
358 357 return (mod_info(&modlinkage, mp));
359 358 }
360 359
361 360 static int
362 361 acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
363 362 {
364 363 switch (cmd) {
365 364 case DDI_ATTACH:
366 365 /* Limit to one instance of driver */
367 366 if (acpi_drv_dip) {
368 367 return (DDI_FAILURE);
369 368 }
370 369 break;
371 370 case DDI_RESUME:
372 371 case DDI_PM_RESUME:
373 372 return (DDI_SUCCESS);
374 373 default:
375 374 return (DDI_FAILURE);
376 375 }
377 376
378 377 acpi_drv_dip = devi;
379 378
380 379 /* Init ACPI related stuff */
381 380 if (acpi_drv_acpi_init() != ACPI_DRV_OK) {
382 381 goto error;
383 382 }
384 383
385 384 /* Init kstat related stuff */
386 385 if (acpi_drv_kstat_init() != ACPI_DRV_OK) {
387 386 goto error;
388 387 }
389 388
390 389 acpi_drv_cbat_rescan_timeout = timeout(acpi_drv_cbat_rescan, NULL,
391 390 drv_usectohz(MICROSEC));
392 391
393 392 return (DDI_SUCCESS);
394 393
395 394 error:
396 395 ddi_remove_minor_node(devi, NULL);
397 396 acpi_drv_kstat_fini();
398 397 acpi_drv_acpi_fini();
399 398 acpi_drv_dip = NULL;
400 399 return (DDI_FAILURE);
401 400 }
402 401
403 402 static int
404 403 acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
405 404 {
406 405 timeout_id_t tmp_rescan_timeout;
407 406
408 407 if (cmd != DDI_DETACH) {
409 408 return (DDI_FAILURE);
410 409 }
411 410
412 411 /*
413 412 * Clear the timeout id to indicate that the handler should not
414 413 * reschedule itself.
415 414 */
416 415 mutex_enter(&acpi_drv_mutex);
417 416 tmp_rescan_timeout = acpi_drv_cbat_rescan_timeout;
418 417 acpi_drv_cbat_rescan_timeout = 0;
419 418 mutex_exit(&acpi_drv_mutex);
420 419
421 420 (void) untimeout(tmp_rescan_timeout);
422 421
423 422 mutex_enter(&acpi_drv_mutex);
424 423 ddi_remove_minor_node(devi, NULL);
425 424
426 425 acpi_drv_kstat_fini();
427 426 acpi_drv_acpi_fini();
428 427 mutex_exit(&acpi_drv_mutex);
429 428 return (DDI_SUCCESS);
430 429 }
431 430
432 431 /* ARGSUSED */
433 432 static int
434 433 acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
435 434 {
436 435 switch (cmd) {
437 436 case DDI_INFO_DEVT2DEVINFO:
438 437 *resultp = acpi_drv_dip;
439 438 return (DDI_SUCCESS);
440 439 case DDI_INFO_DEVT2INSTANCE:
441 440 *resultp = (void*) 0;
442 441 return (DDI_SUCCESS);
443 442 default:
444 443 return (DDI_FAILURE);
445 444 }
446 445 }
447 446
448 447 /*ARGSUSED*/
449 448 static int
450 449 acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp)
451 450 {
452 451 if (acpi_drv_dip == NULL) {
453 452 return (ENXIO);
454 453 }
455 454
456 455 return (0);
457 456 }
458 457
459 458 /*ARGSUSED*/
460 459 static int
461 460 acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp)
462 461 {
463 462 return (0);
464 463 }
465 464
466 465 /*ARGSUSED*/
467 466 static int
468 467 acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
469 468 int *rval)
470 469 {
471 470 int minor;
472 471 int type, index;
473 472 int res = 0;
474 473
475 474 minor = getminor(dev);
476 475 type = MINOR2TYPE(minor);
477 476 index = MINOR2IDX(minor);
478 477
479 478 mutex_enter(&acpi_drv_mutex);
480 479
481 480 switch (type) {
482 481 case ACPI_DRV_TYPE_CBAT:
483 482 res = acpi_drv_cbat_ioctl(index, cmd, arg, mode, cr, rval);
484 483 break;
485 484 case ACPI_DRV_TYPE_AC:
486 485 res = acpi_drv_ac_ioctl(index, cmd, arg, mode, cr, rval);
487 486 break;
488 487 case ACPI_DRV_TYPE_LID:
489 488 res = acpi_drv_lid_ioctl(index, cmd, arg, mode, cr, rval);
490 489 break;
491 490 case ACPI_DRV_TYPE_HOTKEY:
492 491 res = acpi_drv_hotkey_ioctl(cmd, arg, mode, cr, rval);
493 492 break;
494 493 default:
495 494 res = EINVAL;
496 495 break;
497 496 }
498 497
499 498 mutex_exit(&acpi_drv_mutex);
500 499 return (res);
501 500 }
502 501
503 502 /*ARGSUSED*/
504 503 static int
505 504 acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
506 505 int *rval)
507 506 {
508 507 int res = 0;
509 508 acpi_drv_warn_t bwarn;
510 509 struct acpi_drv_cbat_state *bp;
511 510
512 511 ASSERT(mutex_owned(&acpi_drv_mutex));
513 512
514 513 bp = acpi_drv_idx2cbat(index);
515 514 if (!bp || bp->dev.valid != 1) {
516 515 return (ENXIO);
517 516 }
518 517
519 518 switch (cmd) {
520 519 /*
521 520 * Return _BIF(Battery Information) of battery[index],
522 521 * if battery plugged.
523 522 */
524 523 case ACPI_DRV_IOC_INFO:
525 524 if (bp->dev.present == 0) {
526 525 res = ENXIO;
527 526 break;
528 527 }
529 528
530 529 res = acpi_drv_update_bif(bp);
531 530 if (res != ACPI_DRV_OK) {
532 531 break;
533 532 }
534 533 if (copyout(&bp->bif_cache, (void *)arg,
535 534 sizeof (bp->bif_cache))) {
536 535 res = EFAULT;
537 536 }
538 537 break;
539 538
540 539 /*
541 540 * Return _BST(Battery Status) of battery[index],
542 541 * if battery plugged.
543 542 */
544 543 case ACPI_DRV_IOC_STATUS:
545 544 if (bp->dev.present == 0) {
546 545 res = ENXIO;
547 546 break;
548 547 }
549 548
550 549 res = acpi_drv_update_bst(bp);
551 550 if (res != ACPI_DRV_OK) {
552 551 break;
553 552 }
554 553 if (copyout(&bp->bst_cache, (void *)arg,
555 554 sizeof (bp->bst_cache))) {
556 555 res = EFAULT;
557 556 }
558 557 break;
559 558
560 559 /* Return the state of the battery bays in the system */
561 560 case ACPI_DRV_IOC_BAY:
562 561 {
563 562 batt_bay_t bay;
564 563
565 564 bay.bay_number = nbat;
566 565 bay.battery_map = 0;
567 566 for (bp = &acpi_drv_cbat[0];
568 567 bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM]; bp++) {
569 568 if (bp->dev.valid) {
570 569 if (bp->dev.present) {
571 570 bay.battery_map |=
572 571 (1 << bp->dev.index);
573 572 }
574 573 }
575 574 }
576 575 if (copyout(&bay, (void *)arg, sizeof (bay))) {
577 576 res = EFAULT;
578 577 break;
579 578 }
580 579 }
581 580 break;
582 581
583 582 /*
584 583 * Return the current power source device if available:
585 584 * 0 -- battery supplying power
586 585 * 1 -- AC supplying power
587 586 */
588 587 case ACPI_DRV_IOC_POWER_STATUS:
589 588 {
590 589 int val;
591 590
592 591 /* State not available */
593 592 if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
594 593 res = ENXIO;
595 594 break;
596 595 }
597 596 val = (acpi_drv_psr_type == ACPI_DRV_TYPE_AC) ? 1 : 0;
598 597 if (copyout(&val, (void *)arg, sizeof (val))) {
599 598 res = EFAULT;
600 599 break;
601 600 }
602 601 }
603 602 break;
604 603
605 604 /* Get charge-warn and charge-low levels for the whole system */
606 605 case ACPI_DRV_IOC_GET_WARNING:
607 606 bwarn.bw_enabled = acpi_drv_warn_enabled;
608 607 bwarn.bw_charge_warn = acpi_drv_syn_warn_per;
609 608 bwarn.bw_charge_low = acpi_drv_syn_low_per;
610 609 if (copyout(&bwarn, (void *)arg, sizeof (&bwarn))) {
611 610 res = EFAULT;
612 611 }
613 612 break;
614 613
615 614 /* Set charge-warn and charge-low levels for the whole system */
616 615 case ACPI_DRV_IOC_SET_WARNING:
617 616 if (drv_priv(cr)) {
618 617 res = EPERM;
619 618 break;
620 619 }
621 620 if (copyin((void *)arg, &bwarn, sizeof (bwarn))) {
622 621 res = EFAULT;
623 622 break;
624 623 }
625 624 res = acpi_drv_set_warn(&bwarn);
626 625 break;
627 626
628 627 default:
629 628 res = EINVAL;
630 629 break;
631 630 }
632 631
633 632 return (res);
634 633 }
635 634
636 635 /*ARGSUSED*/
637 636 static int
638 637 acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
639 638 int *rval)
640 639 {
641 640 int res = 0;
642 641 int ac_state;
643 642 struct acpi_drv_ac_state *acp;
644 643
645 644 ASSERT(mutex_owned(&acpi_drv_mutex));
646 645
647 646 acp = acpi_drv_idx2ac(index);
648 647 if (!acp || acp->dev.valid != 1) {
649 648 return (ENXIO);
650 649 }
651 650
652 651 switch (cmd) {
653 652 /* Return the number of AC adapters in the system */
654 653 case ACPI_DRV_IOC_AC_COUNT:
655 654 if (copyout(&nac, (void *)arg, sizeof (nac))) {
656 655 res = EFAULT;
657 656 }
658 657 break;
659 658
660 659 /*
661 660 * Return the state of AC[index] if available:
662 661 * 0 -- Off-line
663 662 * 1 -- On-line
664 663 */
665 664 case ACPI_DRV_IOC_POWER_STATUS:
666 665 if (!acp || acp->dev.valid != 1) {
667 666 res = ENXIO;
668 667 break;
669 668 }
670 669 /* State not available */
671 670 if ((ac_state = acpi_drv_ac_present(acp)) == -1) {
672 671 res = ENXIO;
673 672 break;
674 673 }
675 674 if (copyout(&ac_state, (void *)arg, sizeof (ac_state))) {
676 675 res = EFAULT;
677 676 }
678 677 break;
679 678
680 679 default:
681 680 res = EINVAL;
682 681 break;
683 682 }
684 683
685 684 return (res);
686 685 }
687 686
688 687 /*ARGSUSED*/
689 688 static int
690 689 acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
691 690 int *rval)
692 691 {
693 692 int res = 0;
694 693
695 694 /*
696 695 * lid.state 0 means lid is closed.
697 696 * lid.state non-zero means lid is open.
698 697 */
699 698 switch (cmd) {
700 699 case ACPI_DRV_IOC_LID_STATUS:
701 700 if (lid.state_ok == ACPI_DRV_NTF_UNKNOWN) {
702 701 /* State not available */
703 702 res = acpi_drv_update_lid(&lid.dev);
704 703 if (res != ACPI_DRV_OK) {
705 704 res = ENXIO;
706 705 break;
707 706 }
708 707 }
709 708 if (copyout(&lid.state, (void *)arg, sizeof (lid.state))) {
710 709 res = EFAULT;
711 710 }
712 711 break;
713 712 case ACPI_DRV_IOC_LID_UPDATE:
714 713 res = acpi_drv_update_lid(&lid.dev);
715 714 if (res != ACPI_DRV_OK) {
716 715 res = ENXIO;
717 716 break;
718 717 }
719 718 if (copyout(&lid.state, (void *)arg, sizeof (lid.state))) {
720 719 res = EFAULT;
721 720 }
722 721 break;
723 722
724 723 default:
725 724 res = EINVAL;
726 725 break;
727 726 }
728 727 return (res);
729 728 }
730 729
731 730 /*ARGSUSED*/
732 731 static int
733 732 acpi_drv_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
734 733 struct pollhead **phpp)
735 734 {
736 735 if (!anyyet) {
737 736 *phpp = &acpi_drv_pollhead;
738 737 }
739 738 *reventsp = 0;
740 739 return (0);
741 740 }
742 741
743 742 #ifdef DEBUG
744 743 static void
745 744 acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev,
746 745 const char *fmt, ...)
747 746 {
748 747 va_list args;
749 748
750 749 mutex_enter(&acpi_drv_prt_mutex);
751 750
752 751 va_start(args, fmt);
753 752 (void) vsprintf(acpi_drv_prt_buf, fmt, args);
754 753 va_end(args);
755 754
756 755 if (devp) {
757 756 cmn_err(lev, "%s.%s: %s", devp->hid, devp->uid,
758 757 acpi_drv_prt_buf);
759 758 } else {
760 759 cmn_err(lev, "%s", acpi_drv_prt_buf);
761 760 }
762 761 mutex_exit(&acpi_drv_prt_mutex);
763 762 }
764 763
765 764 static void
766 765 acpi_drv_prt_notify(ACPI_HANDLE hdl, UINT32 val)
767 766 {
768 767 ACPI_BUFFER buf;
769 768 char str[1024];
770 769
771 770 buf.Length = sizeof (str);
772 771 buf.Pointer = str;
773 772 (void) AcpiGetName(hdl, ACPI_FULL_PATHNAME, &buf);
774 773 cmn_err(CE_NOTE, "AcpiNotify(%s, 0x%02x)", str, val);
775 774 }
776 775 #endif /* DEBUG */
777 776
778 777 void
779 778 acpi_drv_gen_sysevent(struct acpi_drv_dev *devp, char *ev, uint32_t val)
780 779 {
781 780 nvlist_t *attr_list = NULL;
782 781 int err;
783 782 char pathname[MAXPATHLEN];
784 783
785 784 /* Allocate and build sysevent attribute list */
786 785 err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, DDI_NOSLEEP);
787 786 if (err != 0) {
788 787 ACPI_DRV_DBG(CE_WARN, NULL,
789 788 "cannot allocate memory for sysevent attributes\n");
790 789 return;
791 790 }
792 791
793 792 /* Add attributes */
794 793 err = nvlist_add_string(attr_list, PWRCTL_DEV_HID, devp->hid);
795 794 if (err != 0) {
796 795 ACPI_DRV_DBG(CE_WARN, NULL,
797 796 "Failed to add attr [%s] for %s/%s event",
798 797 PWRCTL_DEV_HID, EC_PWRCTL, ev);
799 798 nvlist_free(attr_list);
800 799 return;
801 800 }
802 801
803 802 err = nvlist_add_string(attr_list, PWRCTL_DEV_UID, devp->uid);
804 803 if (err != 0) {
805 804 ACPI_DRV_DBG(CE_WARN, NULL,
806 805 "Failed to add attr [%s] for %s/%s event",
807 806 PWRCTL_DEV_UID, EC_PWRCTL, ev);
808 807 nvlist_free(attr_list);
809 808 return;
810 809 }
811 810
812 811 err = nvlist_add_uint32(attr_list, PWRCTL_DEV_INDEX, devp->index);
813 812 if (err != 0) {
814 813 ACPI_DRV_DBG(CE_WARN, NULL,
815 814 "Failed to add attr [%s] for %s/%s event",
816 815 PWRCTL_DEV_INDEX, EC_PWRCTL, ev);
817 816 nvlist_free(attr_list);
818 817 return;
819 818 }
820 819
821 820 (void) ddi_pathname(acpi_drv_dip, pathname);
822 821 err = nvlist_add_string(attr_list, PWRCTL_DEV_PHYS_PATH, pathname);
823 822 if (err != 0) {
824 823 ACPI_DRV_DBG(CE_WARN, NULL,
825 824 "Failed to add attr [%s] for %s/%s event",
826 825 PWRCTL_DEV_PHYS_PATH, EC_PWRCTL, ev);
827 826 nvlist_free(attr_list);
828 827 return;
829 828 }
830 829
831 830 if (strcmp(ev, ESC_PWRCTL_WARN) && strcmp(ev, ESC_PWRCTL_LOW)) {
832 831 goto finish;
833 832 }
834 833
835 834 err = nvlist_add_uint32(attr_list, PWRCTL_CHARGE_LEVEL, val);
836 835 if (err != 0) {
837 836 ACPI_DRV_DBG(CE_WARN, NULL,
838 837 "Failed to add attr [%s] for %s/%s event",
839 838 PWRCTL_CHARGE_LEVEL, EC_PWRCTL, ev);
840 839 nvlist_free(attr_list);
841 840 return;
842 841 }
843 842
844 843 finish:
845 844 ACPI_DRV_DBG(CE_NOTE, NULL, "SysEv(%s, %s.%s, %d)",
846 845 ev, devp->hid, devp->uid, val);
847 846 /* Generate/log sysevent */
848 847 err = ddi_log_sysevent(acpi_drv_dip, DDI_VENDOR_SUNW, EC_PWRCTL,
849 848 ev, attr_list, NULL, DDI_NOSLEEP);
850 849 #ifdef DEBUG
851 850 if (err != DDI_SUCCESS) {
852 851 ACPI_DRV_DBG(CE_WARN, NULL,
853 852 "cannot log sysevent, err code %x\n", err);
854 853 }
855 854 #endif
856 855
857 856 nvlist_free(attr_list);
858 857 }
859 858
860 859 static int
861 860 acpi_drv_obj_copy(ACPI_OBJECT *op, char *bp, struct obj_desc *dp)
862 861 {
863 862 ACPI_OBJECT *ep;
864 863 char *fp;
865 864
866 865 ep = &op->Package.Elements[0];
867 866 for (; dp->offset != -1; dp++) {
868 867 fp = bp + dp->offset;
869 868 if (dp->type == ACPI_TYPE_INTEGER &&
870 869 ep->Type == dp->type) {
871 870 #ifdef DEBUG
872 871 if (dp->size <= 4) {
873 872 ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %u",
874 873 dp->name,
875 874 (uint32_t)ep->Integer.Value);
876 875 } else {
877 876 #ifdef _LP64
878 877 ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %lu",
879 878 dp->name, (uint64_t)ep->Integer.Value);
880 879 }
881 880 #else
882 881 ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %llu",
883 882 dp->name, (uint64_t)ep->Integer.Value);
884 883 }
885 884 #endif /* _LP64 */
886 885 #endif /* DEBUG */
887 886 *(uint32_t *)fp = ep->Integer.Value;
888 887 } else if (dp->type == ACPI_TYPE_STRING &&
889 888 ep->Type == dp->type) {
890 889 ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: \"%s\"",
891 890 dp->name, ep->String.Pointer);
892 891 (void) strlcpy(fp, ep->String.Pointer, dp->size);
893 892 } else if (dp->type == ACPI_TYPE_STRING &&
894 893 ep->Type == ACPI_TYPE_BUFFER) {
895 894 #ifdef DEBUG
896 895 int len;
897 896 char buf[MAXNAMELEN + 1];
898 897
899 898 len = (MAXNAMELEN < ep->Buffer.Length) ?
900 899 MAXNAMELEN : ep->Buffer.Length;
901 900 bcopy(ep->Buffer.Pointer, buf, len);
902 901 buf[len] = 0;
903 902 ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: [%d] \"%s\"",
904 903 dp->name, len, buf);
905 904 #endif
906 905
907 906 ASSERT(MAXNAMELEN >= ep->Buffer.Length);
908 907 bcopy(ep->Buffer.Pointer, fp, ep->Buffer.Length);
909 908 } else {
910 909 ACPI_DRV_DBG(CE_WARN, NULL,
911 910 "Bad field at offset %d: type %d",
912 911 dp->offset, ep->Type);
913 912 if (dp->type != ACPI_TYPE_STRING) {
914 913 return (ACPI_DRV_ERR);
915 914 }
916 915 }
917 916 ep++;
918 917 }
919 918
920 919 return (ACPI_DRV_OK);
921 920 }
922 921
923 922 /*
924 923 * Returns the current power source devices. Used for the AC adapter and is
925 924 * located under the AC adapter object in name space. Used to determine if
926 925 * system is running off the AC adapter. This will report that the system is
927 926 * not running on the AC adapter if any of the batteries in the system is
928 927 * being forced to discharge through _BMC.
929 928 *
930 929 * Return value:
931 930 * 0 -- Off-line, ie. battery supplying system power
932 931 * 1 -- On-line, ie. AC supplying system power
933 932 * -1 -- Unknown, some error ocurred.
934 933 * Note: It will also update the driver ac state.
935 934 */
936 935 static int
937 936 acpi_drv_get_psr(struct acpi_drv_ac_state *acp)
938 937 {
939 938 struct acpi_drv_dev *devp = &acp->dev;
940 939 int ac;
941 940
942 941 if (!devp->valid) {
943 942 ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
944 943 return (-1);
945 944 }
946 945
947 946 if (acpica_eval_int(devp->hdl, "_PSR", &ac) == AE_OK) {
948 947 ACPI_DRV_DBG(CE_NOTE, devp, "_PSR = %d", ac);
949 948 devp->present = ac;
950 949 } else {
951 950 ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _PSR failed");
952 951 devp->present = -1;
953 952 }
954 953
955 954 return (ac);
956 955 }
957 956
958 957 /*
959 958 * For most systems, the _STA for this device will always
960 959 * return a value with bits 0-3 set and will toggle bit 4
961 960 * to indicate the actual presence of a battery.
962 961 *
963 962 * Return value:
964 963 * 0 -- battery not present
965 964 * 1 -- battery present
966 965 * -1 -- Unknown, some error ocurred.
967 966 * Note: It will also update the driver cbat state.
968 967 */
969 968 static int
970 969 acpi_drv_get_sta(struct acpi_drv_cbat_state *bp)
971 970 {
972 971 struct acpi_drv_dev *devp = &bp->dev;
973 972 int val;
974 973
975 974 if (!devp->valid) {
976 975 ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
977 976 return (-1);
978 977 }
979 978
980 979 if (acpica_eval_int(devp->hdl, "_STA", &val) == AE_OK) {
981 980 ACPI_DRV_DBG(CE_NOTE, devp, "_STA = 0x%x", val);
982 981 devp->present = ((val & STA_FLAG_BATT_PRESENT) != 0);
983 982 } else {
984 983 ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _STA failed");
985 984 devp->present = -1;
986 985 }
987 986
988 987 return (val);
989 988 }
990 989
991 990 static int
992 991 acpi_drv_update_bif(struct acpi_drv_cbat_state *bp)
993 992 {
994 993 ACPI_BUFFER buf;
995 994 ACPI_OBJECT *objp;
996 995
997 996 /* BIF is only available when battery plugged */
998 997 ASSERT(bp->dev.present != 0);
999 998
1000 999 /* Update internal BIF cache */
1001 1000 bp->bat_bifok = ACPI_DRV_NTF_UNKNOWN;
1002 1001
1003 1002 buf.Length = ACPI_ALLOCATE_BUFFER;
1004 1003 if (ACPI_FAILURE(AcpiEvaluateObjectTyped(bp->dev.hdl, "_BIF",
1005 1004 NULL, &buf, ACPI_TYPE_PACKAGE))) {
1006 1005 ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _BIF failed");
1007 1006 return (ACPI_DRV_ERR);
1008 1007 }
1009 1008
1010 1009 objp = buf.Pointer;
1011 1010 ACPI_DRV_DBG(CE_NOTE, &bp->dev, "get _BIF");
1012 1011 if (acpi_drv_obj_copy(objp, (char *)&bp->bif_cache, bif_desc) ==
1013 1012 ACPI_DRV_ERR) {
1014 1013 AcpiOsFree(objp);
1015 1014 return (ACPI_DRV_ERR);
1016 1015 }
1017 1016 AcpiOsFree(objp);
1018 1017 bp->bat_bifok = ACPI_DRV_NTF_OK;
1019 1018 return (ACPI_DRV_OK);
1020 1019 }
1021 1020
1022 1021 static int
1023 1022 acpi_drv_update_bst(struct acpi_drv_cbat_state *bp)
1024 1023 {
1025 1024 ACPI_BUFFER buf;
1026 1025 ACPI_OBJECT *objp;
1027 1026
1028 1027 /* BST is only available when battery plugged */
1029 1028 ASSERT(bp->dev.present != 0);
1030 1029
1031 1030 /* Update internal BST cache */
1032 1031 bp->bat_bstok = ACPI_DRV_NTF_UNKNOWN;
1033 1032
1034 1033 buf.Length = ACPI_ALLOCATE_BUFFER;
1035 1034 if (ACPI_FAILURE(AcpiEvaluateObjectTyped(bp->dev.hdl, "_BST",
1036 1035 NULL, &buf, ACPI_TYPE_PACKAGE))) {
1037 1036 ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _BST failed");
1038 1037 return (ACPI_DRV_ERR);
1039 1038 }
1040 1039
1041 1040 objp = buf.Pointer;
1042 1041 ACPI_DRV_DBG(CE_NOTE, &bp->dev, "get _BST");
1043 1042 if (acpi_drv_obj_copy(objp, (char *)&bp->bst_cache, bst_desc) ==
1044 1043 ACPI_DRV_ERR) {
1045 1044 AcpiOsFree(objp);
1046 1045 return (ACPI_DRV_ERR);
1047 1046 }
1048 1047 AcpiOsFree(objp);
1049 1048
1050 1049 if (bp->bst_cache.bst_rate == 0) {
1051 1050 bp->bst_cache.bst_state &= ~(ACPI_DRV_BST_CHARGING |
1052 1051 ACPI_DRV_BST_DISCHARGING);
1053 1052 }
1054 1053 bp->bat_bstok = ACPI_DRV_NTF_OK;
1055 1054 return (ACPI_DRV_OK);
1056 1055 }
1057 1056
1058 1057 /*
1059 1058 * Return value:
1060 1059 * 1 -- device On-line
1061 1060 * 0 -- device Off-line
1062 1061 * -1 -- Unknown, some error ocurred.
1063 1062 */
1064 1063 static int
1065 1064 acpi_drv_dev_present(struct acpi_drv_dev *devp)
1066 1065 {
1067 1066 if (!devp->valid) {
1068 1067 ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
1069 1068 return (-1);
1070 1069 }
1071 1070
1072 1071 ASSERT(devp->type != ACPI_DRV_TYPE_UNKNOWN);
1073 1072
1074 1073 /* Update the device state */
1075 1074 if (devp->present == -1) {
1076 1075 if (devp->type == ACPI_DRV_TYPE_AC) {
1077 1076 (void) acpi_drv_get_psr((struct acpi_drv_ac_state *)
1078 1077 devp);
1079 1078 } else if (devp->type == ACPI_DRV_TYPE_CBAT) {
1080 1079 (void) acpi_drv_get_sta((struct acpi_drv_cbat_state *)
1081 1080 devp);
1082 1081 }
1083 1082 }
1084 1083
1085 1084 return (devp->present);
1086 1085 }
1087 1086
1088 1087 /*
1089 1088 * Check if the device p existance state has changed.
1090 1089 * Return value:
1091 1090 * 1 -- changed
1092 1091 * 0 -- no change
1093 1092 * -1 -- unknown
1094 1093 */
1095 1094 static int
1096 1095 acpi_drv_update_present(struct acpi_drv_dev *p)
1097 1096 {
1098 1097 int old_present = p->present;
1099 1098 int new_present;
1100 1099
1101 1100 ASSERT(p && p->valid);
1102 1101
1103 1102 p->present = -1;
1104 1103 new_present = acpi_drv_dev_present(p);
1105 1104 if (new_present == -1) {
1106 1105 return (-1);
1107 1106 }
1108 1107 if (new_present != old_present) {
1109 1108 return (1);
1110 1109 }
1111 1110 return (0);
1112 1111 }
1113 1112
1114 1113 static void
1115 1114 acpi_drv_set_psr(struct acpi_drv_dev *p)
1116 1115 {
1117 1116 acpi_drv_psr_devp = p;
1118 1117 if (p != NULL) {
1119 1118 ACPI_DRV_DBG(CE_NOTE, p, "psr = .");
1120 1119 acpi_drv_psr_type = p->type;
1121 1120 } else {
1122 1121 ACPI_DRV_DBG(CE_NOTE, p, "psr = ?");
1123 1122 acpi_drv_psr_type = ACPI_DRV_TYPE_UNKNOWN;
1124 1123 }
1125 1124 }
1126 1125
1127 1126 /*
1128 1127 * OSPM can determine independent warning and low battery
1129 1128 * capacity values based on the OEM-designed levels, but
1130 1129 * cannot set these values lower than the OEM-designed values.
1131 1130 */
1132 1131 static int
1133 1132 acpi_drv_set_warn(acpi_drv_warn_t *bwp)
1134 1133 {
1135 1134 uint32_t warn, low;
1136 1135
1137 1136 warn = acpi_drv_syn_last_cap * bwp->bw_charge_warn / 100;
1138 1137 low = acpi_drv_syn_last_cap * bwp->bw_charge_low / 100;
1139 1138
1140 1139 /* Update internal state */
1141 1140 if (bwp->bw_enabled) {
1142 1141 if (low >= warn || warn < acpi_drv_syn_oem_warn_cap ||
1143 1142 low < acpi_drv_syn_oem_low_cap) {
1144 1143 ACPI_DRV_DBG(CE_WARN, NULL, "charge level error");
1145 1144 return (EINVAL);
1146 1145 }
1147 1146
1148 1147 ACPI_DRV_DBG(CE_NOTE, NULL, "set warn: warn=%d low=%d", warn,
1149 1148 low);
1150 1149
1151 1150 acpi_drv_syn_warn_per = bwp->bw_charge_warn;
1152 1151 acpi_drv_syn_low_per = bwp->bw_charge_low;
1153 1152 acpi_drv_syn_warn_cap = warn;
1154 1153 acpi_drv_syn_low_cap = low;
1155 1154 acpi_drv_warn_enabled = 1;
1156 1155 } else {
1157 1156 acpi_drv_warn_enabled = 0;
1158 1157 }
1159 1158
1160 1159 return (0);
1161 1160 }
1162 1161
1163 1162 /*
1164 1163 * Update information for the synthesis battery
1165 1164 *
1166 1165 * Note: Sometimes the value to be returned from _BST or _BIF will be
1167 1166 * temporarily unknown. In this case, the method may return the value
1168 1167 * 0xFFFFFFFF as a placeholder. When the value becomes known, the
1169 1168 * appropriate notification (0x80 for _BST or 0x81 for BIF) should be
1170 1169 * issued, in like manner to any other change in the data returned by
1171 1170 * these methods. This will cause OSPM to re-evaluate the method obtaining
1172 1171 * the correct data value.
1173 1172 */
1174 1173 static void
1175 1174 acpi_drv_update_cap(int bif_changed)
1176 1175 {
1177 1176 struct acpi_drv_cbat_state *bp;
1178 1177
1179 1178 if (bif_changed != 0) {
1180 1179 acpi_drv_syn_oem_warn_cap = 0xffffffff;
1181 1180 acpi_drv_syn_oem_low_cap = 0xffffffff;
1182 1181 acpi_drv_syn_last_cap = 0xffffffff;
1183 1182 }
1184 1183 acpi_drv_syn_last_level = acpi_drv_syn_rem_cap;
1185 1184 acpi_drv_syn_rem_cap = 0xffffffff; /* initially unknown */
1186 1185
1187 1186 for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
1188 1187 bp++) {
1189 1188 if (bp->dev.valid) {
1190 1189 /* Escape the empty bays */
1191 1190 if (acpi_drv_cbat_present(bp) <= 0) {
1192 1191 continue;
1193 1192 }
1194 1193
1195 1194 if (bif_changed != 0 &&
1196 1195 bp->bat_bifok == ACPI_DRV_NTF_OK) {
1197 1196 acpi_bif_t *bif;
1198 1197
1199 1198 bif = &bp->bif_cache;
1200 1199
1201 1200 if (acpi_drv_syn_last_cap == 0xffffffff) {
1202 1201 acpi_drv_syn_last_cap = 0;
1203 1202 }
1204 1203 acpi_drv_syn_last_cap += bif->bif_last_cap;
1205 1204
1206 1205 if (bif->bif_warn_cap == 0xffffffff ||
1207 1206 bif->bif_low_cap == 0xffffffff) {
1208 1207 ACPI_DRV_DBG(CE_WARN, &bp->dev,
1209 1208 "BIF value "
1210 1209 "invalid, warn_cap=0x%x "
1211 1210 "low_cap=0x%x", bif->bif_warn_cap,
1212 1211 bif->bif_low_cap);
1213 1212 continue;
1214 1213 }
1215 1214 if (acpi_drv_syn_oem_warn_cap == 0xffffffff) {
1216 1215 acpi_drv_syn_oem_warn_cap = 0;
1217 1216 }
1218 1217 if (acpi_drv_syn_oem_low_cap == 0xffffffff) {
1219 1218 acpi_drv_syn_oem_low_cap = 0;
1220 1219 }
1221 1220
1222 1221 /*
1223 1222 * Use the highest level as the synthesis
1224 1223 * level.
1225 1224 */
1226 1225 if (bif->bif_warn_cap >
1227 1226 acpi_drv_syn_oem_warn_cap) {
1228 1227 acpi_drv_syn_oem_low_cap =
1229 1228 bif->bif_low_cap;
1230 1229 acpi_drv_syn_oem_warn_cap =
1231 1230 bif->bif_warn_cap;
1232 1231 }
1233 1232 }
1234 1233 #ifdef DEBUG
1235 1234 else if (bif_changed) {
1236 1235 ACPI_DRV_DBG(CE_NOTE, &bp->dev,
1237 1236 "BIF not ready");
1238 1237 }
1239 1238 #endif
1240 1239
1241 1240 if (bp->bat_bstok == ACPI_DRV_NTF_OK) {
1242 1241 acpi_bst_t *bst;
1243 1242
1244 1243 bst = &bp->bst_cache;
1245 1244
1246 1245 /*
1247 1246 * Batteries that are rechargeable and are in
1248 1247 * the discharging state are required to return
1249 1248 * a valid Battery Present Rate value.
1250 1249 * 0xFFFFFFFF - Unknown rate/capacity
1251 1250 */
1252 1251 if (bst->bst_rem_cap == 0xffffffff) {
1253 1252 ACPI_DRV_DBG(CE_WARN, &bp->dev,
1254 1253 "BST value invalid, "
1255 1254 "rate=0x%x cap=0x%x",
1256 1255 bst->bst_rate, bst->bst_rem_cap);
1257 1256 continue;
1258 1257 }
1259 1258
1260 1259 if (acpi_drv_syn_rem_cap == 0xffffffff) {
1261 1260 acpi_drv_syn_rem_cap = 0;
1262 1261 }
1263 1262 acpi_drv_syn_rem_cap += bst->bst_rem_cap;
1264 1263 /* Check for overflow */
1265 1264 ASSERT(acpi_drv_syn_rem_cap >=
1266 1265 bst->bst_rem_cap);
1267 1266 }
1268 1267 #ifdef DEBUG
1269 1268 else {
1270 1269 ACPI_DRV_DBG(CE_NOTE, &bp->dev,
1271 1270 "BST not ready");
1272 1271 }
1273 1272 #endif
1274 1273 }
1275 1274 }
1276 1275
1277 1276 ACPI_DRV_DBG(CE_NOTE, NULL, "syn_cap: %d syn_oem_warn: %d "
1278 1277 "syn_oem_low: %d", acpi_drv_syn_rem_cap, acpi_drv_syn_oem_warn_cap,
1279 1278 acpi_drv_syn_oem_low_cap);
1280 1279 }
1281 1280
1282 1281 static struct acpi_drv_cbat_state *
1283 1282 acpi_drv_idx2cbat(int idx)
1284 1283 {
1285 1284 if (idx >= ACPI_DRV_MAX_BAT_NUM) {
1286 1285 return (NULL);
1287 1286 }
1288 1287 return (&acpi_drv_cbat[idx]);
1289 1288 }
1290 1289
1291 1290 static struct acpi_drv_ac_state *
1292 1291 acpi_drv_idx2ac(int idx)
1293 1292 {
1294 1293 if (idx >= ACPI_DRV_MAX_AC_NUM) {
1295 1294 return (NULL);
1296 1295 }
1297 1296 return (&acpi_drv_ac[idx]);
1298 1297 }
1299 1298
1300 1299 /*ARGSUSED*/
1301 1300 static void
1302 1301 acpi_drv_cbat_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
1303 1302 {
1304 1303 struct acpi_drv_cbat_state *bp = ctx;
1305 1304 struct acpi_drv_dev *devp = &bp->dev;
1306 1305 int bif_changed;
1307 1306 uint32_t eval;
1308 1307 char *ev;
1309 1308 acpi_bst_t *bst;
1310 1309
1311 1310 mutex_enter(&acpi_drv_mutex);
1312 1311 ACPI_DRV_PRT_NOTIFY(hdl, val);
1313 1312
1314 1313 switch (val) {
1315 1314 /*
1316 1315 * BST has changed
1317 1316 * Whenever the Battery State value changes, the
1318 1317 * system will generate an SCI to notify the OS.
1319 1318 *
1320 1319 * Note: trip point is not used to implement the
1321 1320 * warning levels.
1322 1321 */
1323 1322 case 0x80:
1324 1323 /*
1325 1324 * We always get 0x80 and 0x81 at battery plug/unplug,
1326 1325 * but 0x80 may come first. In case that situation, we have
1327 1326 * to update battery present state here too to update bst
1328 1327 * correctly.
1329 1328 */
1330 1329 bif_changed = acpi_drv_update_present(devp);
1331 1330
1332 1331 if (devp->present == 0) {
1333 1332 if (acpi_drv_psr_devp == devp) {
1334 1333 acpi_drv_set_psr(NULL);
1335 1334 }
1336 1335 goto done;
1337 1336 }
1338 1337
1339 1338 if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) {
1340 1339 break;
1341 1340 }
1342 1341 acpi_drv_update_cap(bif_changed);
1343 1342
1344 1343 bst = &bp->bst_cache;
1345 1344 eval = bst->bst_rem_cap;
1346 1345
1347 1346 if (bst->bst_state & BST_FLAG_DISCHARGING) {
1348 1347 acpi_drv_set_psr(devp);
1349 1348 }
1350 1349 /*
1351 1350 * The Critical battery state indicates that all
1352 1351 * available batteries are discharged and do not
1353 1352 * appear to be able to supply power to run the
1354 1353 * system any longer. When this occurs, the OS
1355 1354 * should attempt to perform an emergency shutdown.
1356 1355 * Right now we do not shutdown. This would
1357 1356 * need some discussion first since it could be
1358 1357 * controversial.
1359 1358 */
1360 1359 #ifdef DEBUG
1361 1360 if (bst->bst_state & BST_FLAG_CRITICAL) {
1362 1361 ACPI_DRV_DBG(CE_WARN, devp, "BST_FLAG_CRITICAL set");
1363 1362
1364 1363 /*
1365 1364 * BST_FLAG_CRITICAL may set even with AC,
1366 1365 * plugged, when plug/unplug battery. Check
1367 1366 * to avoid erroneous shutdown.
1368 1367 */
1369 1368 if (acpi_drv_psr_devp == devp &&
1370 1369 bst->bst_rem_cap != 0xffffffff) {
1371 1370 ACPI_DRV_DBG(CE_WARN, NULL,
1372 1371 "Battery in critical state");
1373 1372 }
1374 1373 } else
1375 1374 #endif
1376 1375 if (acpi_drv_warn_enabled &&
1377 1376 (bst->bst_state & BST_FLAG_DISCHARGING)) {
1378 1377 /*
1379 1378 * This value is an estimation of the amount of
1380 1379 * energy or battery capacity required by the
1381 1380 * system to transition to any supported sleeping
1382 1381 * state. When the OS detects that the total
1383 1382 * available battery capacity is less than this
1384 1383 * value, it will transition the system to a user
1385 1384 * defined system state (S1-S5).
1386 1385 */
1387 1386 if (acpi_drv_syn_last_level > acpi_drv_syn_low_cap &&
1388 1387 acpi_drv_syn_rem_cap <= acpi_drv_syn_low_cap) {
1389 1388 acpi_drv_gen_sysevent(devp, ESC_PWRCTL_LOW,
1390 1389 eval);
1391 1390 /*
1392 1391 * When the total available energy (mWh) or capacity
1393 1392 * (mAh) in the batteries falls below this level,
1394 1393 * the OS will notify the user through the UI.
1395 1394 */
1396 1395 } else if (acpi_drv_syn_last_level >
1397 1396 acpi_drv_syn_warn_cap &&
1398 1397 acpi_drv_syn_rem_cap <= acpi_drv_syn_warn_cap) {
1399 1398 acpi_drv_gen_sysevent(devp, ESC_PWRCTL_WARN,
1400 1399 eval);
1401 1400 }
1402 1401 }
1403 1402
1404 1403 done:
1405 1404 acpi_drv_gen_sysevent(devp, ESC_PWRCTL_STATE_CHANGE, 0);
1406 1405 pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
1407 1406 break;
1408 1407
1409 1408 /* battery has been removed completely */
1410 1409 case 0x03:
1411 1410 /* BIF has changed */
1412 1411 case 0x81:
1413 1412 /*
1414 1413 * Note: Do not eliminate multiple ADD/REMOVE here,
1415 1414 * because they may corresponding to different batterys.
1416 1415 */
1417 1416 (void) acpi_drv_update_present(devp);
1418 1417 if (devp->present == 1) {
1419 1418 if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) {
1420 1419 break;
1421 1420 }
1422 1421 }
1423 1422
1424 1423 acpi_drv_update_cap(1);
1425 1424
1426 1425 eval = devp->present;
1427 1426 ev = eval ? ESC_PWRCTL_ADD : ESC_PWRCTL_REMOVE;
1428 1427 acpi_drv_gen_sysevent(devp, ev, 0);
1429 1428 pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
1430 1429 break;
1431 1430
1432 1431 case 0x82:
1433 1432 default:
1434 1433 break;
1435 1434 }
1436 1435
1437 1436 mutex_exit(&acpi_drv_mutex);
1438 1437 }
1439 1438
1440 1439 static int
1441 1440 acpi_drv_update_lid(struct acpi_drv_dev *p)
1442 1441 {
1443 1442 struct acpi_drv_lid_state *lp = (struct acpi_drv_lid_state *)p;
1444 1443
1445 1444 if (acpica_eval_int(p->hdl, "_LID", &lp->state) == AE_OK) {
1446 1445 lp->state_ok = ACPI_DRV_NTF_OK;
1447 1446 return (ACPI_DRV_OK);
1448 1447 }
1449 1448 return (ACPI_DRV_ERR);
1450 1449 }
1451 1450
1452 1451 /*ARGSUSED*/
1453 1452 static void
1454 1453 acpi_drv_ac_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
1455 1454 {
1456 1455 struct acpi_drv_ac_state *acp = ctx;
1457 1456 struct acpi_drv_dev *devp = &acp->dev;
1458 1457 int old_present;
1459 1458 char *ev;
1460 1459 int eval;
1461 1460
1462 1461 ACPI_DRV_PRT_NOTIFY(hdl, val);
1463 1462 if (val != 0x80) {
1464 1463 return;
1465 1464 }
1466 1465
1467 1466 mutex_enter(&acpi_drv_mutex);
1468 1467 /*
1469 1468 * Note: if unplug and then quickly plug back, two ADD
1470 1469 * events will be generated.
1471 1470 */
1472 1471 old_present = devp->present;
1473 1472 eval = acpi_drv_get_psr(acp);
1474 1473
1475 1474 /* Eliminate redundant events */
1476 1475 if (eval != -1 && eval != old_present) {
1477 1476 /* Keep tracking the current power source device */
1478 1477 if (eval == 1) {
1479 1478 ev = ESC_PWRCTL_ADD;
1480 1479 acpi_drv_set_psr(devp);
1481 1480 } else {
1482 1481 ev = ESC_PWRCTL_REMOVE;
1483 1482 /* If AC was supplying the power, it's not now */
1484 1483 if (acpi_drv_psr_devp == devp) {
1485 1484 acpi_drv_set_psr(NULL);
1486 1485 }
1487 1486 }
1488 1487
1489 1488 acpi_drv_gen_sysevent(devp, ev, 0);
1490 1489 pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
1491 1490 }
1492 1491
1493 1492 mutex_exit(&acpi_drv_mutex);
1494 1493 }
1495 1494
1496 1495 static void
1497 1496 acpi_drv_lid_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
1498 1497 {
1499 1498 struct acpi_drv_lid_state *p = ctx;
1500 1499
1501 1500 ACPI_DRV_PRT_NOTIFY(hdl, val);
1502 1501 if (val == 0x80) {
1503 1502 mutex_enter(&acpi_drv_mutex);
1504 1503 if (acpi_drv_update_lid(&p->dev) == ACPI_DRV_OK) {
1505 1504 acpi_drv_gen_sysevent(&p->dev, p->state ?
1506 1505 ESC_PWRCTL_ADD : ESC_PWRCTL_REMOVE, 0);
1507 1506 }
1508 1507 mutex_exit(&acpi_drv_mutex);
1509 1508 }
1510 1509 }
1511 1510
1512 1511 static int
1513 1512 acpi_drv_obj_init(struct acpi_drv_dev *p)
1514 1513 {
1515 1514 ACPI_DEVICE_INFO *info;
1516 1515 ACPI_NOTIFY_HANDLER ntf_handler = NULL;
1517 1516 ACPI_STATUS ret;
1518 1517 char name[KSTAT_STRLEN];
1519 1518
1520 1519 ASSERT(p != NULL && p->hdl != NULL);
1521 1520
1522 1521 p->valid = 0;
1523 1522
1524 1523 /* Info size is variable depending on existance of _CID */
1525 1524 ret = AcpiGetObjectInfo(p->hdl, &info);
1526 1525 if (ACPI_FAILURE(ret)) {
1527 1526 ACPI_DRV_DBG(CE_WARN, NULL,
1528 1527 "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
1529 1528 return (ACPI_DRV_ERR);
1530 1529 }
1531 1530
1532 1531 if ((info->Valid & ACPI_VALID_HID) == 0) {
1533 1532 ACPI_DRV_DBG(CE_WARN, NULL,
1534 1533 "AcpiGetObjectInfo(): _HID not available");
1535 1534 p->hid[0] = 0;
1536 1535 } else {
1537 1536 (void) strlcpy(p->hid, info->HardwareId.String, ID_LEN);
1538 1537 }
1539 1538
1540 1539 /*
1541 1540 * This object is optional, but is required when the device
1542 1541 * has no other way to report a persistent unique device ID.
1543 1542 */
1544 1543 if ((info->Valid & ACPI_VALID_UID) == 0) {
1545 1544 ACPI_DRV_DBG(CE_WARN, NULL,
1546 1545 "AcpiGetObjectInfo(): _UID not available");
1547 1546 /* Use 0 as the default _UID */
1548 1547 p->uid[0] = 0;
1549 1548 } else {
1550 1549 (void) strlcpy(p->uid, info->UniqueId.String, ID_LEN);
1551 1550 }
1552 1551
1553 1552 AcpiOsFree(info);
1554 1553 p->valid = 1;
1555 1554
1556 1555 if (strcmp(p->hid, ACPI_DEVNAME_CBAT) == 0) {
1557 1556 struct acpi_drv_cbat_state *bp =
1558 1557 (struct acpi_drv_cbat_state *)p;
1559 1558 kstat_t *ksp;
1560 1559
1561 1560 p->type = ACPI_DRV_TYPE_CBAT;
1562 1561 p->index = nbat - 1;
1563 1562
1564 1563 /* Update device present state */
1565 1564 (void) acpi_drv_update_present(p);
1566 1565 if (p->present) {
1567 1566 (void) acpi_drv_update_bif(bp);
1568 1567 (void) acpi_drv_update_bst(bp);
1569 1568
1570 1569 /* Init the current power source */
1571 1570 if (bp->bst_cache.bst_state & BST_FLAG_DISCHARGING) {
1572 1571 acpi_drv_set_psr(p);
1573 1572 }
1574 1573 }
1575 1574 ntf_handler = acpi_drv_cbat_notify;
1576 1575 ACPI_DRV_DBG(CE_NOTE, p, "battery %s",
1577 1576 (p->present ? "present" : "absent"));
1578 1577
1579 1578 /* Create minor node for battery */
1580 1579 (void) snprintf(name, sizeof (name), "battery%d", p->index);
1581 1580 if (ddi_create_minor_node(acpi_drv_dip, name, S_IFCHR,
1582 1581 MINOR_BATT(p->index), DDI_PSEUDO, 0) == DDI_FAILURE)
1583 1582 ACPI_DRV_DBG(CE_WARN, NULL,
1584 1583 "%s: minor node create failed", name);
1585 1584
1586 1585 /*
1587 1586 * Allocate, initialize and install BIF and BST kstat
1588 1587 */
1589 1588 /* BIF kstat */
1590 1589 (void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
1591 1590 ACPI_DRV_BIF_KSTAT_NAME, bp->dev.index);
1592 1591 ksp = kstat_create(ACPI_DRV_NAME, 0, name, "misc",
1593 1592 KSTAT_TYPE_NAMED,
1594 1593 sizeof (acpi_drv_bif_kstat) / sizeof (kstat_named_t),
1595 1594 KSTAT_FLAG_VIRTUAL);
1596 1595 if (ksp != NULL) {
1597 1596 ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
1598 1597 name);
1599 1598
1600 1599 bp->bat_bif_ksp = ksp;
1601 1600 ksp->ks_data = &acpi_drv_bif_kstat;
1602 1601 ksp->ks_update = acpi_drv_kstat_bif_update;
1603 1602 ksp->ks_data_size += MAXNAMELEN * 4;
1604 1603 ksp->ks_private = bp;
1605 1604
1606 1605 kstat_install(ksp);
1607 1606 } else {
1608 1607 ACPI_DRV_DBG(CE_WARN, NULL,
1609 1608 "kstat_create(%s) fail", name);
1610 1609 }
1611 1610
1612 1611 /* BST kstat */
1613 1612 (void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
1614 1613 ACPI_DRV_BST_KSTAT_NAME, bp->dev.index);
1615 1614 ksp = kstat_create(ACPI_DRV_NAME, 0, name, "misc",
1616 1615 KSTAT_TYPE_NAMED,
1617 1616 sizeof (acpi_drv_bst_kstat) / sizeof (kstat_named_t),
1618 1617 KSTAT_FLAG_VIRTUAL);
1619 1618 if (ksp != NULL) {
1620 1619 ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
1621 1620 name);
1622 1621
1623 1622 bp->bat_bst_ksp = ksp;
1624 1623 ksp->ks_data = &acpi_drv_bst_kstat;
1625 1624 ksp->ks_update = acpi_drv_kstat_bst_update;
1626 1625 ksp->ks_data_size += MAXNAMELEN * 4;
1627 1626 ksp->ks_private = bp;
1628 1627
1629 1628 kstat_install(ksp);
1630 1629 } else {
1631 1630 ACPI_DRV_DBG(CE_WARN, NULL,
1632 1631 "kstat_create(%s) fail", name);
1633 1632 }
1634 1633 } else if (strcmp(p->hid, ACPI_DEVNAME_AC) == 0) {
1635 1634 p->type = ACPI_DRV_TYPE_AC;
1636 1635 p->index = nac - 1;
1637 1636
1638 1637 /* Update device present state */
1639 1638 (void) acpi_drv_update_present(p);
1640 1639 if (p->present) {
1641 1640 /* Init the current power source */
1642 1641 acpi_drv_set_psr(p);
1643 1642 }
1644 1643 ntf_handler = acpi_drv_ac_notify;
1645 1644 ACPI_DRV_DBG(CE_NOTE, p, "AC %s",
1646 1645 (p->present ? "on-line" : "off-line"));
1647 1646
1648 1647 /* Create minor node for AC */
1649 1648 (void) snprintf(name, sizeof (name), "ac%d", p->index);
1650 1649 if (ddi_create_minor_node(acpi_drv_dip, name, S_IFCHR,
1651 1650 MINOR_AC(p->index), DDI_PSEUDO, 0) == DDI_FAILURE)
1652 1651 ACPI_DRV_DBG(CE_WARN, NULL,
1653 1652 "%s: minor node create failed", name);
1654 1653 } else if (strcmp(p->hid, ACPI_DEVNAME_LID) == 0) {
1655 1654 p->type = ACPI_DRV_TYPE_LID;
1656 1655 p->index = 0;
1657 1656 lid.state_ok = ACPI_DRV_NTF_UNKNOWN;
1658 1657 (void) acpi_drv_update_lid(p);
1659 1658 ntf_handler = acpi_drv_lid_notify;
1660 1659 ACPI_DRV_DBG(CE_NOTE, p, "added");
1661 1660
1662 1661 /* Create minor node for lid. */
1663 1662 if (ddi_create_minor_node(acpi_drv_dip, "lid", S_IFCHR,
1664 1663 MINOR_LID(p->index), DDI_PSEUDO, 0) == DDI_FAILURE)
1665 1664 ACPI_DRV_DBG(CE_WARN, NULL,
1666 1665 "lid: minor node create failed");
1667 1666 } else {
1668 1667 ACPI_DRV_DBG(CE_NOTE, p, "unknown device");
1669 1668 p->valid = 0;
1670 1669 }
1671 1670
1672 1671 /* Register ACPI battery related events */
1673 1672 if (ntf_handler != NULL) {
1674 1673 if (ACPI_FAILURE(AcpiInstallNotifyHandler(p->hdl,
1675 1674 ACPI_ALL_NOTIFY, ntf_handler, p))) {
1676 1675 ACPI_DRV_DBG(CE_NOTE, NULL,
1677 1676 "Notify handler for %s.%s install failed",
1678 1677 p->hid, p->uid);
1679 1678 return (ACPI_DRV_ERR);
1680 1679 }
1681 1680 }
1682 1681
1683 1682 return (ACPI_DRV_OK);
1684 1683 }
1685 1684
1686 1685 /*ARGSUSED*/
1687 1686 static ACPI_STATUS
1688 1687 acpi_drv_find_cb(ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context,
1689 1688 void **ReturnValue)
1690 1689 {
1691 1690 struct acpi_drv_dev *devp;
1692 1691 int *type = (int *)Context;
1693 1692
1694 1693 if (*type == ACPI_DRV_TYPE_CBAT) {
1695 1694 struct acpi_drv_cbat_state *bp;
1696 1695
1697 1696 for (bp = acpi_drv_cbat;
1698 1697 bp != &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
1699 1698 bp++)
1700 1699 if (bp->dev.hdl == ObjHandle)
1701 1700 return (AE_OK);
1702 1701
1703 1702 if (nbat == ACPI_DRV_MAX_BAT_NUM) {
1704 1703 ACPI_DRV_DBG(CE_WARN, NULL,
1705 1704 "Need to support more batteries: "
1706 1705 "BATTERY_MAX = %d", ACPI_DRV_MAX_BAT_NUM);
1707 1706 return (AE_LIMIT);
1708 1707 }
1709 1708 bp = &acpi_drv_cbat[nbat++];
1710 1709 devp = (struct acpi_drv_dev *)bp;
1711 1710 } else if (*type == ACPI_DRV_TYPE_AC) {
1712 1711 struct acpi_drv_ac_state *ap;
1713 1712
1714 1713 for (ap = acpi_drv_ac;
1715 1714 ap != &acpi_drv_ac[ACPI_DRV_MAX_AC_NUM];
1716 1715 ap++)
1717 1716 if (ap->dev.hdl == ObjHandle)
1718 1717 return (AE_OK);
1719 1718
1720 1719 if (nac == ACPI_DRV_MAX_AC_NUM) {
1721 1720 ACPI_DRV_DBG(CE_WARN, NULL, "Need to support more ACs: "
1722 1721 "AC_MAX = %d", ACPI_DRV_MAX_AC_NUM);
1723 1722 return (AE_LIMIT);
1724 1723 }
1725 1724 ap = &acpi_drv_ac[nac++];
1726 1725 devp = (struct acpi_drv_dev *)ap;
1727 1726 } else if (*type == ACPI_DRV_TYPE_LID) {
1728 1727 struct acpi_drv_lid_state *lp;
1729 1728
1730 1729 lp = &lid;
1731 1730 if (lp->dev.hdl == ObjHandle)
1732 1731 return (AE_OK);
1733 1732
1734 1733 nlid++;
1735 1734 devp = (struct acpi_drv_dev *)lp;
1736 1735 } else {
1737 1736 ACPI_DRV_DBG(CE_WARN, NULL, "acpi_drv_find_cb(): "
1738 1737 "Unknown device");
1739 1738 return (AE_ERROR);
1740 1739 }
1741 1740
1742 1741 devp->hdl = ObjHandle;
1743 1742
1744 1743 /* Try to get as many working objs as possible */
1745 1744 (void) acpi_drv_obj_init(devp);
1746 1745 return (AE_OK);
1747 1746 }
1748 1747
1749 1748 /*ARGSUSED*/
1750 1749 static void
1751 1750 acpi_drv_cbat_rescan(void *arg)
1752 1751 {
1753 1752 int *retp, type = ACPI_DRV_TYPE_CBAT;
1754 1753
1755 1754 mutex_enter(&acpi_drv_mutex);
1756 1755
1757 1756 /*
1758 1757 * The detach routine clears the timeout id to tell us not to
1759 1758 * reschedule ourselves. If thats the case there's also no point
1760 1759 * in looking for new ACPI battery devices, so just return.
1761 1760 */
1762 1761 if (acpi_drv_cbat_rescan_timeout == 0) {
1763 1762 mutex_exit(&acpi_drv_mutex);
1764 1763 return;
1765 1764 }
1766 1765
1767 1766 (void) AcpiGetDevices(ACPI_DEVNAME_CBAT, acpi_drv_find_cb, &type,
1768 1767 (void *)&retp);
1769 1768
1770 1769 acpi_drv_cbat_rescan_timeout = timeout(acpi_drv_cbat_rescan, NULL,
1771 1770 drv_usectohz(MICROSEC));
1772 1771 mutex_exit(&acpi_drv_mutex);
1773 1772 }
1774 1773
1775 1774 static int
1776 1775 acpi_drv_acpi_init(void)
1777 1776 {
1778 1777 int *retp, type;
1779 1778 int status = ACPI_DRV_ERR;
1780 1779 hotkey_drv_t *htkp;
1781 1780
1782 1781 /* Check to see if ACPI CA services are available */
1783 1782 if (AcpiSubsystemStatus() != AE_OK) {
1784 1783 ACPI_DRV_DBG(CE_WARN, NULL, "ACPI CA not ready");
1785 1784 return (status);
1786 1785 }
1787 1786
1788 1787 /* Init Control Method Batterys */
1789 1788 type = ACPI_DRV_TYPE_CBAT;
1790 1789 if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_CBAT, acpi_drv_find_cb,
1791 1790 &type, (void *)&retp)) && nbat) {
1792 1791 status = ACPI_DRV_OK;
1793 1792 }
1794 1793
1795 1794 /* Init AC */
1796 1795 type = ACPI_DRV_TYPE_AC;
1797 1796 if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_AC, acpi_drv_find_cb,
1798 1797 &type, (void *)&retp)) && nac) {
1799 1798 status = ACPI_DRV_OK;
1800 1799 }
1801 1800
1802 1801 /* Init LID */
1803 1802 type = ACPI_DRV_TYPE_LID;
1804 1803 if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_LID, acpi_drv_find_cb,
1805 1804 &type, (void *)&retp)) && nlid) {
1806 1805 status = ACPI_DRV_OK;
1807 1806 }
1808 1807
1809 1808 /* Init Hotkey Device */
1810 1809 type = ACPI_DRV_TYPE_HOTKEY;
1811 1810 htkp = &acpi_hotkey;
1812 1811 bzero(htkp, sizeof (hotkey_drv_t));
1813 1812 htkp->dip = acpi_drv_dip;
1814 1813 htkp->hotkey_lock = &acpi_drv_mutex;
1815 1814 if (hotkey_init(htkp) == ACPI_DRV_OK) {
1816 1815 status = ACPI_DRV_OK;
1817 1816 }
1818 1817
1819 1818 acpi_drv_update_cap(1);
1820 1819
1821 1820 return (status);
1822 1821 }
1823 1822
1824 1823 static void
1825 1824 acpi_drv_acpi_fini(void)
1826 1825 {
1827 1826 int i;
1828 1827 struct acpi_drv_cbat_state *bp;
1829 1828
1830 1829 for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
1831 1830 bp++) {
1832 1831 if (bp->dev.valid) {
1833 1832 (void) AcpiRemoveNotifyHandler(bp->dev.hdl,
1834 1833 ACPI_DEVICE_NOTIFY, acpi_drv_cbat_notify);
1835 1834 }
1836 1835 }
1837 1836 for (i = 0; i < nac; i++) {
1838 1837 (void) AcpiRemoveNotifyHandler(acpi_drv_ac[i].dev.hdl,
1839 1838 ACPI_DEVICE_NOTIFY, acpi_drv_ac_notify);
1840 1839 }
1841 1840 (void) AcpiRemoveNotifyHandler(lid.dev.hdl, ACPI_DEVICE_NOTIFY,
1842 1841 acpi_drv_lid_notify);
1843 1842
1844 1843 if (acpi_hotkey.hotkey_method != HOTKEY_METHOD_NONE)
1845 1844 (void) hotkey_fini(&acpi_hotkey);
1846 1845 }
1847 1846
1848 1847 /*ARGSUSED*/
1849 1848 static int
1850 1849 acpi_drv_kstat_power_update(kstat_t *ksp, int flag)
1851 1850 {
1852 1851 if (flag == KSTAT_WRITE) {
1853 1852 return (EACCES);
1854 1853 }
1855 1854
1856 1855 mutex_enter(&acpi_drv_mutex);
1857 1856 if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
1858 1857 mutex_exit(&acpi_drv_mutex);
1859 1858 return (EIO);
1860 1859 }
1861 1860 kstat_named_setstr(&acpi_drv_power_kstat.acpi_drv_power,
1862 1861 acpi_drv_psr_type == ACPI_DRV_TYPE_AC ? AC : BATTERY);
1863 1862 acpi_drv_power_kstat.acpi_drv_supported_battery_count.value.ui32 =
1864 1863 (uint32_t)nbat;
1865 1864 mutex_exit(&acpi_drv_mutex);
1866 1865
1867 1866 return (0);
1868 1867 }
1869 1868
1870 1869 /*ARGSUSED*/
1871 1870 static int
1872 1871 acpi_drv_kstat_warn_update(kstat_t *ksp, int flag)
1873 1872 {
1874 1873 if (flag == KSTAT_WRITE) {
1875 1874 int ret = 0;
1876 1875 acpi_drv_warn_t bw;
1877 1876 acpi_drv_warn_kstat_t kbw;
1878 1877
1879 1878 kbw = *(acpi_drv_warn_kstat_t *)acpi_drv_warn_ksp->ks_data;
1880 1879
1881 1880 mutex_enter(&acpi_drv_mutex);
1882 1881 bw.bw_enabled = kbw.acpi_drv_bw_enabled.value.ui32;
1883 1882 bw.bw_charge_warn = kbw.acpi_drv_bw_charge_warn.value.ui32;
1884 1883 bw.bw_charge_low = kbw.acpi_drv_bw_charge_low.value.ui32;
1885 1884 ret = acpi_drv_set_warn(&bw);
1886 1885 mutex_exit(&acpi_drv_mutex);
1887 1886
1888 1887 return (ret);
1889 1888 } else {
1890 1889 acpi_drv_warn_kstat_t *wp = &acpi_drv_warn_kstat;
1891 1890
1892 1891 mutex_enter(&acpi_drv_mutex);
1893 1892 wp->acpi_drv_bw_enabled.value.ui32 = acpi_drv_warn_enabled;
1894 1893 wp->acpi_drv_bw_charge_warn.value.ui32 = acpi_drv_syn_warn_per;
1895 1894 wp->acpi_drv_bw_charge_low.value.ui32 = acpi_drv_syn_low_per;
1896 1895 mutex_exit(&acpi_drv_mutex);
1897 1896
1898 1897 return (0);
1899 1898 }
1900 1899 }
1901 1900
1902 1901 static int
1903 1902 acpi_drv_kstat_bif_update(kstat_t *ksp, int flag)
1904 1903 {
1905 1904 struct acpi_drv_cbat_state *bp;
1906 1905 acpi_bif_t *bif;
1907 1906 acpi_drv_bif_kstat_t *kp;
1908 1907
1909 1908 if (flag == KSTAT_WRITE) {
1910 1909 return (EACCES);
1911 1910 }
1912 1911
1913 1912 bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
1914 1913 mutex_enter(&acpi_drv_mutex);
1915 1914
1916 1915 if (acpi_drv_cbat_present(bp) <= 0) {
1917 1916 mutex_exit(&acpi_drv_mutex);
1918 1917 return (ENXIO);
1919 1918 }
1920 1919
1921 1920 bzero(&bif, sizeof (bif));
1922 1921 if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) {
1923 1922 mutex_exit(&acpi_drv_mutex);
1924 1923 return (ENXIO);
1925 1924 }
1926 1925
1927 1926 bif = &bp->bif_cache;
1928 1927 kp = &acpi_drv_bif_kstat;
1929 1928
1930 1929 /* Update BIF */
1931 1930 kp->acpi_drv_bif_unit.value.ui32 = bif->bif_unit;
1932 1931 kp->acpi_drv_bif_design_cap.value.ui32 = bif->bif_design_cap;
1933 1932 kp->acpi_drv_bif_last_cap.value.ui32 = bif->bif_last_cap;
1934 1933 kp->acpi_drv_bif_tech.value.ui32 = bif->bif_tech;
1935 1934 kp->acpi_drv_bif_voltage.value.ui32 = bif->bif_voltage;
1936 1935 kp->acpi_drv_bif_warn_cap.value.ui32 = bif->bif_warn_cap;
1937 1936 kp->acpi_drv_bif_low_cap.value.ui32 = bif->bif_low_cap;
1938 1937 kp->acpi_drv_bif_gran1_cap.value.ui32 = bif->bif_gran1_cap;
1939 1938 kp->acpi_drv_bif_gran2_cap.value.ui32 = bif->bif_gran2_cap;
1940 1939
1941 1940 kstat_named_setstr(&kp->acpi_drv_bif_model, bif->bif_model);
1942 1941 kstat_named_setstr(&kp->acpi_drv_bif_serial, bif->bif_serial);
1943 1942 kstat_named_setstr(&kp->acpi_drv_bif_type, bif->bif_type);
1944 1943 kstat_named_setstr(&kp->acpi_drv_bif_oem_info, bif->bif_oem_info);
1945 1944
1946 1945 mutex_exit(&acpi_drv_mutex);
1947 1946 return (0);
1948 1947 }
1949 1948
1950 1949 static int
1951 1950 acpi_drv_kstat_bst_update(kstat_t *ksp, int flag)
1952 1951 {
1953 1952 struct acpi_drv_cbat_state *bp;
1954 1953 acpi_bst_t *bst;
1955 1954 acpi_drv_bst_kstat_t *kp;
1956 1955
1957 1956 if (flag == KSTAT_WRITE) {
1958 1957 return (EACCES);
1959 1958 }
1960 1959
1961 1960 bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
1962 1961 mutex_enter(&acpi_drv_mutex);
1963 1962
1964 1963 if (acpi_drv_cbat_present(bp) <= 0) {
1965 1964 mutex_exit(&acpi_drv_mutex);
1966 1965 return (ENXIO);
1967 1966 }
1968 1967
1969 1968 bzero(&bst, sizeof (bst));
1970 1969 if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) {
1971 1970 mutex_exit(&acpi_drv_mutex);
1972 1971 return (ENXIO);
1973 1972 }
1974 1973
1975 1974 bst = &bp->bst_cache;
1976 1975 kp = &acpi_drv_bst_kstat;
1977 1976
1978 1977 /* Update BST */
1979 1978 kp->acpi_drv_bst_state.value.ui32 = bst->bst_state;
1980 1979 kp->acpi_drv_bst_rate.value.ui32 = bst->bst_rate;
1981 1980 kp->acpi_drv_bst_rem_cap.value.ui32 = bst->bst_rem_cap;
1982 1981 kp->acpi_drv_bst_voltage.value.ui32 = bst->bst_voltage;
1983 1982
1984 1983 mutex_exit(&acpi_drv_mutex);
1985 1984 return (0);
1986 1985 }
1987 1986
1988 1987 static int
1989 1988 acpi_drv_kstat_init(void)
1990 1989 {
1991 1990 /*
1992 1991 * Allocate, initialize and install powerstatus and
1993 1992 * supported_battery_count kstat.
1994 1993 */
1995 1994 acpi_drv_power_ksp = kstat_create(ACPI_DRV_NAME, 0,
1996 1995 ACPI_DRV_POWER_KSTAT_NAME, "misc",
1997 1996 KSTAT_TYPE_NAMED,
1998 1997 sizeof (acpi_drv_power_kstat) / sizeof (kstat_named_t),
1999 1998 KSTAT_FLAG_VIRTUAL);
2000 1999 if (acpi_drv_power_ksp == NULL) {
2001 2000 ACPI_DRV_DBG(CE_WARN, NULL,
2002 2001 "kstat_create(%s) fail", ACPI_DRV_POWER_KSTAT_NAME);
2003 2002 return (ACPI_DRV_ERR);
2004 2003 }
2005 2004
2006 2005 acpi_drv_power_ksp->ks_data = &acpi_drv_power_kstat;
2007 2006 acpi_drv_power_ksp->ks_update = acpi_drv_kstat_power_update;
2008 2007 acpi_drv_power_ksp->ks_data_size += MAXNAMELEN;
2009 2008 kstat_install(acpi_drv_power_ksp);
2010 2009
2011 2010 /*
2012 2011 * Allocate, initialize and install battery_capacity_warning kstat.
2013 2012 */
2014 2013 acpi_drv_warn_ksp = kstat_create(ACPI_DRV_NAME, 0,
2015 2014 ACPI_DRV_BTWARN_KSTAT_NAME, "misc",
2016 2015 KSTAT_TYPE_NAMED,
2017 2016 sizeof (acpi_drv_warn_kstat) / sizeof (kstat_named_t),
2018 2017 KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
2019 2018 if (acpi_drv_warn_ksp == NULL) {
2020 2019 ACPI_DRV_DBG(CE_WARN, NULL,
2021 2020 "kstat_create(%s) fail", ACPI_DRV_BTWARN_KSTAT_NAME);
2022 2021 return (ACPI_DRV_ERR);
2023 2022 }
2024 2023
2025 2024 acpi_drv_warn_ksp->ks_data = &acpi_drv_warn_kstat;
2026 2025 acpi_drv_warn_ksp->ks_update = acpi_drv_kstat_warn_update;
2027 2026 kstat_install(acpi_drv_warn_ksp);
2028 2027
2029 2028 return (ACPI_DRV_OK);
2030 2029 }
2031 2030
2032 2031 static void
2033 2032 acpi_drv_kstat_fini()
2034 2033 {
2035 2034 struct acpi_drv_cbat_state *bp;
2036 2035
2037 2036 if (acpi_drv_power_ksp != NULL) {
2038 2037 kstat_delete(acpi_drv_power_ksp);
2039 2038 }
2040 2039 if (acpi_drv_warn_ksp != NULL) {
2041 2040 kstat_delete(acpi_drv_warn_ksp);
2042 2041 }
2043 2042 for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
2044 2043 bp++) {
2045 2044 if (bp->dev.valid) {
2046 2045 if (bp->bat_bif_ksp != NULL) {
2047 2046 kstat_delete(bp->bat_bif_ksp);
2048 2047 }
2049 2048 if (bp->bat_bst_ksp != NULL) {
2050 2049 kstat_delete(bp->bat_bst_ksp);
2051 2050 }
2052 2051 }
2053 2052 }
2054 2053 }
2055 2054
2056 2055 int
2057 2056 acpi_drv_set_int(ACPI_HANDLE dev, char *method, uint32_t aint)
2058 2057 {
2059 2058 ACPI_OBJECT_LIST al;
2060 2059 ACPI_OBJECT ao;
2061 2060
2062 2061 al.Pointer = &ao;
2063 2062 al.Count = 1;
2064 2063 ao.Type = ACPI_TYPE_INTEGER;
2065 2064 ao.Integer.Value = aint;
2066 2065 return (AcpiEvaluateObject(dev, method, &al, NULL));
2067 2066 }
2068 2067
2069 2068 int
2070 2069 acpi_drv_dev_init(struct acpi_drv_dev *p)
2071 2070 {
2072 2071 ACPI_DEVICE_INFO *info;
2073 2072 ACPI_STATUS ret;
2074 2073
2075 2074 ASSERT(p != NULL && p->hdl != NULL);
2076 2075
2077 2076 p->valid = 0;
2078 2077
2079 2078 /* Info size is variable depending on existance of _CID */
2080 2079 ret = AcpiGetObjectInfo(p->hdl, &info);
2081 2080 if (ACPI_FAILURE(ret)) {
2082 2081 ACPI_DRV_DBG(CE_WARN, NULL,
2083 2082 "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
2084 2083 return (ACPI_DRV_ERR);
2085 2084 }
2086 2085
2087 2086 if ((info->Valid & ACPI_VALID_HID) == 0) {
2088 2087 ACPI_DRV_DBG(CE_WARN, NULL,
2089 2088 "!AcpiGetObjectInfo(): _HID not available");
2090 2089 p->hid[0] = 0;
2091 2090 } else {
2092 2091 (void) strlcpy(p->hid, info->HardwareId.String, ID_LEN);
2093 2092 }
2094 2093
2095 2094 /*
2096 2095 * This object is optional, but is required when the device
2097 2096 * has no other way to report a persistent unique device ID.
2098 2097 */
2099 2098 if ((info->Valid & ACPI_VALID_UID) == 0) {
2100 2099 ACPI_DRV_DBG(CE_WARN, NULL,
2101 2100 "!AcpiGetObjectInfo(): _UID not available");
2102 2101 /* Use 0 as the default _UID */
2103 2102 p->uid[0] = 0;
2104 2103 } else {
2105 2104 (void) strlcpy(p->uid, info->UniqueId.String, ID_LEN);
2106 2105 }
2107 2106
2108 2107 if (info->Valid & ACPI_VALID_ADR) {
2109 2108 p->valid = 1;
2110 2109 p->type = ACPI_DRV_TYPE_HOTKEY;
2111 2110 }
2112 2111
2113 2112 AcpiOsFree(info);
2114 2113
2115 2114 return (ACPI_DRV_OK);
2116 2115 }
↓ open down ↓ |
1788 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX