251 lines
6 KiB
C
251 lines
6 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (C) Microsoft Corporation, 2000
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
internal.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This file contains internal routines
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
kernel mode only
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "port.h"
|
|||
|
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, iScsiPortFdoDeviceControl)
|
|||
|
#pragma alloc_text(PAGE, iScsiPortFdoCreateClose)
|
|||
|
#endif // ALLOC_PRAGMA
|
|||
|
|
|||
|
extern PEPROCESS iScsiSystemProcess;
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
iScsiPortFdoDeviceControl(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
{
|
|||
|
PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
|
|||
|
PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
|||
|
PIO_STACK_LOCATION irpStack;
|
|||
|
NTSTATUS status = STATUS_SUCCESS;
|
|||
|
ULONG controlCode;
|
|||
|
ULONG isRemoved;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|||
|
controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
|
|||
|
|
|||
|
DebugPrint((3,
|
|||
|
"iSpFdoDeviceControl : DeviceObject %x, ControlCode 0x%08x\n",
|
|||
|
DeviceObject, controlCode));
|
|||
|
|
|||
|
isRemoved = iSpAcquireRemoveLock(DeviceObject, Irp);
|
|||
|
if (isRemoved) {
|
|||
|
|
|||
|
iSpReleaseRemoveLock(DeviceObject, Irp);
|
|||
|
|
|||
|
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
|
|||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|||
|
return STATUS_DEVICE_DOES_NOT_EXIST;
|
|||
|
}
|
|||
|
|
|||
|
switch (controlCode) {
|
|||
|
case IOCTL_ISCSI_SETUP_SERVER: {
|
|||
|
|
|||
|
if (commonExtension->IsServerNodeSetup) {
|
|||
|
DebugPrint((1, "Server node already setup\n"));
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
} else {
|
|||
|
iSpAttachProcess(iScsiSystemProcess);
|
|||
|
status = iSpStartNetwork(DeviceObject);
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
commonExtension->IsServerNodeSetup = TRUE;
|
|||
|
}
|
|||
|
iSpDetachProcess();
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case IOCTL_ISCSI_CLOSE_SERVER: {
|
|||
|
if ((commonExtension->IsServerNodeSetup) == FALSE) {
|
|||
|
DebugPrint((1, "Server node not setup\n"));
|
|||
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|||
|
} else {
|
|||
|
iSpAttachProcess(iScsiSystemProcess);
|
|||
|
status = iSpStopNetwork(DeviceObject);
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
commonExtension->IsServerNodeSetup = FALSE;
|
|||
|
}
|
|||
|
iSpDetachProcess();
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
default: {
|
|||
|
//
|
|||
|
// Control code that we don't understand. Just pass
|
|||
|
// it to the lower driver
|
|||
|
//
|
|||
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|||
|
iSpReleaseRemoveLock(DeviceObject, Irp);
|
|||
|
status = IoCallDriver(commonExtension->LowerDeviceObject,
|
|||
|
Irp);
|
|||
|
return status;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
} // switch (controlCode)
|
|||
|
|
|||
|
iSpReleaseRemoveLock(DeviceObject, Irp);
|
|||
|
Irp->IoStatus.Status = status;
|
|||
|
Irp->IoStatus.Information = 0L;
|
|||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
iScsiPortFdoCreateClose(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
{
|
|||
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|||
|
|
|||
|
DebugPrint((3, "iScsiPortFdoCreateClose : %s - DeviceObject %x, Irp %x\n",
|
|||
|
((irpStack->MajorFunction) == IRP_MJ_CREATE) ? "Create" : "Close",
|
|||
|
DeviceObject, Irp));
|
|||
|
|
|||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|||
|
Irp->IoStatus.Information = 0L;
|
|||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
iSpSetEvent(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp,
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
{
|
|||
|
KeSetEvent((PKEVENT)Context, 0, FALSE);
|
|||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
iScsiPortClaimDevice(
|
|||
|
IN PDEVICE_OBJECT LowerDeviceObject,
|
|||
|
IN BOOLEAN Release
|
|||
|
)
|
|||
|
{
|
|||
|
IO_STATUS_BLOCK ioStatus;
|
|||
|
PIRP irp;
|
|||
|
PIO_STACK_LOCATION irpStack;
|
|||
|
KEVENT event;
|
|||
|
NTSTATUS status;
|
|||
|
SCSI_REQUEST_BLOCK srb;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Clear the SRB fields.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
|
|||
|
|
|||
|
//
|
|||
|
// Write length to SRB.
|
|||
|
//
|
|||
|
|
|||
|
srb.Length = SCSI_REQUEST_BLOCK_SIZE;
|
|||
|
|
|||
|
srb.Function = Release ? SRB_FUNCTION_RELEASE_DEVICE :
|
|||
|
SRB_FUNCTION_CLAIM_DEVICE;
|
|||
|
|
|||
|
//
|
|||
|
// Set the event object to the unsignaled state.
|
|||
|
// It will be used to signal request completion
|
|||
|
//
|
|||
|
|
|||
|
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
|
|||
|
|
|||
|
//
|
|||
|
// Build synchronous request with no transfer.
|
|||
|
//
|
|||
|
|
|||
|
irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE,
|
|||
|
LowerDeviceObject,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
TRUE,
|
|||
|
&event,
|
|||
|
&ioStatus);
|
|||
|
|
|||
|
if (irp == NULL) {
|
|||
|
DebugPrint((1, "ClassClaimDevice: Can't allocate Irp\n"));
|
|||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
irpStack = IoGetNextIrpStackLocation(irp);
|
|||
|
|
|||
|
//
|
|||
|
// Save SRB address in next stack for port driver.
|
|||
|
//
|
|||
|
|
|||
|
irpStack->Parameters.Scsi.Srb = &srb;
|
|||
|
|
|||
|
//
|
|||
|
// Set up IRP Address.
|
|||
|
//
|
|||
|
|
|||
|
srb.OriginalRequest = irp;
|
|||
|
|
|||
|
//
|
|||
|
// Call the port driver with the request and wait for it to complete.
|
|||
|
//
|
|||
|
|
|||
|
status = IoCallDriver(LowerDeviceObject, irp);
|
|||
|
if (status == STATUS_PENDING) {
|
|||
|
|
|||
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
|
|||
|
status = ioStatus.Status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If this is a release request, then just decrement the reference count
|
|||
|
// and return. The status does not matter.
|
|||
|
//
|
|||
|
|
|||
|
if (Release) {
|
|||
|
|
|||
|
// ObDereferenceObject(LowerDeviceObject);
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT(srb.DataBuffer != NULL);
|
|||
|
|
|||
|
return status;
|
|||
|
} // end ClassClaimDevice()
|