226 lines
4.5 KiB
C
226 lines
4.5 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (C) Microsoft Corporation, 1990 - 1999
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
stop.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This is the NT SCSI port driver. This file contains the initialization
|
|||
|
code.
|
|||
|
|
|||
|
Authors:
|
|||
|
|
|||
|
Mike Glass
|
|||
|
Jeff Havens
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
kernel mode only
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
This module is a driver dll for scsi miniports.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "port.h"
|
|||
|
|
|||
|
typedef struct _SP_STOP_DEVICE_CONTEXT {
|
|||
|
OUT NTSTATUS Status;
|
|||
|
IN KEVENT Event;
|
|||
|
} SP_STOP_DEVICE_CONTEXT, *PSP_STOP_DEVICE_CONTEXT;
|
|||
|
|
|||
|
VOID
|
|||
|
SpCallHwStopAdapter(
|
|||
|
IN PDEVICE_OBJECT Adapter
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SpCallHwStopAdapterSynchronized(
|
|||
|
IN PADAPTER_EXTENSION AdapterExtension
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
SpDeviceStoppedCompletion(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN NTSTATUS Status,
|
|||
|
IN PSP_STOP_DEVICE_CONTEXT Context
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, ScsiPortStopLogicalUnit)
|
|||
|
#pragma alloc_text(PAGE, ScsiPortStopAdapter)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ScsiPortStopLogicalUnit(
|
|||
|
IN PLOGICAL_UNIT_EXTENSION LogicalUnit
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will lock the queue for the given logical unit to make sure
|
|||
|
that all request processing for this device is stopped. It will clear
|
|||
|
the IsStarted flag once the queue has been locked successfully. This will
|
|||
|
keep any other requests from being processed until a start has been
|
|||
|
received.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LogicalUnit - the logical unit to be started.
|
|||
|
|
|||
|
Irp - the stop request
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
status
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
SP_STOP_DEVICE_CONTEXT context;
|
|||
|
|
|||
|
NTSTATUS status = STATUS_SUCCESS;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if(LogicalUnit->CommonExtension.CurrentPnpState == IRP_MN_STOP_DEVICE) {
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
KeInitializeEvent(&(context.Event), SynchronizationEvent, FALSE);
|
|||
|
|
|||
|
status = SpEnableDisableLogicalUnit(LogicalUnit,
|
|||
|
FALSE,
|
|||
|
SpDeviceStoppedCompletion,
|
|||
|
&context);
|
|||
|
|
|||
|
KeWaitForSingleObject(&(context.Event),
|
|||
|
Executive,
|
|||
|
KernelMode,
|
|||
|
FALSE,
|
|||
|
NULL);
|
|||
|
|
|||
|
return context.Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SpDeviceStoppedCompletion(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN NTSTATUS Status,
|
|||
|
IN PSP_STOP_DEVICE_CONTEXT Context
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
Context->Status = Status;
|
|||
|
KeSetEvent(&(Context->Event), IO_NO_INCREMENT, FALSE);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ScsiPortStopAdapter(
|
|||
|
IN PDEVICE_OBJECT Adapter,
|
|||
|
IN PIRP StopRequest
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will stop an adapter and release it's io and interrupt
|
|||
|
resources. Pool allocations will not be freed, nor will the various
|
|||
|
miniport extensions.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Adapter - the device object for the adapter.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
status
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PADAPTER_EXTENSION adapterExtension = Adapter->DeviceExtension;
|
|||
|
PCOMMON_EXTENSION commonExtension = Adapter->DeviceExtension;
|
|||
|
|
|||
|
KEVENT event;
|
|||
|
|
|||
|
ULONG bin;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
ASSERT(adapterExtension->IsPnp);
|
|||
|
|
|||
|
//
|
|||
|
// If we're not started and we weren't started then there's no reason
|
|||
|
// to do any work when stopping.
|
|||
|
//
|
|||
|
|
|||
|
if((commonExtension->CurrentPnpState != IRP_MN_START_DEVICE) &&
|
|||
|
(commonExtension->PreviousPnpState != IRP_MN_START_DEVICE)) {
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Since all the children are stopped no requests can get through to the
|
|||
|
// adapter.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Send a request through the start-io routine to shut it down so that we
|
|||
|
// can start it back up later.
|
|||
|
//
|
|||
|
|
|||
|
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
|
|||
|
|
|||
|
StopRequest->IoStatus.Information = (ULONG_PTR) &event;
|
|||
|
|
|||
|
IoStartPacket(Adapter, StopRequest, 0, NULL);
|
|||
|
|
|||
|
KeWaitForSingleObject(&event,
|
|||
|
Executive,
|
|||
|
KernelMode,
|
|||
|
FALSE,
|
|||
|
NULL);
|
|||
|
|
|||
|
//
|
|||
|
// Call the miniport and get it to shut the adapter down.
|
|||
|
//
|
|||
|
|
|||
|
SpEnableDisableAdapter(adapterExtension, FALSE);
|
|||
|
|
|||
|
SpReleaseAdapterResources(adapterExtension, TRUE);
|
|||
|
|
|||
|
//
|
|||
|
// Zero out all the logical unit extensions.
|
|||
|
//
|
|||
|
|
|||
|
for(bin = 0; bin < NUMBER_LOGICAL_UNIT_BINS; bin++) {
|
|||
|
|
|||
|
PLOGICAL_UNIT_EXTENSION lun;
|
|||
|
|
|||
|
for(lun = adapterExtension->LogicalUnitList[bin].List;
|
|||
|
lun != NULL;
|
|||
|
lun = lun->NextLogicalUnit) {
|
|||
|
|
|||
|
RtlZeroMemory(lun->HwLogicalUnitExtension,
|
|||
|
adapterExtension->HwLogicalUnitExtensionSize);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|