+ PIRP Irp;
+ NTSTATUS Status;
+ KEVENT Event;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PAGED_CODE();
+
+ /* Initialize our wait event */
+ KeInitializeEvent(&Event, SynchronizationEvent, 0);
+
+ /* Allocate the IRP */
+ Irp = IoBuildDeviceIoControlRequest(IoControlCode,
+ DeviceObject,
+ InputBuffer,
+ InputBufferLength,
+ OutputBuffer,
+ OutputBufferLength,
+ 0,
+ &Event,
+ &IoStatusBlock);
+ if (!Irp)
+ {
+ /* No IRP, fail */
+ if (CmBattDebug & 0x4C)
+ DbgPrint("CmBattSendDownStreamIrp: Failed to allocate Irp\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Call ACPI */
+ if (CmBattDebug & 0x40)
+ DbgPrint("CmBattSendDownStreamIrp: Irp %x [Tid] %x\n",
+ Irp, KeGetCurrentThread());
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait for completion */
+ KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = Irp->IoStatus.Status;
+ }
+
+ /* Check if caller wanted output */
+ if (OutputBuffer)
+ {
+ /* Make sure it's valid ACPI output buffer */
+ if ((OutputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) ||
+ !(OutputBuffer->Count))
+ {
+ /* It isn't, so set failure code */
+ Status = STATUS_ACPI_INVALID_DATA;
+ }
+ }
+
+ /* Return status */
+ if (CmBattDebug & 0x40)
+ DbgPrint("CmBattSendDownStreamIrp: Irp %x completed %x! [Tid] %x\n",
+ Irp, Status, KeGetCurrentThread());
+ return Status;