VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/DrvACPI.cpp@ 16211

Last change on this file since 16211 was 14710, checked in by vboxsync, 16 years ago

Devices-OSX: added ACPI power reporting (#3342)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 24.5 KB
Line 
1/* $Id: DrvACPI.cpp 14710 2008-11-27 15:13:46Z vboxsync $ */
2/** @file
3 * DrvACPI - ACPI Host Driver.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#define LOG_GROUP LOG_GROUP_DRV_ACPI
26
27#ifdef RT_OS_WINDOWS
28# include <windows.h>
29#endif
30
31#include <VBox/pdmdrv.h>
32#include <VBox/log.h>
33#include <iprt/assert.h>
34#include <iprt/string.h>
35
36#ifdef RT_OS_LINUX
37# include <iprt/string.h>
38# include <sys/types.h>
39# include <dirent.h>
40# include <stdio.h>
41#endif
42
43#ifdef RT_OS_DARWIN
44# include <Carbon/Carbon.h>
45# include <IOKit/ps/IOPowerSources.h>
46# include <IOKit/ps/IOPSKeys.h>
47#endif
48
49#include "Builtins.h"
50
51
52/*******************************************************************************
53* Structures and Typedefs *
54*******************************************************************************/
55/**
56 * ACPI driver instance data.
57 */
58typedef struct DRVACPI
59{
60 /** The ACPI interface. */
61 PDMIACPICONNECTOR IACPIConnector;
62 /** The ACPI port interface. */
63 PPDMIACPIPORT pPort;
64 /** Pointer to the driver instance. */
65 PPDMDRVINS pDrvIns;
66} DRVACPI, *PDRVACPI;
67
68
69/**
70 * Queries an interface to the driver.
71 *
72 * @returns Pointer to interface.
73 * @returns NULL if the interface was not supported by the driver.
74 * @param pInterface Pointer to this interface structure.
75 * @param enmInterface The requested interface identification.
76 * @thread Any thread.
77 */
78static DECLCALLBACK(void *) drvACPIQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
79{
80 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
81 PDRVACPI pThis = PDMINS_2_DATA(pDrvIns, PDRVACPI);
82 switch (enmInterface)
83 {
84 case PDMINTERFACE_BASE:
85 return &pDrvIns->IBase;
86 case PDMINTERFACE_ACPI_CONNECTOR:
87 return &pThis->IACPIConnector;
88 default:
89 return NULL;
90 }
91}
92
93/**
94 * Get the current power source of the host system.
95 *
96 * @returns status code
97 * @param pInterface Pointer to the interface structure containing the called function pointer.
98 * @param pPowerSource Pointer to the power source result variable.
99 */
100static DECLCALLBACK(int) drvACPIQueryPowerSource(PPDMIACPICONNECTOR pInterface,
101 PDMACPIPOWERSOURCE *pPowerSource)
102{
103#if defined(RT_OS_WINDOWS)
104 SYSTEM_POWER_STATUS powerStatus;
105 if (GetSystemPowerStatus(&powerStatus))
106 {
107 /* running on battery? */
108 if ( (powerStatus.ACLineStatus == 0)
109 || (powerStatus.ACLineStatus == 255)
110 && (powerStatus.BatteryFlag & 15))
111 {
112 *pPowerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
113 }
114 /* running on AC link? */
115 else if (powerStatus.ACLineStatus == 1)
116 {
117 *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
118 }
119 else
120 /* what the hell we're running on? */
121 {
122 *pPowerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
123 }
124 }
125 else
126 {
127 AssertMsgFailed(("Could not determine system power status, error: 0x%x\n",
128 GetLastError()));
129 *pPowerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
130 }
131#elif defined (RT_OS_LINUX) /* !RT_OS_WINDOWS */
132 DIR *dfd;
133 struct dirent *dp;
134 FILE *statusFile = NULL;
135 char buff[NAME_MAX+50];
136
137 /* start with no result */
138 *pPowerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
139
140 dfd = opendir("/proc/acpi/ac_adapter/");
141 if (dfd)
142 {
143 for (;;)
144 {
145 dp = readdir(dfd);
146 if (dp == 0)
147 break;
148 if (strcmp(dp->d_name, ".") == 0 ||
149 strcmp(dp->d_name, "..") == 0)
150 continue;
151 strcpy(buff, "/proc/acpi/ac_adapter/");
152 strcat(buff, dp->d_name);
153 strcat(buff, "/status");
154 statusFile = fopen(buff, "r");
155 /* there's another possible name for this file */
156 if (!statusFile)
157 {
158 strcpy(buff, "/proc/acpi/ac_adapter/");
159 strcat(buff, dp->d_name);
160 strcat(buff, "/state");
161 statusFile = fopen(buff, "r");
162 }
163 if (statusFile)
164 break;
165 }
166 closedir(dfd);
167 }
168
169 if (statusFile)
170 {
171 for (;;)
172 {
173 char buff2[1024];
174 if (fgets(buff2, sizeof(buff), statusFile) == NULL)
175 break;
176 if (strstr(buff2, "Status:") != NULL ||
177 strstr(buff2, "state:") != NULL)
178 {
179 if (strstr(buff2, "on-line") != NULL)
180 *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
181 else
182 *pPowerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
183 }
184 }
185 fclose(statusFile);
186 }
187#elif defined (RT_OS_DARWIN) /* !RT_OS_LINUX */
188 *pPowerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
189
190 CFTypeRef pBlob = IOPSCopyPowerSourcesInfo();
191 CFArrayRef pSources = IOPSCopyPowerSourcesList(pBlob);
192
193 CFDictionaryRef pSource = NULL;
194 const void *psValue;
195 bool result;
196
197 if (CFArrayGetCount(pSources) > 0)
198 {
199 for(int i = 0; i < CFArrayGetCount(pSources); ++i)
200 {
201 pSource = IOPSGetPowerSourceDescription(pBlob, CFArrayGetValueAtIndex(pSources, i));
202 /* If the source is empty skip over to the next one. */
203 if(!pSource)
204 continue;
205 /* Skip all power sources which are currently not present like a
206 * second battery. */
207 if (CFDictionaryGetValue(pSource, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse)
208 continue;
209 /* Only internal power types are of interest. */
210 result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTransportTypeKey), &psValue);
211 if (result &&
212 CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSInternalType), 0) == kCFCompareEqualTo)
213 {
214 /* Check which power source we are connect on. */
215 result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSPowerSourceStateKey), &psValue);
216 if (result &&
217 CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo)
218 *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
219 else if (result &&
220 CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo)
221 *pPowerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
222 }
223 }
224 }
225 CFRelease(pBlob);
226 CFRelease(pSources);
227#else /* !RT_OS_DARWIN either - what could this be? */
228 *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
229#endif /* !RT_OS_WINDOWS */
230 return VINF_SUCCESS;
231}
232
233/**
234 * @copydoc PDMIACPICONNECTOR::pfnQueryBatteryStatus
235 */
236static DECLCALLBACK(int) drvACPIQueryBatteryStatus(PPDMIACPICONNECTOR pInterface, bool *pfPresent,
237 PPDMACPIBATCAPACITY penmRemainingCapacity,
238 PPDMACPIBATSTATE penmBatteryState,
239 uint32_t *pu32PresentRate)
240{
241 /* default return values for all architectures */
242 *pfPresent = false; /* no battery present */
243 *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGED;
244 *penmRemainingCapacity = PDM_ACPI_BAT_CAPACITY_UNKNOWN;
245 *pu32PresentRate = ~0; /* present rate is unknown */
246
247#if defined(RT_OS_WINDOWS)
248 SYSTEM_POWER_STATUS powerStatus;
249 if (GetSystemPowerStatus(&powerStatus))
250 {
251 /* 128 means no battery present */
252 *pfPresent = !(powerStatus.BatteryFlag & 128);
253 /* just forward the value directly */
254 *penmRemainingCapacity = (PDMACPIBATCAPACITY)powerStatus.BatteryLifePercent;
255 /* we assume that we are discharging the battery if we are not on-line and
256 * not charge the battery */
257 uint32_t uBs = PDM_ACPI_BAT_STATE_CHARGED;
258 if (powerStatus.BatteryFlag & 8)
259 uBs = PDM_ACPI_BAT_STATE_CHARGING;
260 else if (powerStatus.ACLineStatus == 0 || powerStatus.ACLineStatus == 255)
261 uBs = PDM_ACPI_BAT_STATE_DISCHARGING;
262 if (powerStatus.BatteryFlag & 4)
263 uBs |= PDM_ACPI_BAT_STATE_CRITICAL;
264 *penmBatteryState = (PDMACPIBATSTATE)uBs;
265 /* on Windows it is difficult to request the present charging/discharging rate */
266 }
267 else
268 {
269 AssertMsgFailed(("Could not determine system power status, error: 0x%x\n",
270 GetLastError()));
271 }
272#elif defined(RT_OS_LINUX)
273 DIR *dfd;
274 struct dirent *dp;
275 FILE *statusFile = NULL;
276 FILE *infoFile = NULL;
277 char buff[NAME_MAX+50];
278 /* the summed up maximum capacity */
279 int maxCapacityTotal = ~0;
280 /* the summed up total capacity */
281 int currentCapacityTotal = ~0;
282 int presentRate = 0;
283 int presentRateTotal = 0;
284 bool fBatteryPresent = false, fCharging=false, fDischarging=false, fCritical=false;
285
286 dfd = opendir("/proc/acpi/battery/");
287 if (dfd)
288 {
289 for (;;)
290 {
291 dp = readdir(dfd);
292 if (dp == 0)
293 break;
294 if (strcmp(dp->d_name, ".") == 0 ||
295 strcmp(dp->d_name, "..") == 0)
296 continue;
297 strcpy(buff, "/proc/acpi/battery/");
298 strcat(buff, dp->d_name);
299 strcat(buff, "/status");
300 statusFile = fopen(buff, "r");
301 /* there is a 2nd variant of that file */
302 if (!statusFile)
303 {
304 strcpy(buff, "/proc/acpi/battery/");
305 strcat(buff, dp->d_name);
306 strcat(buff, "/state");
307 statusFile = fopen(buff, "r");
308 }
309 strcpy(buff, "/proc/acpi/battery/");
310 strcat(buff, dp->d_name);
311 strcat(buff, "/info");
312 infoFile = fopen(buff, "r");
313 /* we need both files */
314 if (!statusFile || !infoFile)
315 {
316 if (statusFile)
317 fclose(statusFile);
318 if (infoFile)
319 fclose(infoFile);
320 break;
321 }
322
323 /* get 'present' status from the info file */
324 for (;;)
325 {
326 char buff2[1024];
327 if (fgets(buff2, sizeof(buff), infoFile) == NULL)
328 break;
329
330 if (strstr(buff2, "present:") != NULL)
331 {
332 if (strstr(buff2, "yes") != NULL)
333 fBatteryPresent = true;
334 }
335 }
336
337 /* move file pointer back to start of file */
338 fseek(infoFile, 0, SEEK_SET);
339
340 if (fBatteryPresent)
341 {
342 /* get the maximum capacity from the info file */
343 for (;;)
344 {
345 char buff2[1024];
346 int maxCapacity = ~0;
347 if (fgets(buff2, sizeof(buff), infoFile) == NULL)
348 break;
349 if (strstr(buff2, "last full capacity:") != NULL)
350 {
351 if (sscanf(buff2 + 19, "%d", &maxCapacity) <= 0)
352 maxCapacity = ~0;
353
354 /* did we get a valid capacity and it's the first value we got? */
355 if (maxCapacityTotal < 0 && maxCapacity > 0)
356 {
357 /* take this as the maximum capacity */
358 maxCapacityTotal = maxCapacity;
359 }
360 else
361 {
362 /* sum up the maximum capacity */
363 if (maxCapacityTotal > 0 && maxCapacity > 0)
364 maxCapacityTotal += maxCapacity;
365 }
366 /* we got all we need */
367 break;
368 }
369 }
370
371 /* get the current capacity/state from the status file */
372 bool gotRemainingCapacity=false, gotBatteryState=false,
373 gotCapacityState=false, gotPresentRate=false;
374 while (!gotRemainingCapacity || !gotBatteryState ||
375 !gotCapacityState || !gotPresentRate)
376 {
377 char buff2[1024];
378 int currentCapacity = ~0;
379 if (fgets(buff2, sizeof(buff), statusFile) == NULL)
380 break;
381 if (strstr(buff2, "remaining capacity:") != NULL)
382 {
383 if (sscanf(buff2 + 19, "%d", &currentCapacity) <= 0)
384 currentCapacity = ~0;
385
386 /* is this the first valid value we see? If so, take it! */
387 if (currentCapacityTotal < 0 && currentCapacity >= 0)
388 {
389 currentCapacityTotal = currentCapacity;
390 }
391 else
392 {
393 /* just sum up the current value */
394 if (currentCapacityTotal > 0 && currentCapacity > 0)
395 currentCapacityTotal += currentCapacity;
396 }
397 gotRemainingCapacity = true;
398 }
399 if (strstr(buff2, "charging state:") != NULL)
400 {
401 if (strstr(buff2 + 15, "discharging") != NULL)
402 fDischarging = true;
403 else if (strstr(buff2 + 15, "charging") != NULL)
404 fCharging = true;
405 gotBatteryState = true;
406 }
407 if (strstr(buff2, "capacity state:") != NULL)
408 {
409 if (strstr(buff2 + 15, "critical") != NULL)
410 fCritical = true;
411 gotCapacityState = true;
412 }
413 if (strstr(buff2, "present rate:") != NULL)
414 {
415 if (sscanf(buff2 + 13, "%d", &presentRate) <= 0)
416 presentRate = 0;
417 gotPresentRate = true;
418 }
419 }
420 }
421
422 if (presentRate)
423 {
424 if (fDischarging)
425 presentRateTotal -= presentRate;
426 else
427 presentRateTotal += presentRate;
428 }
429
430 if (statusFile)
431 fclose(statusFile);
432 if (infoFile)
433 fclose(infoFile);
434
435 }
436 closedir(dfd);
437 }
438
439 *pfPresent = fBatteryPresent;
440
441 /* charging/discharging bits are mutual exclusive */
442 uint32_t uBs = PDM_ACPI_BAT_STATE_CHARGED;
443 if (fDischarging)
444 uBs = PDM_ACPI_BAT_STATE_DISCHARGING;
445 else if (fCharging)
446 uBs = PDM_ACPI_BAT_STATE_CHARGING;
447 if (fCritical)
448 uBs |= PDM_ACPI_BAT_STATE_CRITICAL;
449 *penmBatteryState = (PDMACPIBATSTATE)uBs;
450
451 if (presentRateTotal < 0)
452 presentRateTotal = -presentRateTotal;
453
454 if (maxCapacityTotal > 0 && currentCapacityTotal > 0)
455 {
456 /* calculate the percentage */
457 *penmRemainingCapacity = (PDMACPIBATCAPACITY)(((float)currentCapacityTotal / (float)maxCapacityTotal)
458 * PDM_ACPI_BAT_CAPACITY_MAX);
459 *pu32PresentRate = (uint32_t)(((float)presentRateTotal / (float)maxCapacityTotal) * 1000);
460 }
461#elif defined(RT_OS_DARWIN)
462 CFTypeRef pBlob = IOPSCopyPowerSourcesInfo();
463 CFArrayRef pSources = IOPSCopyPowerSourcesList(pBlob);
464
465 CFDictionaryRef pSource = NULL;
466 const void *psValue;
467 bool result;
468
469 if (CFArrayGetCount(pSources) > 0)
470 {
471 for(int i = 0; i < CFArrayGetCount(pSources); ++i)
472 {
473 pSource = IOPSGetPowerSourceDescription(pBlob, CFArrayGetValueAtIndex(pSources, i));
474 /* If the source is empty skip over to the next one. */
475 if(!pSource)
476 continue;
477 /* Skip all power sources which are currently not present like a
478 * second battery. */
479 if (CFDictionaryGetValue(pSource, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse)
480 continue;
481 /* Only internal power types are of interest. */
482 result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTransportTypeKey), &psValue);
483 if (result &&
484 CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSInternalType), 0) == kCFCompareEqualTo)
485 {
486 PDMACPIPOWERSOURCE powerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
487 /* First check which power source we are connect on. */
488 result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSPowerSourceStateKey), &psValue);
489 if (result &&
490 CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo)
491 powerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
492 else if (result &&
493 CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo)
494 powerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
495
496 /* At this point the power source is present. */
497 *pfPresent = true;
498 *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGED;
499
500 int curCapacity = 0;
501 int maxCapacity = 1;
502 float remCapacity = 0.0f;
503
504 /* Fetch the current capacity value of the power source */
505 result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSCurrentCapacityKey), &psValue);
506 if (result)
507 CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity);
508 /* Fetch the maximum capacity value of the power source */
509 result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSMaxCapacityKey), &psValue);
510 if (result)
511 CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity);
512
513 /* Calculate the remaining capacity in percent */
514 remCapacity = ((float)curCapacity/(float)maxCapacity * PDM_ACPI_BAT_CAPACITY_MAX);
515 *penmRemainingCapacity = (PDMACPIBATCAPACITY)remCapacity;
516
517 if (powerSource == PDM_ACPI_POWER_SOURCE_BATTERY)
518 {
519 /* If we are on battery power we are discharging in every
520 * case */
521 *penmBatteryState = PDM_ACPI_BAT_STATE_DISCHARGING;
522 int timeToEmpty = -1;
523 /* Get the time till the battery source will be empty */
524 result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTimeToEmptyKey), &psValue);
525 if (result)
526 CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &timeToEmpty);
527 if (timeToEmpty != -1)
528 /* 0...1000 */
529 *pu32PresentRate = (uint32_t)roundf((remCapacity / ((float)timeToEmpty/60.0)) * 10.0);
530 }
531
532 if (powerSource == PDM_ACPI_POWER_SOURCE_OUTLET &&
533 CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsChargingKey), &psValue))
534 {
535 /* We are running on an AC power source, but we also have a
536 * battery power source present. */
537 if (CFBooleanGetValue((CFBooleanRef)psValue) > 0)
538 {
539 /* This means charging. */
540 *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGING;
541 int timeToFull = -1;
542 /* Get the time till the battery source will be charged */
543 result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTimeToFullChargeKey), &psValue);
544 if (result)
545 CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &timeToFull);
546 if (timeToFull != -1)
547 /* 0...1000 */
548 *pu32PresentRate = (uint32_t)roundf((100.0-(float)remCapacity) / ((float)timeToFull/60.0)) * 10.0;
549 }
550 }
551
552 /* Check for critical */
553 int criticalValue = 20;
554 result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSDeadWarnLevelKey), &psValue);
555 if (result)
556 CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &criticalValue);
557 if (remCapacity < criticalValue)
558 *penmBatteryState = (PDMACPIBATSTATE)(*penmBatteryState | PDM_ACPI_BAT_STATE_CRITICAL);
559 }
560 }
561 }
562 CFRelease(pBlob);
563 CFRelease(pSources);
564#endif /* RT_OS_DARWIN */
565 return VINF_SUCCESS;
566}
567
568/**
569 * Destruct a driver instance.
570 *
571 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
572 * resources can be freed correctly.
573 *
574 * @param pDrvIns The driver instance data.
575 */
576static DECLCALLBACK(void) drvACPIDestruct(PPDMDRVINS pDrvIns)
577{
578 LogFlow(("drvACPIDestruct\n"));
579}
580
581/**
582 * Construct an ACPI driver instance.
583 *
584 * @returns VBox status.
585 * @param pDrvIns The driver instance data.
586 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
587 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
588 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
589 * iInstance it's expected to be used a bit in this function.
590 */
591static DECLCALLBACK(int) drvACPIConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
592{
593 PDRVACPI pThis = PDMINS_2_DATA(pDrvIns, PDRVACPI);
594
595 /*
596 * Init the static parts.
597 */
598 pThis->pDrvIns = pDrvIns;
599 /* IBase */
600 pDrvIns->IBase.pfnQueryInterface = drvACPIQueryInterface;
601 /* IACPIConnector */
602 pThis->IACPIConnector.pfnQueryPowerSource = drvACPIQueryPowerSource;
603 pThis->IACPIConnector.pfnQueryBatteryStatus = drvACPIQueryBatteryStatus;
604
605 /*
606 * Validate the config.
607 */
608 if (!CFGMR3AreValuesValid(pCfgHandle, "\0"))
609 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
610
611 /*
612 * Check that no-one is attached to us.
613 */
614 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, NULL);
615 if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
616 {
617 AssertMsgFailed(("Configuration error: Cannot attach drivers to the ACPI driver!\n"));
618 return VERR_PDM_DRVINS_NO_ATTACH;
619 }
620
621 /*
622 * Query the ACPI port interface.
623 */
624 pThis->pPort = (PPDMIACPIPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase,
625 PDMINTERFACE_ACPI_PORT);
626 if (!pThis->pPort)
627 {
628 AssertMsgFailed(("Configuration error: "
629 "the above device/driver didn't export the ACPI port interface!\n"));
630 return VERR_PDM_MISSING_INTERFACE_ABOVE;
631 }
632
633 return VINF_SUCCESS;
634}
635
636
637/**
638 * ACPI driver registration record.
639 */
640const PDMDRVREG g_DrvACPI =
641{
642 /* u32Version */
643 PDM_DRVREG_VERSION,
644 /* szDriverName */
645 "ACPIHost",
646 /* pszDescription */
647 "ACPI Host Driver",
648 /* fFlags */
649 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
650 /* fClass. */
651 PDM_DRVREG_CLASS_ACPI,
652 /* cMaxInstances */
653 ~0,
654 /* cbInstance */
655 sizeof(DRVACPI),
656 /* pfnConstruct */
657 drvACPIConstruct,
658 /* pfnDestruct */
659 drvACPIDestruct,
660 /* pfnIOCtl */
661 NULL,
662 /* pfnPowerOn */
663 NULL,
664 /* pfnReset */
665 NULL,
666 /* pfnSuspend */
667 NULL,
668 /* pfnResume */
669 NULL,
670 /* pfnDetach */
671 NULL,
672 /* pfnPowerOff */
673 NULL
674};
675
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette