|
|
/*++
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
/*
PISCSI_PDO_EXTENSION GetPdoExtension( IN PISCSI_FDO_EXTENSION fdoExtension ); */
NTSTATUS iScsiPortFdoDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension; PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); NTSTATUS status; ULONG isRemoved; ULONG ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
DebugPrint((1, "FDO DeviceControl - IO control code : 0x%08x\n", ioControlCode));
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 (ioControlCode) { case IOCTL_STORAGE_QUERY_PROPERTY: {
PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;
if(irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_PROPERTY_QUERY)) {
status = STATUS_INVALID_PARAMETER; break; }
//
// This routine will release the lock and complete the irp.
//
status = iScsiPortQueryProperty(DeviceObject, Irp); return status;
break; }
//
// Get adapter capabilities.
//
case IOCTL_SCSI_GET_CAPABILITIES: {
//
// If the output buffer is equal to the size of the a PVOID then just
// return a pointer to the buffer.
//
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(PVOID)) {
*((PVOID *)Irp->AssociatedIrp.SystemBuffer) = &fdoExtension->IoScsiCapabilities;
Irp->IoStatus.Information = sizeof(PVOID); status = STATUS_SUCCESS; break;
}
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(IO_SCSI_CAPABILITIES)) {
status = STATUS_BUFFER_TOO_SMALL; break; }
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &fdoExtension->IoScsiCapabilities, sizeof(IO_SCSI_CAPABILITIES));
Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES); status = STATUS_SUCCESS; break; }
case IOCTL_SCSI_PASS_THROUGH: case IOCTL_SCSI_PASS_THROUGH_DIRECT: {
status = STATUS_NOT_SUPPORTED; break; }
case IOCTL_SCSI_MINIPORT: {
status = STATUS_NOT_SUPPORTED; break; }
case IOCTL_SCSI_GET_DUMP_POINTERS: {
status = STATUS_NOT_SUPPORTED; break; }
case IOCTL_SCSI_RESCAN_BUS: case IOCTL_SCSI_GET_INQUIRY_DATA: { status = STATUS_NOT_SUPPORTED; break; }
default: { DebugPrint((1, "iScsiPortFdoDeviceControl: Unsupported IOCTL (%x)\n", ioControlCode));
status = STATUS_INVALID_DEVICE_REQUEST;
break; } } //
// Set status in Irp.
//
Irp->IoStatus.Status = status;
iSpReleaseRemoveLock(DeviceObject, Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
NTSTATUS iScsiPortFdoDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension; PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb; PISCSI_PDO_EXTENSION pdoExtension; NTSTATUS status; ULONG isRemoved; BOOLEAN sendCommandToServer = FALSE;
//
// Should never get here. All SCSI requests are handled
// by the PDO Dispatch routine
//
DebugPrint((0, "SRB function sent to FDO Dispatch\n"));
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
/*
isRemoved = iSpAcquireRemoveLock(DeviceObject, Irp);
if (isRemoved && !IS_CLEANUP_REQUEST(irpStack)) {
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
iSpReleaseRemoveLock(DeviceObject, Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_DEVICE_DOES_NOT_EXIST; }
if ((srb->Function) != SRB_FUNCTION_EXECUTE_SCSI) { DebugPrint((1, "FdoDispatch - SRB Function : 0x%x\n", srb->Function)); }
pdoExtension = GetPdoExtension(fdoExtension);
ASSERT(pdoExtension != NULL);
switch (srb->Function) {
case SRB_FUNCTION_SHUTDOWN: case SRB_FUNCTION_FLUSH: case SRB_FUNCTION_LOCK_QUEUE: case SRB_FUNCTION_UNLOCK_QUEUE: case SRB_FUNCTION_IO_CONTROL: case SRB_FUNCTION_WMI: { //
// We won't handle these functions on the client
// side for the timebeing.
//
status = STATUS_SUCCESS; srb->SrbStatus = SRB_STATUS_SUCCESS;
break; } case SRB_FUNCTION_SHUTDOWN: case SRB_FUNCTION_FLUSH: {
//
// Send SCSIOP_SYNCHRONIZE_CACHE command
// to flush the queue
//
srb->CdbLength = 10; srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
IoMarkIrpPending(Irp); sendCommandToServer = TRUE;
status = STATUS_PENDING;
break; }
case SRB_FUNCTION_EXECUTE_SCSI: { //
// Mark Irp status pending.
//
IoMarkIrpPending(Irp); sendCommandToServer = TRUE;
status = STATUS_PENDING; } case SRB_FUNCTION_RELEASE_QUEUE: case SRB_FUNCTION_FLUSH_QUEUE: { //
// These will be handled on the server
// side. Here, just return STATUS_SUCCESS
//
status = STATUS_SUCCESS; srb->SrbStatus = SRB_STATUS_SUCCESS;
break; } case SRB_FUNCTION_RESET_BUS: { DebugPrint((1, "FdoDospatch : Received reset request\n"));
srb->SrbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; } case SRB_FUNCTION_ABORT_COMMAND: { DebugPrint((1, "FdoDispatch: SCSI Abort command\n"));
srb->SrbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; } case SRB_FUNCTION_ATTACH_DEVICE: case SRB_FUNCTION_CLAIM_DEVICE: case SRB_FUNCTION_RELEASE_DEVICE: { iSpAcquireRemoveLock((pdoExtension->CommonExtension.DeviceObject), Irp); status = iSpClaimLogicalUnit(fdoExtension, pdoExtension, Irp); iSpReleaseRemoveLock((pdoExtension->CommonExtension.DeviceObject), Irp); break; } default: { //
// Found unsupported SRB function.
//
DebugPrint((1, "FdoDispatch: Unsupported function, SRB %p\n", srb)); srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_DEVICE_REQUEST; break; } }
if (sendCommandToServer == FALSE) { iSpReleaseRemoveLock(DeviceObject, Irp); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
DebugPrint((3, "FdoDispatch : Will send the command to the server\n"));
status = iSpSendScsiCommand(DeviceObject, Irp);
//
// The lock will be released and IRP will be completed in
// iSpSendScsiCommand.
//
if (NT_SUCCESS(status)) { DebugPrint((3, "FdoDispatch : Command sent to the server.\n")); status = STATUS_PENDING; } else { DebugPrint((1, "FdoDispatch : Failed to send the command. Status : %x\n", status)); } return status; */ }
NTSTATUS iScsiPortFdoCreateClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_SUCCESS;
ULONG isRemoved;
isRemoved = iSpAcquireRemoveLock(DeviceObject, Irp); if(irpStack->MajorFunction == IRP_MJ_CREATE) {
if(isRemoved != NO_REMOVE) { status = STATUS_DEVICE_DOES_NOT_EXIST; } else if(commonExtension->CurrentPnpState != IRP_MN_START_DEVICE) { status = STATUS_DEVICE_NOT_READY; } }
iSpReleaseRemoveLock(DeviceObject, Irp); status = STATUS_SUCCESS; Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status; }
NTSTATUS iSpSetEvent( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { KeSetEvent((PKEVENT)Context, 0, FALSE); return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS iSpClaimLogicalUnit( IN PISCSI_FDO_EXTENSION FdoExtension, IN PISCSI_PDO_EXTENSION PdoExtension, IN PIRP Irp ) { PIO_STACK_LOCATION irpStack; PSCSI_REQUEST_BLOCK srb; PDEVICE_OBJECT saveDevice;
NTSTATUS status;
PAGED_CODE();
DebugPrint((3, "Entering iSpClaimLogicalUnit\n"));
//
// Get SRB address from current IRP stack.
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
srb = (PSCSI_REQUEST_BLOCK) irpStack->Parameters.Others.Argument1;
if (srb->Function == SRB_FUNCTION_RELEASE_DEVICE) {
PdoExtension->IsClaimed = FALSE; srb->SrbStatus = SRB_STATUS_SUCCESS; return(STATUS_SUCCESS); }
//
// Check for a claimed device.
//
if (PdoExtension->IsClaimed) {
DebugPrint((0, "Device already claimed\n")); srb->SrbStatus = SRB_STATUS_BUSY; return(STATUS_DEVICE_BUSY); }
//
// Save the current device object.
//
saveDevice = PdoExtension->CommonExtension.DeviceObject;
//
// Update the lun information based on the operation type.
//
if (srb->Function == SRB_FUNCTION_CLAIM_DEVICE) { PdoExtension->IsClaimed = TRUE; }
if (srb->Function == SRB_FUNCTION_ATTACH_DEVICE) { ASSERT(FALSE); PdoExtension->CommonExtension.DeviceObject = srb->DataBuffer; }
srb->DataBuffer = saveDevice;
srb->SrbStatus = SRB_STATUS_SUCCESS;
DebugPrint((3, "Successfully claimed the device\n")); return(STATUS_SUCCESS); }
/*
PISCSI_PDO_EXTENSION GetPdoExtension( IN PISCSI_FDO_EXTENSION fdoExtension ) { return ((fdoExtension->UpperPDO)->DeviceExtension); } */
NTSTATUS iSpProcessScsiRequest( IN PDEVICE_OBJECT LogicalUnit, IN PSCSI_REQUEST_BLOCK Srb ) { PISCSI_PDO_EXTENSION pdoExtension = LogicalUnit->DeviceExtension; PIRP irp;
ULONG bytesReturned;
NTSTATUS status;
PAGED_CODE();
irp = IoAllocateIrp((LogicalUnit->StackSize) + 1, FALSE); if (irp == NULL) { DebugPrint((1, "IssueInquiry : Failed to allocate IRP.\n")); return STATUS_INSUFFICIENT_RESOURCES; }
IoInitializeIrp(irp, IoSizeOfIrp((LogicalUnit->StackSize) + 1), ((LogicalUnit->StackSize) + 1));
status = iSpSendSrbSynchronous(LogicalUnit, Srb, irp, Srb->DataBuffer, Srb->DataTransferLength, Srb->SenseInfoBuffer, Srb->SenseInfoBufferLength, &bytesReturned );
ASSERT(bytesReturned <= (Srb->DataTransferLength));
if(!NT_SUCCESS(status)) {
DebugPrint((1, "Failed to process SRB. Status : %x\n", status)); }
IoFreeIrp(irp);
return status; }
|