Driver for ACPI device ASL evaluation

Hi All,

I’m new to ACPI device driver. I need to implement a driver to evaluate the ASL method call. To confirm the communication between my driver and the ASL, I set a ASL method ‘RTN0’ which does nothing but return ‘0’. If I can successfully called ‘RTN0’ and get the ‘0’, then I can go ahead for next steps. However… :frowning:

The problem I met is
outputBuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE

And the data I get is of course useless. I guess the reason is the fdo in MyRead passed from I/O manager is not the one I thought. And a related finding is using WinDbg to check the device object, I can see the device object is “AttachedTo” “Device\ACPI” object, but from the dump of my driver, the “AttachedDevice” is null…

Any advise from anyone is high appreciated, my code is also attached in below.

-tftu


My current approach is quite simple, based on the normal WDM structure and the instruction of “ACPI Driver Interface in Windows Vista”, below are the codes(list the important piece only):

DriverEntry…
pDriverObject->DriverExtension->AddDevice = MyAddDevice;
pDriverObject->MajorFunction[IRP_MJ_READ] = MyRead;

MyAddDevice…
IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&(UNICODE_STRING)devName,
FILE_DEVICE_ACPI,
0,
FALSE,
&fdo);

NTSTATUS MyRead(IN PDEVICE_OBJECT fdo, IN PIRP Irp) {
Access_ASL_RTN0_Method(fdo);
return STATUS_SUCCESS;
}

NTSTATUS Access_ASL_RTN0_Method(IN PDEVICE_OBJECT Pdo) {
ACPI_EVAL_INPUT_BUFFER inputBuffer;
ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
NTSTATUS status;
PACPI_METHOD_ARGUMENT argument;

int i;

// Fill in the input data
inputBuffer.MethodNameAsUlong = (ULONG) (‘SMMG’);

inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;

// Send the request along
status = SendDownStreamIrp(
Pdo,
IOCTL_ACPI_EVAL_METHOD_EX,
&inputBuffer,
sizeof(ACPI_EVAL_INPUT_BUFFER),
&outputBuffer,
sizeof(ACPI_EVAL_OUTPUT_BUFFER)
);

for (i = 0; i <= 50; i++) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “(outputBuffer.Argument->Data)[%d] = (x=%x), (c=%c)\n”,i, (outputBuffer.Argument->Data)[i], (outputBuffer.Argument->Data)[i]));
}

if (!NT_SUCCESS(status)) {
return status;
}

// Sanity check the data
if ((outputBuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) ||
(outputBuffer.Count == 0)) {
return STATUS_ACPI_INVALID_DATA;
}

// Grab the argument
argument = outputBuffer.Argument;

return status;
}

NTSTATUS
SendDownStreamIrp(
IN PDEVICE_OBJECT Pdo,
IN ULONG Ioctl,
IN PVOID InputBuffer,
IN ULONG InputSize,
IN PVOID OutputBuffer,
IN ULONG OutputSize
)
{
IO_STATUS_BLOCK ioBlock;
KEVENT myIoctlEvent;
NTSTATUS status;
PIRP irp;
KSPIN_LOCK SpinLock;
KIRQL OldIrql;

// Initialize an event to wait on
KeInitializeEvent(&myIoctlEvent, SynchronizationEvent, FALSE);

// Build the request
irp = IoBuildDeviceIoControlRequest(
Ioctl,
Pdo,
InputBuffer,
InputSize,
OutputBuffer,
OutputSize,
FALSE,
&myIoctlEvent,
&ioBlock);

if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}

// Pass request to Pdo, always wait for completion routine
status = IoCallDriver(Pdo, irp);
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “IoCallDriver status = (%d)\n”, status));

if (status == STATUS_PENDING) {
// Wait for the IRP to be completed, and then return the status code
KeWaitForSingleObject(
&myIoctlEvent,
Executive,
KernelMode,
FALSE,
NULL);

status = ioBlock.Status;
}

return status;
}

What is the status that’s being returned from your call to IOCTL_ACPI_EVAL_METHOD_EX?

Why are you using IOCTL_ACPI_EVAL_METHOD_EX, and not IOCTL_ACPI_EVAL_METHOD? You only use the EX variant if your driver is not directly instantiated on the device that represents the namespace that implements the method you’re calling.

What are you specifying as the path for the method to evaluate?

Peter
OSR

I got STATUS_ACPI_INVALID_DATA, but the same if I use IOCTL_ACPI_EVAL_METHOD… but I thought the EX is for Windows Vista and later…
(http://msdn.microsoft.com/en-us/library/ff536139(v=vs.85).aspx)

and there is a typo in my post, in Access_ASL_RTN0_Method(IN PDEVICE_OBJECT Pdo),

it should be :
inputBuffer.MethodNameAsUlong = (ULONG) (‘0NTR’);

instead of
inputBuffer.MethodNameAsUlong = (ULONG) (‘SMMG’);

and thanks for Peter’s reply, I forgot to mention the hierarchy of the ASL:

Scope(_SB){
Device(AKDV){
… skip …
Method(RTN0,0){
Return(0)
}
… skip …
}

I don’t specify the path since I thought the fdo is pointing to device AKDV…

Again, thanks for any advise!

xxxxx@yahoo.com wrote:

and thanks for Peter’s reply, I forgot to mention the hierarchy of the ASL:

Scope(_SB){
Device(AKDV){
… skip …
Method(RTN0,0){
Return(0)
}
… skip …
}

I don’t specify the path since I thought the fdo is pointing to device AKDV…

Why? How is your driver loaded? What is the AKDV device? Does it
match the slot number of the device your INF matches?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

FIRST of all, it’s a serious mistake to be doing this driver in WDM. You REALLY want to write it using KMDF. You’ll avoid all SORTS of problems.

So, THAT’s the problem, right? NOT the fact that you get back something other than ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE. You’re sending a method invocation and that’s failing.

It’s only SUPPORTED on Vista and later. Unless you need to specify the path to a child device, don’t use the EX function.

Now, back to your original post:

Huh?? YOU create your FDO via IoCreateDevice (let me repeat again that you SHOULD be using KMDF for this).

What’s the name of the PDO in the devnode on which your driver is instantiated?

How are you installing your driver?

Peter
OSR

To Tim,

I use INF to load driver, AKDV is the device name in ASL and it’s a sensor,

Have no idea about the slot number of the device, could you please clarify it in detail?

Thanks a lot!

xxxxx@yahoo.com wrote:

I use INF to load driver, AKDV is the device name in ASL and it’s a sensor,

How is it connected?

Have no idea about the slot number of the device, could you please clarify it in detail?

The ACPI DSDT says there is an AKDV device, and describes exactly where
it is located (such PCI slot 6, USB root hub port 3 in host controller
#1, I/O port number, etc). In order for your driver to use the ACPI
information, the PDO you are driving must exactly match the location in
the ACPI description. Otherwise, ACPI won’t be able to match up your
device to the DSDT information.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

It directly connected to EC

Thanks for your explain, but how do I specify the location? I thought the PDO is representing the AKDV and then I can just pass the method call… Could I have a sample code for my reference?

-tftu

Hi! All,

Based on the instruction from the reply of this thread, I implement two KMDF versions of my driver, both are modified from the WDK samples and both no success

1st is from \general\toaster\kmdf\func\simple, the return NTSTATUS is 0xC0000010, STATUS_INVALID_DEVICE_REQUEST

2nd is from \general\portio\sys, return NTSTATUS is 0x00000103, STATUS_PENDING

Have also compared the Pdo by WinDbg, it’s exactly the same one, howcome it cannot return me the value I expected? Below is the data from WinDbg:

0: kd> !devobj 86927C10
Device object (86927c10) is for:
AKDV \Driver\ADRV99 DriverObject 867e0b10
Current Irp 00000000 RefCount 0 Type 00000032 Flags 00002044
Dacl 8acec138 DevExt 868d84c0 DevObjExt 86927ce0
ExtensionFlags (0000000000)
AttachedTo (Lower) 8608acb8 \Driver\ACPI
Device queue is not busy.

0: kd> !devstack 86927c10
!DevObj !DrvObj !DevExt ObjectName

86927c10 \Driver\ADRV99 868d84c0 AKDV
8608acb8 \Driver\ACPI 8605e270 00000058
!DevNode 86d506a8 :
DeviceInst is “ACPI\ADV0001\2&daba3ff&2”
ServiceName is “AK8975”

Can anyone advise me how to correctly accessed the device object? For this ACPI device, should I process any initialization or registration in my driver? And, now I’m confused by the instruction in MSDN, is the ACPI driver means ACPI.sys or the driver I’m developing? I have been stuck here for a month, any advise or hint is highly appreciated!

-tftu

You MIGHT want to try answering the questions I asked back on 30 June, for a start.

Peter
OSR

Dear Peter,

Many thanks for your advise since the beginning of this thread. I do modify my driver based on your instruction:

  1. use IOCTL_ACPI_EVAL_METHOD
  2. use KMDF to implement my driver

But regarding your below question:

[quote]
What’s the name of the PDO in the devnode on which your driver is instantiated?
<\quote>

I understand you want me to figure out the bug by tracing the Pdo, but since the Device Object “86927C10” in both WinDbg and KdPrint dump is exactly the same, I really need a further advise to refresh my thinking…

And the driver is installed by a INF file, I also need to learn how does the INF affect the Pdo, your kind advise is more than welcome…

Anyhow, I appreciate your support which has help me to think more and go further!

-tftu

Hi Peter, attached below is the INF I’m using, hope it’s helpful for your understanding on my driver.


;/*++
;Module Name:
;
; ADRV99KMDF_Func.INF
;
;Abstract:
; INF file for installing ADRV99 driver
;
;–*/

[Version]
Signature=“$WINDOWS NT$”
Class=Sensor
ClassGuid={5175d334-c371-4806-b3ba-71fd53c9258d}
Provider=%ADV%
DriverVer=07/05/2011,6.1.7600.16385
CatalogFile=KmdfSamples.cat

[DestinationDirs]
DefaultDestDir = 12

; ================= Class section =====================

[ClassInstall32]
Addreg=ADRV99ClassReg

[ADRV99ClassReg]
HKR,0,%ClassName%
HKR,Icon,-5
HKR,DeviceCharacteristics,0x10001,0x100 ;Use same security checks on relative opens
HKR,Security,“D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;LS)” ;Allow generic all access to system, built-in Admin, and Local System.
;This one overrides the security set by the driver

;*****************************************
; ADRV99 Device Install Section
;*****************************************

[Manufacturer]
%ADV%=ADV,NTx86

; For Win2K
[ADV]
; DisplayName Section DeviceId
; ----------- ------- --------
%ADRV99.DRVDESC%=ADRV99_Inst,ACPI\ADV0001

; For XP and later
[ADV.NTx86]
%ADRV99.DRVDESC%=ADRV99_Inst,ACPI\ADV0001

[ADRV99_Inst.NT]
CopyFiles=ADRV99.CopyFiles
AddProperty=DriverPropertiesSection

[ADRV99.CopyFiles]
ADRV99KMDF_Func.sys

;-------------- Service installation

[ADRV99_Inst.NT.Services]
AddService=ADRV99,%SPSVCINST_ASSOCSERVICE%,ADRV99_Service

[ADRV99_Service]
DisplayName = %ADRV99.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\ADRV99KMDF_Func.sys
LoadOrderGroup = Extended Base

[SourceDisksFiles]
ADRV99KMDF_Func.sys=1,

[SourceDisksNames]
1 = %DiskId1%,“”

;
;— ADRV99_Device WDF Coinstaller installation ------
;
[DestinationDirs]
ADRV99_Device_CoInstaller_CopyFiles = 11

[ADRV99_Device.NT.CoInstallers]
AddReg=ADRV99_Device_CoInstaller_AddReg
CopyFiles=ADRV99_Device_CoInstaller_CopyFiles

[ADRV99_Device_CoInstaller_AddReg]
HKR,CoInstallers32,0x00010000, “WdfCoInstaller01009.dll,WdfCoInstaller”

[ADRV99_Device_CoInstaller_CopyFiles]
WdfCoInstaller01009.dll

[SourceDisksFiles]
WdfCoInstaller01009.dll=1 ; make sure the number matches with SourceDisksNames

[ADRV99_Device.NT.Wdf]
KmdfService = ADRV99, ADRV99_wdfsect

[ADRV99_wdfsect]
KmdfLibraryVersion = 1.9

[DriverPropertiesSection]
DeviceIcon,“%SystemRoot%\system32\sensorscpl.dll,-1013”

[Strings]
SPSVCINST_ASSOCSERVICE= 0x00000002
ADV = “A sample device vendor”
ClassName = “ADRV99 Driver”
ADRV99.SVCDESC = “ADRV99 Service”
ADRV99.DRVDESC = “ADRV99KMDF_Func V20110705.02”
DiskId1 = “ADRV99 Install Disk”

Well, Mr. Tu, I’m glad you decided that my questions were finally worthy of a reply. You know, when you ask for help, and somebody asks a clarifying question in order to be better able to provide that help, it’s rather rude to ignore their question.

OK, so from the devstack dump:

0: kd> !devstack 86927c10
!DevObj !DrvObj !DevExt ObjectName
86927c10 \Driver\ADRV99 868d84c0 AKDV
8608acb8 \Driver\ACPI 8605e270 00000058
!DevNode 86d506a8 :
DeviceInst is “ACPI\ADV0001\2&daba3ff&2”
ServiceName is “AK8975”

We can see YOUR driver is named ADRV99 and your device object (which is your FDO) is named \Device\AKDV… can you please confirm – if it’s not too much trouble Mr. Tu – that what I just said is correct.

… and the device instance is ACPI\ADV0001.… which is the hardware ID for which you’re installing your driver, given your INF.

So… tell me more about what you’re doing in your driver, and how the driver acts. What callbacks are you getting? From what routine are you attempting to send the IOCT_ACPI_EVAL_METHOD call? Is this in response to an IOCTL you send from user mode?

In your EvtDriverDeviceAdd event processing callback you’re creating your FDO, right? And you’re getting the underlying (local, i.e. In-Stack) target from the returned WDFDEVICE handle by calling WdfDeviceGetIoTarget, right? And you’re sending the IOCTL_ACPI_EVAL_METHOD to that In-Stack target?

Sorry, I don’t understand the question.

“ACPI driver” means the ACPI driver. There’s only one of them. It’s ACPI.SYS – You’re driver is a driver for an APCI device.

Well, I’m glad we got you moved from WDM to KMDF, for one thing. That’ll make your life easier.

I suspect there’s a simple bug either in your driver or in your ASL. It could be either place, right? How confident are you about your ASL code? Do you have more experience with ASL than you have with Windows drivers?

Peter
OSR

Dear Peter,

I should say sorry again, I don’t know you have answered here before I replied your email…

Yes, they are correct

Yes, it’s correct too, and you can see it in [ADV.NTx86] section of my INF

I feel I’m not good in explaining, please let me attach my code as below:

#include “ADRV99KMDF_Func.h”
#include “acpiioct.h”

#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, ADRV99EvtDeviceAdd)
#pragma alloc_text (PAGE, ADRV99EvtIoRead)
#pragma alloc_text (PAGE, ADRV99EvtIoWrite)
#pragma alloc_text (PAGE, ADRV99EvtIoDeviceControl)
#endif

NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = STATUS_SUCCESS;
WDF_DRIVER_CONFIG config;

WDF_DRIVER_CONFIG_INIT(
&config,
ADRV99EvtDeviceAdd
);

status = WdfDriverCreate(
DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES, // Driver Attributes
&config, // Driver Config Info
WDF_NO_HANDLE
);

if (!NT_SUCCESS(status)) {
KdPrint( (“WdfDriverCreate failed with status 0x%x\n”, status));
}

return status;
}

NTSTATUS
ADRV99EvtDeviceAdd(
IN WDFDRIVER Driver,
IN PWDFDEVICE_INIT DeviceInit
)
{
NTSTATUS status = STATUS_SUCCESS;
PFDO_DATA fdoData;
WDF_IO_QUEUE_CONFIG queueConfig;
WDF_OBJECT_ATTRIBUTES fdoAttributes;
WDFDEVICE hDevice;
WDFQUEUE queue;

UNICODE_STRING ntDeviceName;
UNICODE_STRING win32DeviceName;

UNREFERENCED_PARAMETER(Driver);

PAGED_CODE();

WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DATA);

RtlInitUnicodeString(&ntDeviceName, GPD_DEVICE_NAME);

status = WdfDeviceInitAssignName(DeviceInit,&ntDeviceName);
if (!NT_SUCCESS(status)) {
return status;
}

WdfDeviceInitSetDeviceType(DeviceInit, GPD_TYPE);

status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &hDevice);
if (!NT_SUCCESS(status)) {
KdPrint( (“WdfDeviceCreate failed with status code 0x%x\n”, status));
return status;
}

RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);

status = WdfDeviceCreateSymbolicLink(
hDevice,
&win32DeviceName);

if (!NT_SUCCESS(status)) {
return status;
}

fdoData = ADRV99FdoGetData(hDevice);

status = WdfDeviceCreateDeviceInterface(
hDevice,
(LPGUID) &GUID_DEVINTERFACE_ADRV99,
NULL // ReferenceString
);

if (!NT_SUCCESS (status)) {
KdPrint( (“WdfDeviceCreateDeviceInterface failed 0x%x\n”, status));
return status;
}

WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel);

queueConfig.EvtIoRead = ADRV99EvtIoRead;
queueConfig.EvtIoWrite = ADRV99EvtIoWrite;
queueConfig.EvtIoDeviceControl = ADRV99EvtIoDeviceControl;

status = WdfIoQueueCreate(
hDevice,
&queueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&queue
);

if (!NT_SUCCESS (status)) {

KdPrint( (“WdfIoQueueCreate failed 0x%x\n”, status));
return status;
}

return status;
}

VOID
ADRV99EvtIoRead (
WDFQUEUE Queue,
WDFREQUEST Request,
size_t Length
)
{
NTSTATUS status;
ULONG_PTR bytesCopied =0;
WDFMEMORY memory;
//Add by Tu
WDFDEVICE device;
device = WdfIoQueueGetDevice(Queue);

UNREFERENCED_PARAMETER(Queue);
UNREFERENCED_PARAMETER(Length);

PAGED_CODE();

status = WdfRequestRetrieveOutputMemory(Request, &memory);
if(NT_SUCCESS(status) ) {

status = AccessADRV99_ASL_RTNO_Method(WdfDeviceWdmGetDeviceObject(device));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “AccessADRV99_ASL_RTNO_Method exec. Status = (%x)\n”, status));
}

WdfRequestCompleteWithInformation(Request, status, bytesCopied);
}

VOID
ADRV99EvtIoDeviceControl(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength,
IN ULONG IoControlCode
)
{
NTSTATUS status= STATUS_SUCCESS;

UNREFERENCED_PARAMETER(Queue);
UNREFERENCED_PARAMETER(OutputBufferLength);
UNREFERENCED_PARAMETER(InputBufferLength);

PAGED_CODE();

switch (IoControlCode) {

default:
status = STATUS_INVALID_DEVICE_REQUEST;
}

WdfRequestCompleteWithInformation(Request, status, (ULONG_PTR) 0);
}

//For testing only
NTSTATUS AccessADRV99_ASL_RTNO_Method(IN PDEVICE_OBJECT Pdo)
{
ACPI_EVAL_INPUT_BUFFER inputBuffer;
ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
NTSTATUS status;
PACPI_METHOD_ARGUMENT argument;
int i;

// Fill in the input data
inputBuffer.MethodNameAsUlong = (ULONG) (‘0NTR’);
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “inputBuffer.MethodNameAsUlong = %s\n”, inputBuffer.MethodNameAsUlong));
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;

KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “%s”, “***RTNO INPUT***\n”));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “inputBuffer = (%p)\n”, inputBuffer));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “inputBuffer.Signature = (%d)\n”, inputBuffer.Signature));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “inputBuffer.MethodNameAsUlong = (%d)\n”, inputBuffer.MethodNameAsUlong));
// Send the request along
status = SendDownStreamIrp(
Pdo,
//IOCTL_ACPI_EVAL_METHOD,
IOCTL_ACPI_ASYNC_EVAL_METHOD,
&inputBuffer,
sizeof(ACPI_EVAL_INPUT_BUFFER),
&outputBuffer,
sizeof(ACPI_EVAL_OUTPUT_BUFFER)
);
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “SendDownStreamIrp exec. Status = (%x)\n”, status));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “%s”, “***RTNO OUTPUT***\n”));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuffer.Signature = (%d)\n”, outputBuffer.Signature));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuffer.Length = (%d)\n”, outputBuffer.Length));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuffer.Count = (%d)\n”, outputBuffer.Count));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuffer.Argument = (%s)\n”, outputBuffer.Argument));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuffer.Argument->Type = (%d)\n”, outputBuffer.Argument->Type));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuffer.Argument->DataLength = (%d)\n”, outputBuffer.Argument->DataLength));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuffer.Argument->Argument = (%d)\n”, outputBuffer.Argument->Argument));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuffer.Argument->Data = (%s)\n”, outputBuffer.Argument->Data));
//KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “Size of (outputBuffer.Argument->Data) = (%d)\n”, sizeof(outputBuffer.Argument->Data)/sizeof(*(outputBuffer.Argument->Data))));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “Size of (outputBuffer.Argument->Data) = (%d)\n”, sizeof(outputBuffer.Argument->Data)));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “Size of (*outputBuffer.Argument->Data) = (%d)\n”, sizeof(*(outputBuffer.Argument->Data))));

for (i = 0; i <= 50; i++) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “(outputBuffer.Argument->Data)[%d] = (x=%x), (c=%c)\n”,i, (outputBuffer.Argument->Data)[i], (outputBuffer.Argument->Data)[i]));
}

if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “!NT_SUCCESS Status = (%x)\n”, status));
return status;
}

// Sanity check the data
if ((outputBuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) ||
(outputBuffer.Count == 0)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuffer.Signature = (%d)\n”, outputBuffer.Signature));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuffer.Count = (%d)\n”, outputBuffer.Count));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “%s”, “(outputBuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) || (outputBuffer.Count == 0) \n”));
return STATUS_ACPI_INVALID_DATA;
}

// Grab the argument
argument = outputBuffer.Argument;
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “argument = (%s)\n”, argument));

// Process argument
//.
//.
//.

KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “%s”, “Leave ADRV99WDM.cpp AccessADRV99_ASL_RTN0_Method \n”));
return status;
}

NTSTATUS
SendDownStreamIrp(
IN PDEVICE_OBJECT Pdo,
IN ULONG Ioctl,
IN PVOID InputBuffer,
IN ULONG InputSize,
IN PVOID OutputBuffer,
IN ULONG OutputSize
)
{
IO_STATUS_BLOCK ioBlock;
KEVENT myIoctlEvent;
NTSTATUS status;
PIRP irp;
KSPIN_LOCK SpinLock;
KIRQL OldIrql;

KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “%s”, “Enter ADRV99WDM SendDownStreamIrp\n”));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “Current IRQL(s) = (%s)\n”, KeGetCurrentIrql()));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “Current IRQL(d) = (%d)\n”, KeGetCurrentIrql()));
// Initialize an event to wait on
KeInitializeEvent(&myIoctlEvent, SynchronizationEvent, FALSE);

//KeInitializeSpinLock(&SpinLock);
//KeAcquireSpinLock (&SpinLock, &OldIrql);

//KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “After Acquire Spin Lock, Current IRQL(d) = (%d)\n”, KeGetCurrentIrql()));

// Build the request
irp = IoBuildDeviceIoControlRequest(
Ioctl,
Pdo,
InputBuffer,
InputSize,
OutputBuffer,
OutputSize,
FALSE,
&myIoctlEvent,
&ioBlock);

KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “irp->MdlAddress = (d, %d)\n”, irp->MdlAddress));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “irp->Flags = (d, %d)\n”, irp->Flags));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “irp->AssociatedIrp.MasterIrp = (s, %s)\n”, irp->AssociatedIrp.MasterIrp));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “irp->AssociatedIrp.SystemBuffer = (s, %s)\n”, irp->AssociatedIrp.SystemBuffer));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “irp->IoStatus = (d, %d)\n”, irp->IoStatus));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “irp->Tail.Overlay.ListEntry = (s, %s)\n”, irp->Tail.Overlay.ListEntry));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “ioBlock.Status = (d, %d)\n”, ioBlock.Status));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “ioBlock.Status = (x, %x)\n”, ioBlock.Status));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “ioBlock.Information = (d, %d)\n”, ioBlock.Information ));
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “ioBlock.Information = (x, %x)\n”, ioBlock.Information ));

if (!irp) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “%s”, “================ !irp ===============\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}

// Pass request to Pdo, always wait for completion routine
status = IoCallDriver(Pdo, irp);
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “IoCallDriver status = (%d)\n”, status));

if (status == STATUS_PENDING) {
// Wait for the IRP to be completed, and then return the status code
KeWaitForSingleObject(
&myIoctlEvent,
Executive,
KernelMode,
FALSE,
NULL);

status = ioBlock.Status;
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “ioBlock.Status = (%d)\n”, status));
}

//KeReleaseSpinLock (&SpinLock, OldIrql);

KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “%s”, “Leave ADRV99WDM SendDownStreamIrp\n”));

return status;
}

Highlight of the ADRV99KMDF_Func.h:

#define GPD_DEVICE_NAME L"\Device\AKDV"
#define GPD_TYPE FILE_DEVICE_ACPI
#define DOS_DEVICE_NAME L"\DosDevices\ADRV99"

//
// Io events callbacks.
//
EVT_WDF_IO_QUEUE_IO_READ ADRV99EvtIoRead;
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL ADRV99EvtIoDeviceControl;

And below is the highlight of my user mode testing code:

CreateFile(
“\\.\AKDV99”, // Open the Device "file
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);

The NTSTATUS I get is 0xC0000010, STATUS_INVALID_DEVICE_REQUEST…

Please ignore, this is just from my imagination…

As my colleague Vincent mentioned in his email, the ASL is maintained by different
team, we should confirm no bug in our driver before questioning their ASL…

Now is mid night here and I will leave office during Wed. ~ Sun. I’ll try my
best to check email and this thread in hotel, but please let me officially reply
on next Mon. And I hope you have read and accept the explain in my previous email.

Again, many thanks for your time and kind help!

-tftu

xxxxx@yahoo.com wrote:

Yes, they are correct

Yes, it’s correct too, and you can see it in [ADV.NTx86] section of my INF

OK, but just naming your device object “AKDV” is not enough to connect
to the ACPI DSDT. The information you want is in a section called AKDV
in the APCI DSDT, right? Are you 100% absolutely convinced that the
AKDV section is exposing the name ADV0001? Remember, this all gets
launched from the bottom up. The ACPI driver parses the DSDT. It looks
for names that need to be exposed as PDOs (such as your ADV0001). That
PDO will have access to the DSDT section that created it, and ONLY that
section. If the ADV0001 name comes from the AKDV section, the you
should be able to access the data. Otherwise, there is no access.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Mr. Tu… you’re still writing what’s probably the most important part of the code in WDM. But, in a QUICK read-through (and I *do* mean quick, I make it a policy not to carefully plow-through code that people post here on NTDEV), it LOOKS like you’re sending the request to the PDO.

This driver loads? It gets and processes requests that you send?

So, what are the symptoms you’re getting now? You said in your post that you’re getting STATUS_INVALID_DEVICE_REQUEST from your application… WHERE are you getting this… on CreateFile? THAT’s not a good sign, because KMDF will typically handle that request for you.

Peter
OSR

Hey Tim…

You wrote:

If his driver’s getting loaded using this:

[Manufacturer]
%ADV%=ADV,NTx86

; For Win2K
[ADV]
; DisplayName Section DeviceId
; ----------- ------- --------
%ADRV99.DRVDESC%=ADRV99_Inst,ACPI\ADV0001

Which he APPEARS to be saying it is… is that not a priori proof that he’s exposing the right device name and loading on the right PDO? Or are you concerned that he’s loading on a name “ADV0001” that’s defined in a DIFFERENT place in the DSDT?

>> Mr. Tu… Perhaps you should give us the complete ASL definition of your device, not one with the “…skip…” stuff left out. That would probably help us out here.

Peter
OSR

Dear Tim & Peter,

For the legal concern, please forgive me I can’t post the complete ASL, but below are the key piese for my questions (I think, pls correct me if you need more details…):

Scope(_SB){
Device(AKDV){
Name(_HID,“ADV0001”)
Method(_INI){
… skip …
}
Method(RTN0,0){
Return(0)
}
… skip …
}

Hope it’s helpful. and thank you for your continual help.

-tftu

Hi! Peter,

Thanks for your comment again!

Yes, the driver successfully loaded w/o complaint. And yes, it process request and trigger the ADRV99EvtIoRead method of my driver.

My current expectation for my driver is I can get NTSTATUS = 0 (SUCCESS) and a return value ‘0’ (ASL RTN0 return value)from the ACPI_EVAL_OUTPUT_BUFFER in method AccessADRV99_ASL_RTNO_Method of my driver, however, I get 0xC0000010, STATUS_INVALID_DEVICE_REQUEST from this driver which is based on KMDF and copy from WDK \general\toaster\kmdf\func\simple sample, but add AccessADRV99_ASL_RTNO_Method and SendDownStreamIrp. AccessADRV99_ASL_RTNO_Method is invoked by ADRV99EvtIoRead method which is the callback of EVT_WDF_IO_QUEUE_IO_READ.

Please kindly provide us your opinion. Thanks!

-tftu

VERY helpful, thanks. That’s all *I* needed to see.

Sorry… WHAT function call is getting a return status of STATUS_INVALID_DEVICE_REQUEST…

Peter
OSR