|
|
/*++
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()
|