scsiport.c
来自「一个类似windows」· C语言 代码 · 共 2,184 行 · 第 1/5 页
C
2,184 行
/*
* 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 21260 2006-03-08 23:23:57Z audit $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/storage/scsiport/scsiport.c
* PURPOSE: SCSI port driver
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
*/
/* 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>
#define NDEBUG
#include <debug.h>
#include "scsiport_int.h"
/* TYPES *********************************************************************/
#define IRP_FLAG_COMPLETE 0x00000001
#define IRP_FLAG_NEXT 0x00000002
#define IRP_FLAG_NEXT_LU 0x00000004
/* GLOBALS *******************************************************************/
static ULONG InternalDebugLevel = 0;
static VOID
SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PIRP NextIrp);
static VOID
SpiStartIo(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PIRP Irp);
static BOOLEAN
SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
IN ULONG BusNumber,
IN OUT PPCI_SLOT_NUMBER NextSlotNumber);
static NTSTATUS STDCALL
ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static NTSTATUS STDCALL
ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static NTSTATUS STDCALL
ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static BOOLEAN STDCALL
ScsiPortStartPacket(IN OUT PVOID Context);
static PSCSI_PORT_LUN_EXTENSION
SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun);
static VOID
SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension);
static PSCSI_PORT_LUN_EXTENSION
SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun);
static NTSTATUS
SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
IN OUT PSCSI_REQUEST_BLOCK Srb,
IN OUT PIO_STATUS_BLOCK IoStatusBlock,
IN OUT PKEVENT Event);
static VOID
SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
static ULONG
SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo);
static BOOLEAN STDCALL
ScsiPortIsr(IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext);
static VOID STDCALL
ScsiPortDpc(IN PKDPC Dpc,
IN PDEVICE_OBJECT DpcDeviceObject,
IN PIRP DpcIrp,
IN PVOID DpcContext);
static VOID STDCALL
ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
PVOID Context);
static PSCSI_REQUEST_BLOCK
ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb);
static NTSTATUS
SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PUNICODE_STRING RegistryPath);
static VOID
SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PSCSI_REQUEST_BLOCK Srb);
static VOID
SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PSCSI_REQUEST_BLOCK Srb);
static NTSTATUS
SpiScsiMiniport(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/* 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)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PSCSI_PORT_LUN_EXTENSION LunExtension;
PLIST_ENTRY Entry;
PIRP Irp;
PSCSI_REQUEST_BLOCK Srb;
DPRINT("ScsiPortCompleteRequest(HwDeviceExtension %x, PathId %d, TargetId %d, Lun %d, SrbStatus %x)\n",
HwDeviceExtension, PathId, TargetId, Lun, SrbStatus);
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
Entry = DeviceExtension->LunExtensionListHead.Flink;
while (Entry != &DeviceExtension->LunExtensionListHead)
{
LunExtension = CONTAINING_RECORD(Entry,
SCSI_PORT_LUN_EXTENSION,
List);
if (PathId == (UCHAR)SP_UNTAGGED ||
(PathId == LunExtension->PathId && TargetId == (UCHAR)SP_UNTAGGED) ||
(PathId == LunExtension->PathId && TargetId == LunExtension->TargetId && Lun == (UCHAR)SP_UNTAGGED) ||
(PathId == LunExtension->PathId && TargetId == LunExtension->TargetId && Lun == LunExtension->Lun))
{
Irp = LunExtension->NextIrp;
while (Irp)
{
Srb = (PSCSI_REQUEST_BLOCK)Irp->Tail.Overlay.DriverContext[3];
if (Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)
{
Srb->SrbStatus = SrbStatus;
ScsiPortNotification(RequestComplete,
HwDeviceExtension,
Srb);
}
Irp = Irp->Tail.Overlay.DriverContext[1];
}
}
Entry = Entry->Flink;
}
}
/*
* @implemented
*/
#undef ScsiPortConvertPhysicalAddressToUlong
ULONG STDCALL
ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
{
DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
return(Address.u.LowPart);
}
/*
* @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;
PSCSI_PORT_DEVICE_BASE DeviceBase;
PLIST_ENTRY Entry;
DPRINT("ScsiPortFreeDeviceBase() called\n");
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
if (IsListEmpty(&DeviceExtension->DeviceBaseListHead))
return;
Entry = DeviceExtension->DeviceBaseListHead.Flink;
while (Entry != &DeviceExtension->DeviceBaseListHead)
{
DeviceBase = CONTAINING_RECORD(Entry,
SCSI_PORT_DEVICE_BASE,
List);
if (DeviceBase->MappedAddress == MappedAddress)
{
MmUnmapIoSpace(DeviceBase->MappedAddress,
DeviceBase->NumberOfBytes);
RemoveEntryList(Entry);
ExFreePool(DeviceBase);
return;
}
Entry = Entry->Flink;
}
}
/*
* @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,
IN BOOLEAN InIoSpace)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PHYSICAL_ADDRESS TranslatedAddress;
PSCSI_PORT_DEVICE_BASE DeviceBase;
ULONG AddressSpace;
PVOID MappedAddress;
DPRINT ("ScsiPortGetDeviceBase() called\n");
AddressSpace = (ULONG)InIoSpace;
if (HalTranslateBusAddress(BusType,
SystemIoBusNumber,
IoAddress,
&AddressSpace,
&TranslatedAddress) == FALSE)
return NULL;
/* i/o space */
if (AddressSpace != 0)
return((PVOID)TranslatedAddress.u.LowPart);
MappedAddress = MmMapIoSpace(TranslatedAddress,
NumberOfBytes,
MmNonCached);
DeviceBase = ExAllocatePool(NonPagedPool,
sizeof(SCSI_PORT_DEVICE_BASE));
if (DeviceBase == NULL)
return(MappedAddress);
DeviceBase->MappedAddress = MappedAddress;
DeviceBase->NumberOfBytes = NumberOfBytes;
DeviceBase->IoAddress = IoAddress;
DeviceBase->SystemIoBusNumber = SystemIoBusNumber;
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
InsertHeadList(&DeviceExtension->DeviceBaseListHead,
&DeviceBase->List);
return(MappedAddress);
}
/*
* @implemented
*/
PVOID STDCALL
ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PSCSI_PORT_LUN_EXTENSION LunExtension;
PLIST_ENTRY Entry;
DPRINT("ScsiPortGetLogicalUnit() called\n");
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
return NULL;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?