Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

225 lines
4.5 KiB

/*++
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;
}