[CMBATT]: Implement PnP handling. Only the ACPI-facing interface needs to be written...
[reactos.git] / reactos / drivers / bus / acpi / cmbatt / cmbatt.c
index 2b69d27..747ac9e 100644 (file)
@@ -19,26 +19,120 @@ UNICODE_STRING GlobalRegistryPath;
 KTIMER CmBattWakeDpcTimerObject;
 KDPC CmBattWakeDpcObject;
 PDEVICE_OBJECT AcAdapterPdo;
+LARGE_INTEGER CmBattWakeDpcDelay;
  
 /* FUNCTIONS ******************************************************************/
 
 VOID
 NTAPI
-CmBattPowerCallBack(PCMBATT_DEVICE_EXTENSION DeviceExtension,
-                    PVOID Argument1,
-                    PVOID Argument2)
+CmBattPowerCallBack(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
+                    IN ULONG Action,
+                    IN ULONG Value)
 {
-    UNIMPLEMENTED;
+    BOOLEAN Cancelled;
+    PDEVICE_OBJECT DeviceObject;
+    if (CmBattDebug & 0x10)
+        DbgPrint("CmBattPowerCallBack: action: %d, value: %d \n", Action, Value);
+    
+    /* Check if a transition is going to happen */
+    if (Action == PO_CB_SYSTEM_STATE_LOCK)
+    {
+        /* We have just re-entered S0: call the wake DPC in 10 seconds */
+        if (Value == 1)
+        {
+            if (CmBattDebug & 0x10)
+                DbgPrint("CmBattPowerCallBack: Calling CmBattWakeDpc after 10 seconds.\n");
+            Cancelled = KeSetTimer(&CmBattWakeDpcTimerObject, CmBattWakeDpcDelay, &CmBattWakeDpcObject);
+            if (CmBattDebug & 0x10)
+                DbgPrint("CmBattPowerCallBack: timerCanceled = %d.\n", Cancelled);
+        }
+        else if (Value == 0)
+        {
+            /* We are exiting the S0 state: loop all devices to set the delay flag */
+            if (CmBattDebug & 0x10)
+                DbgPrint("CmBattPowerCallBack: Delaying Notifications\n");
+            for (DeviceObject = DeviceExtension->DeviceObject;
+                 DeviceObject;
+                 DeviceObject = DeviceObject->NextDevice)
+            {
+                /* Set the delay flag */
+                DeviceExtension = DeviceObject->DeviceExtension;
+                DeviceExtension->DelayNotification = TRUE;
+            }
+        }
+        else if (CmBattDebug & 0x10)
+        {
+            /* Unknown value */
+            DbgPrint("CmBattPowerCallBack: unknown argument2 = %08x\n");
+        }
+    }
 }
 
 VOID
 NTAPI
-CmBattWakeDpc(PKDPC Dpc,
-              PCMBATT_DEVICE_EXTENSION FdoExtension,
-              PVOID SystemArgument1,
-              PVOID SystemArgument2)
+CmBattWakeDpc(IN PKDPC Dpc,
+              IN PCMBATT_DEVICE_EXTENSION FdoExtension,
+              IN PVOID SystemArgument1,
+              IN PVOID SystemArgument2)
 {
+    PDEVICE_OBJECT CurrentObject;
+    BOOLEAN AcNotify = FALSE;
+    PCMBATT_DEVICE_EXTENSION DeviceExtension;
+    ULONG ArFlag;
+    if (CmBattDebug & 2) DbgPrint("CmBattWakeDpc: Entered.\n");
+    
+    /* Loop all device objects */
+    for (CurrentObject = FdoExtension->DeviceObject;
+         CurrentObject;
+         CurrentObject = CurrentObject->NextDevice)
+    {
+        /* Turn delay flag off, we're back in S0 */
+        DeviceExtension = CurrentObject->DeviceExtension;
+        DeviceExtension->DelayNotification = 0;
+        
+        /* Check if this is an AC adapter */
+        if (DeviceExtension->FdoType == CmBattAcAdapter)
+        {
+            /* Was there a pending notify? */
+            if (DeviceExtension->ArFlag & CMBATT_AR_NOTIFY)
+            {
+                /* We'll send a notify on the next pass */
+                AcNotify = TRUE;
+                DeviceExtension->ArFlag = 0;
+                if (CmBattDebug & 0x20)
+                    DbgPrint("CmBattWakeDpc: AC adapter notified\n");
+            }
+        }
+    }
+
+    /* Loop the device objects again */
+    for (CurrentObject = FdoExtension->DeviceObject;
+         CurrentObject;
+         CurrentObject = CurrentObject->NextDevice)
+    {
+        /* Check if this is a battery */
+        DeviceExtension = CurrentObject->DeviceExtension;
+        if (DeviceExtension->FdoType == CmBattBattery)
+        {
+            /* Check what ARs are pending */
+            ArFlag = DeviceExtension->ArFlag;
+            if (CmBattDebug & 0x20)
+                DbgPrint("CmBattWakeDpc: Performing delayed ARs: %01x\n", ArFlag);
+
+            /* Insert notification, clear the lock value */
+            if (ArFlag & CMBATT_AR_INSERT) InterlockedExchange(&DeviceExtension->ArLockValue, 0);
+
+            /* Removal, clear the battery tag */
+            if (ArFlag & CMBATT_AR_REMOVE) DeviceExtension->Tag = 0;
 
+            /* Notification (or AC/DC adapter change from first pass above) */
+            if ((ArFlag & CMBATT_AR_NOTIFY) || (AcNotify))
+            {
+                /* Notify the class driver */
+                BatteryClassStatusNotify(DeviceExtension->ClassData);
+            }
+        }
+    }
 }
 
 VOID
@@ -112,7 +206,7 @@ CmBattNotifyHandler(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
     if (DeviceExtension->FdoType == CmBattBattery)
     {
         /* Reset the current trip point */
-        DeviceExtension->TripPointValue = 0xFFFFFFFF;
+        DeviceExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY;
         
         /* Check what ARs have to be done */
         ArFlag = DeviceExtension->ArFlag;
@@ -131,23 +225,20 @@ CmBattNotifyHandler(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
             BatteryClassStatusNotify(DeviceExtension->ClassData);
         }
     }
-    else
+    else if (DeviceExtension->ArFlag & CMBATT_AR_NOTIFY)
     {
-        /* The only known notification is AC/DC change */
-        if (DeviceExtension->ArFlag & CMBATT_AR_NOTIFY)
+        /* The only known notification is AC/DC change. Loop device objects. */
+        for (DeviceObject = DeviceExtension->FdoDeviceObject->DriverObject->DeviceObject;
+             DeviceObject;
+             DeviceObject = DeviceObject->NextDevice)
         {
-            for (DeviceObject = DeviceExtension->FdoDeviceObject->DriverObject->DeviceObject;
-                 DeviceObject;
-                 DeviceObject = DeviceObject->NextDevice)
+            /* Is this a battery? */
+            FdoExtension = DeviceObject->DeviceExtension;
+            if (FdoExtension->FdoType == CmBattBattery)
             {
-                /* Is this a battery? */
-                FdoExtension = DeviceObject->DeviceExtension;
-                if (FdoExtension->FdoType == CmBattBattery)
-                {
-                    /* Send a notification to the class driver */
-                    FdoExtension->NotifySent = TRUE;
-                    BatteryClassStatusNotify(FdoExtension->ClassData);
-                }
+                /* Send a notification to the class driver */
+                FdoExtension->NotifySent = TRUE;
+                BatteryClassStatusNotify(FdoExtension->ClassData);
             }
         }
     }
@@ -254,11 +345,188 @@ Complete:
 
 NTSTATUS
 NTAPI
-CmBattIoctl(PDEVICE_OBJECT DeviceObject,
-            PIRP Irp)
+CmBattIoctl(IN PDEVICE_OBJECT DeviceObject,
+            IN PIRP Irp)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+    NTSTATUS Status;
+    PIO_STACK_LOCATION IoStackLocation;
+    ULONG IoControlCode, OutputBufferLength, InputBufferLength;
+    PAGED_CODE();
+    if (CmBattDebug & 2) DbgPrint("CmBattIoctl\n");
+
+    /* Acquire the remove lock */
+    Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, 0);
+    if (!NT_SUCCESS(Status))
+    {
+        /* It's too late, fail */
+        Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
+        IofCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_DEVICE_REMOVED;
+    }
+    
+    /* There's nothing to do for an AC adapter */
+    if (DeviceExtension->FdoType == CmBattAcAdapter)
+    {
+        /* Pass it down, and release the remove lock */
+        IoSkipCurrentIrpStackLocation(Irp);
+        Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
+        IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
+        return Status;
+    }
+    
+    /* Send to class driver */
+    Status = BatteryClassIoctl(DeviceExtension->ClassData, Irp);
+    if (Status == STATUS_NOT_SUPPORTED)
+    {
+        /* Read IOCTL information from IRP stack */
+        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+        IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
+        OutputBufferLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
+        InputBufferLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
+        if (CmBattDebug & 4)
+            DbgPrint("CmBattIoctl: Received  Direct Access IOCTL %x\n", IoControlCode);
+    
+        /* Handle internal IOCTLs */
+        switch (IoControlCode)
+        {
+            case IOCTL_BATTERY_QUERY_UNIQUE_ID:
+            
+                /* Data is 4 bytes long */
+                if (OutputBufferLength == sizeof(ULONG))
+                {
+                    /* Query it */
+                    Status = CmBattGetUniqueId(DeviceExtension->PdoDeviceObject,
+                                               Irp->AssociatedIrp.SystemBuffer);
+                    if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(ULONG);
+                }
+                else
+                {
+                    /* Buffer size invalid */
+                    Status = STATUS_INVALID_BUFFER_SIZE;
+                }
+                break;
+            
+            case IOCTL_BATTERY_QUERY_STA:
+            
+                /* Data is 4 bytes long */
+                if (OutputBufferLength == sizeof(ULONG))
+                {
+                    /* Query it */
+                    Status = CmBattGetStaData(DeviceExtension->PdoDeviceObject,
+                                              Irp->AssociatedIrp.SystemBuffer);
+                    if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(ULONG);
+                }
+                else
+                {
+                    /* Buffer size invalid */
+                    Status = STATUS_INVALID_BUFFER_SIZE;
+                }
+                break;
+            
+            case IOCTL_BATTERY_QUERY_PSR:
+            
+                /* Data is 4 bytes long */
+                if (OutputBufferLength == sizeof(ULONG))
+                {
+                    /* Do we have an AC adapter? */
+                    if (AcAdapterPdo)
+                    {
+                        /* Query it */
+                        Status = CmBattGetPsrData(AcAdapterPdo,
+                                                  Irp->AssociatedIrp.SystemBuffer);
+                        if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(ULONG);
+                    }
+                    else
+                    {
+                        /* No adapter, just a battery, so fail */
+                        Status = STATUS_NO_SUCH_DEVICE;
+                    }
+                }
+                else
+                {
+                    /* Buffer size invalid */
+                    Status = STATUS_INVALID_BUFFER_SIZE;
+                }
+                break;
+                
+            case IOCTL_BATTERY_SET_TRIP_POINT:
+            
+                /* Data is 4 bytes long */
+                if (InputBufferLength == sizeof(ULONG))
+                {
+                    /* Query it */
+                    Status = CmBattSetTripPpoint(DeviceExtension,
+                                                 *(PULONG)Irp->AssociatedIrp.SystemBuffer);
+                    Irp->IoStatus.Information = 0;
+                }
+                else
+                {
+                    /* Buffer size invalid */
+                    Status = STATUS_INVALID_BUFFER_SIZE;
+                }
+                break;
+    
+            case IOCTL_BATTERY_QUERY_BIF:
+            
+                /* Data is 1060 bytes long */
+                if (OutputBufferLength == sizeof(ACPI_BIF_DATA))
+                {
+                    /* Query it */
+                    Status = CmBattGetBifData(DeviceExtension,
+                                              Irp->AssociatedIrp.SystemBuffer);
+                    if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(ACPI_BIF_DATA);
+                }
+                else
+                {
+                    /* Buffer size invalid */
+                    Status = STATUS_INVALID_BUFFER_SIZE;
+                }
+                break;
+            
+            case IOCTL_BATTERY_QUERY_BST:
+            
+                /* Data is 16 bytes long */
+                if (OutputBufferLength == sizeof(ACPI_BST_DATA))
+                {
+                    /* Query it */
+                    Status = CmBattGetBstData(DeviceExtension,
+                                              Irp->AssociatedIrp.SystemBuffer);
+                    if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(ACPI_BST_DATA);
+                }
+                else
+                {
+                    /* Buffer size invalid */
+                    Status = STATUS_INVALID_BUFFER_SIZE;
+                }
+                break;
+            
+            default:
+            
+                /* Unknown, let us pass it on to ACPI */
+                if (CmBattDebug & 0xC)
+                    DbgPrint("CmBattIoctl: Unknown IOCTL %x\n", IoControlCode);
+                break;
+        }
+        
+        /* Did someone pick it up? */
+        if (Status != STATUS_NOT_SUPPORTED)
+        {
+            /* Complete the request */
+            Irp->IoStatus.Status = Status;
+            IofCompleteRequest(Irp, IO_NO_INCREMENT);
+        }
+        else
+        {
+            /* Still unsupported, try ACPI */
+            IoSkipCurrentIrpStackLocation(Irp);
+            Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
+        }
+    }
+
+    /* Release the remove lock and return status */
+    IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
+    return Status;
 }
 
 NTSTATUS
@@ -298,7 +566,7 @@ CmBattQueryTag(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
                 
                 /* Reset trip point data */
                 DeviceExtension->TripPointOld = 0;
-                DeviceExtension->TripPointValue = 0xFFFFFFFF;
+                DeviceExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY;
                                 
                 /* Clear AR lock and set new interrupt time */
                 InterlockedExchange(&DeviceExtension->ArLockValue, 0);
@@ -322,20 +590,189 @@ CmBattQueryTag(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
 
 NTSTATUS
 NTAPI
-CmBattDisableStatusNotify(PCMBATT_DEVICE_EXTENSION DeviceExtension)
+CmBattDisableStatusNotify(IN PCMBATT_DEVICE_EXTENSION DeviceExtension)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PAGED_CODE();
+    if (CmBattDebug & 0xA) DbgPrint("CmBattDisableStatusNotify\n");
+
+    /* Do we have a trip point */
+    if (DeviceExtension->TripPointSet)
+    {
+        /* Is there a current value set? */
+        if (DeviceExtension->TripPointValue)
+        {
+            /* Reset it back to 0 */
+            DeviceExtension->TripPointValue = 0;
+            Status = CmBattSetTripPpoint(DeviceExtension, 0);
+            if (!NT_SUCCESS(Status))
+            {
+                /* If it failed, set unknown/invalid value */
+                DeviceExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY;
+                if (CmBattDebug & 8)
+                    DbgPrint("CmBattDisableStatusNotify: SetTripPoint failed - %x\n", Status);
+            }
+        }
+        else
+        {
+            /* No trip point set, so this is a successful no-op */
+            Status = STATUS_SUCCESS;
+        }
+    }
+    else
+    {
+        /* Nothing we can do */
+        Status = STATUS_OBJECT_NAME_NOT_FOUND;
+    }
+    
+    /* Return status */
+    return Status;
 }
 
 NTSTATUS
 NTAPI
-CmBattSetStatusNotify(PCMBATT_DEVICE_EXTENSION DeviceExtension,
-                      ULONG BatteryTag,
-                      PBATTERY_NOTIFY BatteryNotify)
+CmBattSetStatusNotify(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
+                      IN ULONG BatteryTag,
+                      IN PBATTERY_NOTIFY BatteryNotify)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    ACPI_BST_DATA BstData;
+    ULONG Capacity, NewTripPoint, TripPoint, DesignVoltage;
+    BOOLEAN Charging;
+    PAGED_CODE();
+    if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO))
+        DbgPrint("CmBattSetStatusNotify: Tag (%d) Target(0x%x)\n",
+                 BatteryTag, BatteryNotify->LowCapacity);
+    
+    /* Update any ACPI evaluations */    
+    Status = CmBattVerifyStaticInfo(DeviceExtension, BatteryTag);
+    if (!NT_SUCCESS(Status)) return Status;
+    
+    /* Trip point not supported, fail */
+    if (!DeviceExtension->TripPointSet) return STATUS_OBJECT_NAME_NOT_FOUND;
+    
+    /* Are both capacities known? */
+    if ((BatteryNotify->HighCapacity == BATTERY_UNKNOWN_CAPACITY) ||
+        (BatteryNotify->LowCapacity == BATTERY_UNKNOWN_CAPACITY))
+    {
+        /* We can't set trip points without these */
+        if (CmBattDebug & CMBATT_GENERIC_WARNING)
+            DbgPrint("CmBattSetStatusNotify: Failing request because of BATTERY_UNKNOWN_CAPACITY.\n");
+        return STATUS_NOT_SUPPORTED;
+    }
+    
+    /* Is the battery charging? */
+    Charging = DeviceExtension->BstData.State & ACPI_BATT_STAT_CHARGING;
+    if (Charging)
+    {
+        /* Then the trip point is when we hit the cap */
+        Capacity = BatteryNotify->HighCapacity;
+        NewTripPoint = BatteryNotify->HighCapacity;
+    }
+    else
+    {
+        /* Otherwise it's when we discharge to the bottom */
+        Capacity = BatteryNotify->LowCapacity;
+        NewTripPoint = BatteryNotify->LowCapacity;
+    }
+
+    /* Do we have data in Amps or Watts? */
+    if (DeviceExtension->BifData.PowerUnit == ACPI_BATT_POWER_UNIT_AMPS)
+    {
+        /* We need the voltage to do the conversion */
+        DesignVoltage = DeviceExtension->BifData.DesignVoltage;
+        if ((DesignVoltage != BATTERY_UNKNOWN_VOLTAGE) && (DesignVoltage))
+        {
+            /* Convert from mAh into Ah */
+            TripPoint = 1000 * NewTripPoint;
+            if (Charging)
+            {
+                /* Scale the high trip point */
+                NewTripPoint = (TripPoint + 500) / DesignVoltage + ((TripPoint + 500) % DesignVoltage != 0);
+            }
+            else
+            {
+                /* Scale the low trip point */
+                NewTripPoint = (TripPoint - 500) / DesignVoltage - ((TripPoint - 500) % DesignVoltage == 0);
+            }
+        }
+        else
+        {
+            /* Without knowing the voltage, Amps are not enough data on consumption */
+            Status = STATUS_NOT_SUPPORTED;
+            if (CmBattDebug & CMBATT_ACPI_WARNING)
+                DbgPrint("CmBattSetStatusNotify: Can't calculate BTP, DesignVoltage = 0x%08x\n",
+                        DesignVoltage);  
+        }
+    }
+    else if (Charging)
+    {
+        /* Make it trip just one past the charge cap */
+        ++NewTripPoint;
+    }
+    else if (NewTripPoint > 0)
+    {
+        /* Make it trip just one below the drain cap */
+        --NewTripPoint;
+    }
+
+    /* Do we actually have a new trip point? */
+    if (NewTripPoint == DeviceExtension->TripPointValue)
+    {
+        /* No, so there is no work to be done */
+        if (CmBattDebug & CMBATT_GENERIC_STATUS)
+            DbgPrint("CmBattSetStatusNotify: Keeping original setting: %X\n", DeviceExtension->TripPointValue);
+        return STATUS_SUCCESS;
+    }
+    
+    /* Set the trip point with ACPI and check for success */
+    DeviceExtension->TripPointValue = NewTripPoint;
+    Status = CmBattSetTripPpoint(DeviceExtension, NewTripPoint);
+    if (!(NewTripPoint) && (Capacity)) Status = STATUS_NOT_SUPPORTED;
+    if (!NT_SUCCESS(Status))
+    {
+        /* We failed to set the trip point, or there wasn't one settable */
+        DeviceExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY;
+        if (CmBattDebug & (CMBATT_GENERIC_WARNING | CMBATT_ACPI_WARNING))
+            DbgPrint("CmBattSetStatusNotify: SetTripPoint failed - %x\n", Status);
+        return Status;
+    }
+    
+    /* Read the new BST data to see the latest state */
+    Status = CmBattGetBstData(DeviceExtension, &BstData);
+    if (!NT_SUCCESS(Status))
+    {
+        /* We'll return failure to the caller */
+        if (CmBattDebug & (CMBATT_GENERIC_WARNING | CMBATT_ACPI_WARNING))
+            DbgPrint("CmBattSetStatusNotify: GetBstData - %x\n", Status);
+    }
+    else if ((Charging) && (BstData.RemainingCapacity >= NewTripPoint))
+    {
+        /* We are charging and our capacity is past the trip point, so trip now */
+        if (CmBattDebug & CMBATT_GENERIC_WARNING)
+            DbgPrint("CmBattSetStatusNotify: Trip point already crossed (1): TP = %08x, remaining capacity = %08x\n",
+                     NewTripPoint, BstData.RemainingCapacity);
+        CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS);
+    }
+    else if ((BstData.RemainingCapacity) && (Capacity))
+    {
+        /* We are discharging, and our capacity is below the trip point, trip now */
+        if (CmBattDebug & CMBATT_GENERIC_WARNING)
+            DbgPrint("CmBattSetStatusNotify: Trip point already crossed (1): TP = %08x, remaining capacity = %08x\n",
+                     NewTripPoint, BstData.RemainingCapacity);
+        CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS);        
+    }
+
+    /* All should've went well if we got here, unless BST failed... return! */
+    if (CmBattDebug & CMBATT_GENERIC_STATUS)
+          DbgPrint("CmBattSetStatusNotify: Want %X CurrentCap %X\n",
+                    Capacity, DeviceExtension->RemainingCapacity);
+    if (CmBattDebug & CMBATT_ACPI_WARNING)
+          DbgPrint("CmBattSetStatusNotify: Set to: [%#08lx][%#08lx][%#08lx] Status %x\n",
+                    BatteryNotify->PowerState,
+                    BatteryNotify->LowCapacity,
+                    BatteryNotify->HighCapacity);
+    return Status;
 }
 
 NTSTATUS
@@ -832,12 +1269,12 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
                  RegistryPath->Buffer);
     
     /* Setup the major dispatchers */
-    DriverObject->MajorFunction[0] = CmBattOpenClose;
-    DriverObject->MajorFunction[2] = CmBattOpenClose;
-    DriverObject->MajorFunction[14] = CmBattIoctl;
-    DriverObject->MajorFunction[22] = CmBattPowerDispatch;
-    DriverObject->MajorFunction[27] = CmBattPnpDispatch;
-    DriverObject->MajorFunction[23] = CmBattSystemControl;
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = CmBattOpenClose;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE] = CmBattOpenClose;
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CmBattIoctl;
+    DriverObject->MajorFunction[IRP_MJ_POWER] = CmBattPowerDispatch;
+    DriverObject->MajorFunction[IRP_MJ_PNP] = CmBattPnpDispatch;
+    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = CmBattSystemControl;
 
     /* And the unload routine */
     DriverObject->DriverUnload = CmBattUnload;