windows-nt/Source/XPSP1/NT/drivers/storage/iscsiprt/server/internal.c

251 lines
6 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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()