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.
 
 
 
 
 
 

540 lines
13 KiB

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