391 lines
9.2 KiB
C
391 lines
9.2 KiB
C
/*++
|
||
|
||
Copyright (c) 2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
processor.c
|
||
|
||
Abstract:
|
||
|
||
Processor support
|
||
|
||
Author:
|
||
|
||
Stephane Plante (splante)
|
||
|
||
Environment:
|
||
|
||
NT Kernel Model Driver only
|
||
|
||
Revision History:
|
||
|
||
Adapted for processors from buttons - JakeO (3-28-2000)
|
||
|
||
--*/
|
||
|
||
#include "pch.h"
|
||
#include "..\shared\acpictl.h"
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE, ACPIButtonStartDevice)
|
||
#endif
|
||
|
||
//
|
||
// Spinlock to protect the processor list
|
||
//
|
||
KSPIN_LOCK AcpiProcessorLock;
|
||
|
||
//
|
||
// List entry to store the thermal requests on
|
||
//
|
||
LIST_ENTRY AcpiProcessorList;
|
||
|
||
|
||
VOID
|
||
ACPIProcessorCancelRequest(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine cancels an outstanding processor request
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - the device which as a request being cancelled
|
||
Irp - the cancelling irp
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
KIRQL oldIrql;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
|
||
//
|
||
// We no longer need the cancel lock
|
||
//
|
||
IoReleaseCancelSpinLock( Irp->CancelIrql );
|
||
|
||
//
|
||
// We do however need the processor queue lock
|
||
//
|
||
KeAcquireSpinLock( &AcpiProcessorLock, &oldIrql );
|
||
|
||
//
|
||
// Remove the irp from the list that it is on
|
||
//
|
||
RemoveEntryList( &(Irp->Tail.Overlay.ListEntry) );
|
||
|
||
//
|
||
// Complete the irp now
|
||
//
|
||
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
}
|
||
|
||
BOOLEAN
|
||
ACPIProcessorCompletePendingIrps(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN ULONG ProcessorEvent
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine completes any pending processor irp sent to the specified
|
||
device object with the knowledge of which processor events have occured
|
||
|
||
The respective's processor's spinlock is held during this call
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - the target processor object
|
||
ProcessorEvent - the processor event that occured
|
||
|
||
Return Value:
|
||
|
||
TRUE if we completed an irp, FALSE, otherwise
|
||
|
||
--*/
|
||
{
|
||
BOOLEAN handledRequest = FALSE;
|
||
KIRQL oldIrql;
|
||
LIST_ENTRY doneList;
|
||
PDEVICE_OBJECT targetObject;
|
||
PIO_STACK_LOCATION irpSp;
|
||
PIRP irp;
|
||
PLIST_ENTRY listEntry;
|
||
PULONG resultBuffer;
|
||
|
||
//
|
||
// Initialize the list that will hold the requests that we need to
|
||
// complete
|
||
//
|
||
InitializeListHead( &doneList );
|
||
|
||
//
|
||
// Acquire the thermal lock so that we can pend these requests
|
||
//
|
||
KeAcquireSpinLock( &AcpiProcessorLock, &oldIrql );
|
||
|
||
//
|
||
// Walk the list of pending irps to see which ones match this extension
|
||
//
|
||
listEntry = AcpiProcessorList.Flink;
|
||
while (listEntry != &AcpiProcessorList) {
|
||
|
||
//
|
||
// Grab the irp from the list entry and update the next list entry
|
||
// that we will look at
|
||
//
|
||
irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
|
||
listEntry = listEntry->Flink;
|
||
|
||
//
|
||
// We need the current irp stack location
|
||
//
|
||
irpSp = IoGetCurrentIrpStackLocation( irp );
|
||
|
||
//
|
||
// what is the target object for this irp?
|
||
//
|
||
targetObject = irpSp->DeviceObject;
|
||
|
||
//
|
||
// Is this an irp that we care about? IE: does the does target mage
|
||
// the ones specified in this function
|
||
//
|
||
if (targetObject != DeviceObject) {
|
||
|
||
continue;
|
||
|
||
}
|
||
|
||
//
|
||
// At this point, we need to set the cancel routine to NULL because
|
||
// we are going to take care of this irp and we don't want it cancelled
|
||
// underneath us
|
||
//
|
||
if (IoSetCancelRoutine(irp, NULL) == NULL) {
|
||
|
||
//
|
||
// Cancel routine is active. stop processing this irp and move on
|
||
//
|
||
continue;
|
||
|
||
}
|
||
|
||
//
|
||
// set the data to return in the irp
|
||
//
|
||
resultBuffer = (PULONG) irp->AssociatedIrp.SystemBuffer;
|
||
*resultBuffer = ProcessorEvent;
|
||
irp->IoStatus.Status = STATUS_SUCCESS;
|
||
irp->IoStatus.Information = sizeof(ULONG);
|
||
|
||
//
|
||
// Remove the entry from the list
|
||
//
|
||
RemoveEntryList( &(irp->Tail.Overlay.ListEntry) );
|
||
|
||
//
|
||
// Insert the list onto the next queue, so that we know how to
|
||
// complete it later on
|
||
//
|
||
InsertTailList( &doneList, &(irp->Tail.Overlay.ListEntry) );
|
||
|
||
}
|
||
|
||
//
|
||
// At this point, droup our processor lock
|
||
//
|
||
KeReleaseSpinLock( &AcpiProcessorLock, oldIrql );
|
||
|
||
//
|
||
// Walk the list of irps to be completed
|
||
//
|
||
listEntry = doneList.Flink;
|
||
while (listEntry != &doneList) {
|
||
|
||
//
|
||
// Grab the irp from the list entry, update the next list entry
|
||
// that we will look at, and complete the request
|
||
//
|
||
irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
|
||
listEntry = listEntry->Flink;
|
||
RemoveEntryList( &(irp->Tail.Overlay.ListEntry) );
|
||
|
||
//
|
||
// Complete the request and remember that we handled a request
|
||
//
|
||
IoCompleteRequest( irp, IO_NO_INCREMENT );
|
||
handledRequest = TRUE;
|
||
|
||
|
||
}
|
||
|
||
//
|
||
// Return wether or not we handled a request
|
||
//
|
||
return handledRequest;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIProcessorDeviceControl (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Fixed processor device IOCTL handler
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - fixed feature processor device object
|
||
Irp - the ioctl request
|
||
|
||
Return Value:
|
||
|
||
Status
|
||
|
||
--*/
|
||
{
|
||
KIRQL oldIrql;
|
||
NTSTATUS status;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
PULONG resultBuffer;
|
||
OBJDATA data;
|
||
|
||
//
|
||
// Do not allow user mode IRPs in this routine
|
||
//
|
||
if (Irp->RequestorMode != KernelMode) {
|
||
|
||
return ACPIDispatchIrpInvalid( DeviceObject, Irp );
|
||
|
||
}
|
||
|
||
resultBuffer = (PULONG) Irp->AssociatedIrp.SystemBuffer;
|
||
|
||
switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
|
||
case IOCTL_GET_PROCESSOR_OBJ_INFO:
|
||
|
||
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
||
sizeof(IOCTL_GET_PROCESSOR_OBJ_INFO)) {
|
||
|
||
Irp->IoStatus.Status = status = STATUS_INFO_LENGTH_MISMATCH;
|
||
Irp->IoStatus.Information = 0;
|
||
|
||
} else {
|
||
|
||
status = AMLIEvalNameSpaceObject(deviceExtension->AcpiObject,
|
||
&data,
|
||
0,
|
||
NULL);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
ASSERT (data.dwDataType == OBJTYPE_PROCESSOR);
|
||
ASSERT (data.pbDataBuff != NULL);
|
||
|
||
(*(PPROCESSOR_OBJECT_INFO)resultBuffer).PhysicalID =
|
||
((PROCESSOROBJ *)data.pbDataBuff)->bApicID;
|
||
|
||
(*(PPROCESSOR_OBJECT_INFO)resultBuffer).PBlkAddress =
|
||
((PROCESSOROBJ *)data.pbDataBuff)->dwPBlk;
|
||
|
||
(*(PPROCESSOR_OBJECT_INFO)resultBuffer).PBlkLength =
|
||
(UCHAR)((PROCESSOROBJ *)data.pbDataBuff)->dwPBlkLen;
|
||
|
||
AMLIFreeDataBuffs(&data, 1);
|
||
|
||
status = STATUS_SUCCESS;
|
||
Irp->IoStatus.Information = sizeof(PROCESSOR_OBJECT_INFO);
|
||
|
||
}
|
||
|
||
Irp->IoStatus.Status = status;
|
||
}
|
||
|
||
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
||
break;
|
||
|
||
case IOCTL_ACPI_ASYNC_EVAL_METHOD:
|
||
|
||
//
|
||
// Handle this elsewhere
|
||
//
|
||
status = ACPIIoctlAsyncEvalControlMethod(
|
||
DeviceObject,
|
||
Irp,
|
||
irpSp
|
||
);
|
||
break;
|
||
|
||
case IOCTL_ACPI_EVAL_METHOD:
|
||
|
||
//
|
||
// Handle this elsewhere
|
||
//
|
||
status = ACPIIoctlEvalControlMethod(
|
||
DeviceObject,
|
||
Irp,
|
||
irpSp
|
||
);
|
||
break;
|
||
|
||
default:
|
||
|
||
status = STATUS_NOT_SUPPORTED;
|
||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
||
break;
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIProcessorStartDevice (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Start device function for the fixed feature power and sleep device
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - fixed feature processor device object
|
||
Irp - the start request
|
||
|
||
Return Value:
|
||
|
||
Status
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
|
||
Status = ACPIInternalSetDeviceInterface (
|
||
DeviceObject,
|
||
(LPGUID) &GUID_DEVICE_PROCESSOR
|
||
);
|
||
|
||
Irp->IoStatus.Status = Status;
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
return Status;
|
||
|
||
}
|