📄 scsiport.c
字号:
/*
* ReactOS kernel
* Copyright (C) 2001, 2002 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: scsiport.c 28981 2007-09-09 15:04:06Z fireball $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Storage Stack
* FILE: drivers/storage/scsiport/scsiport.c
* PURPOSE: SCSI port driver
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
* Aleksey Bragin (aleksey reactos org)
*/
/* INCLUDES *****************************************************************/
#include <ntddk.h>
#include <srb.h>
#include <scsi.h>
#include <ntddscsi.h>
#include <ntddstor.h>
#include <ntdddisk.h>
#include <stdio.h>
#include <stdarg.h>
#ifndef NDEBUG
#define NDEBUG
#endif
#include <debug.h>
#include "scsiport_int.h"
#ifdef _MSC_VER
#define STDCALL
#define DDKAPI
#endif
ULONG InternalDebugLevel = 0x00;
/* TYPES *********************************************************************/
/* GLOBALS *******************************************************************/
static BOOLEAN
SpiGetPciConfigData(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject,
IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
IN PUNICODE_STRING RegistryPath,
IN ULONG BusNumber,
IN OUT PPCI_SLOT_NUMBER NextSlotNumber);
static NTSTATUS STDCALL
ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static DRIVER_DISPATCH ScsiPortDispatchScsi;
static NTSTATUS STDCALL
ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static NTSTATUS STDCALL
ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static DRIVER_STARTIO ScsiPortStartIo;
static VOID STDCALL
ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static BOOLEAN STDCALL
ScsiPortStartPacket(IN OUT PVOID Context);
IO_ALLOCATION_ACTION
STDCALL
SpiAdapterControl(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PVOID MapRegisterBase, PVOID Context);
static PSCSI_PORT_LUN_EXTENSION
SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
static PSCSI_PORT_LUN_EXTENSION
SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun);
static PSCSI_REQUEST_BLOCK_INFO
SpiAllocateSrbStructures(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PSCSI_PORT_LUN_EXTENSION LunExtension,
PSCSI_REQUEST_BLOCK Srb);
static NTSTATUS
SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
IN PSCSI_LUN_INFO LunInfo);
static VOID
SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
static NTSTATUS
SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN PIRP Irp);
static PSCSI_REQUEST_BLOCK_INFO
SpiGetSrbData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun,
IN UCHAR QueueTag);
static KSERVICE_ROUTINE ScsiPortIsr;
static BOOLEAN STDCALL
ScsiPortIsr(IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext);
static VOID STDCALL
ScsiPortDpcForIsr(IN PKDPC Dpc,
IN PDEVICE_OBJECT DpcDeviceObject,
IN PIRP DpcIrp,
IN PVOID DpcContext);
static VOID STDCALL
ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
PVOID Context);
static NTSTATUS
SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PUNICODE_STRING RegistryPath);
static NTSTATUS
SpiStatusSrbToNt(UCHAR SrbStatus);
static VOID
SpiSendRequestSense(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb);
static IO_COMPLETION_ROUTINE SpiCompletionRoutine;
NTSTATUS STDCALL
SpiCompletionRoutine(PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context);
static VOID
STDCALL
SpiProcessCompletedRequest(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN PSCSI_REQUEST_BLOCK_INFO SrbInfo,
OUT PBOOLEAN NeedToCallStartIo);
VOID STDCALL
SpiGetNextRequestFromLun(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN PSCSI_PORT_LUN_EXTENSION LunExtension);
VOID STDCALL
SpiMiniportTimerDpc(IN struct _KDPC *Dpc,
IN PVOID DeviceObject,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2);
static NTSTATUS
SpiCreatePortConfig(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PHW_INITIALIZATION_DATA HwInitData,
PCONFIGURATION_INFO InternalConfigInfo,
PPORT_CONFIGURATION_INFORMATION ConfigInfo,
BOOLEAN FirstCall);
NTSTATUS STDCALL
SpQueryDeviceCallout(IN PVOID Context,
IN PUNICODE_STRING PathName,
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
IN CONFIGURATION_TYPE ControllerType,
IN ULONG ControllerNumber,
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
IN CONFIGURATION_TYPE PeripheralType,
IN ULONG PeripheralNumber,
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation);
static VOID
SpiParseDeviceInfo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN HANDLE Key,
IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
IN PCONFIGURATION_INFO InternalConfigInfo,
IN PUCHAR Buffer);
static VOID
SpiResourceToConfig(IN PHW_INITIALIZATION_DATA HwInitializationData,
IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor,
IN PPORT_CONFIGURATION_INFORMATION PortConfig);
static PCM_RESOURCE_LIST
SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PPORT_CONFIGURATION_INFORMATION PortConfig);
static VOID
SpiCleanupAfterInit(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
static NTSTATUS
SpiHandleAttachRelease(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PIRP Irp);
static NTSTATUS
SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCachedSize);
/* FUNCTIONS *****************************************************************/
/**********************************************************************
* NAME EXPORTED
* DriverEntry
*
* DESCRIPTION
* This function initializes the driver.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* DriverObject
* System allocated Driver Object for this driver.
*
* RegistryPath
* Name of registry driver service key.
*
* RETURN VALUE
* Status.
*/
NTSTATUS STDCALL
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
DPRINT("ScsiPort Driver %s\n", VERSION);
return(STATUS_SUCCESS);
}
/**********************************************************************
* NAME EXPORTED
* ScsiDebugPrint
*
* DESCRIPTION
* Prints debugging messages.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* DebugPrintLevel
* Debug level of the given message.
*
* DebugMessage
* Pointer to printf()-compatible format string.
*
* ...
Additional output data (see printf()).
*
* RETURN VALUE
* None.
*
* @implemented
*/
VOID
ScsiDebugPrint(IN ULONG DebugPrintLevel,
IN PCHAR DebugMessage,
...)
{
char Buffer[256];
va_list ap;
if (DebugPrintLevel > InternalDebugLevel)
return;
va_start(ap, DebugMessage);
vsprintf(Buffer, DebugMessage, ap);
va_end(ap);
DbgPrint(Buffer);
}
/*
* @unimplemented
*/
VOID STDCALL
ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun,
IN UCHAR SrbStatus)
{
DPRINT("ScsiPortCompleteRequest()\n");
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID STDCALL
ScsiPortFlushDma(IN PVOID HwDeviceExtension)
{
DPRINT("ScsiPortFlushDma()\n");
UNIMPLEMENTED;
}
/*
* @implemented
*/
VOID STDCALL
ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
IN PVOID MappedAddress)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PMAPPED_ADDRESS NextMa, LastMa;
//DPRINT("ScsiPortFreeDeviceBase() called\n");
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
/* Initialize our pointers */
NextMa = DeviceExtension->MappedAddressList;
LastMa = NextMa;
while (NextMa)
{
if (NextMa->MappedAddress == MappedAddress)
{
/* Unmap it first */
MmUnmapIoSpace(MappedAddress, NextMa->NumberOfBytes);
/* Remove it from the list */
if (NextMa == DeviceExtension->MappedAddressList)
{
/* Remove the first entry */
DeviceExtension->MappedAddressList = NextMa->NextMappedAddress;
}
else
{
LastMa->NextMappedAddress = NextMa->NextMappedAddress;
}
/* Free the resources and quit */
ExFreePool(NextMa);
return;
}
else
{
LastMa = NextMa;
NextMa = NextMa->NextMappedAddress;
}
}
}
/*
* @implemented
*/
ULONG STDCALL
ScsiPortGetBusData(IN PVOID DeviceExtension,
IN ULONG BusDataType,
IN ULONG SystemIoBusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Length)
{
return(HalGetBusData(BusDataType,
SystemIoBusNumber,
SlotNumber,
Buffer,
Length));
}
/*
* @implemented
*/
PVOID STDCALL
ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
IN INTERFACE_TYPE BusType,
IN ULONG SystemIoBusNumber,
IN SCSI_PHYSICAL_ADDRESS IoAddress,
IN ULONG NumberOfBytes,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -