📄 scsiport.c
字号:
LunInfo = Ptr;
}
ExFreePool(DeviceExtension->BusesConfig->BusScanInfo[Bus]);
}
ExFreePool(DeviceExtension->BusesConfig);
}
/* Free PortConfig */
if (DeviceExtension->PortConfig)
ExFreePool(DeviceExtension->PortConfig);
/* Free LUNs*/
for(Lun = 0; Lun < LUS_NUMBER; Lun++)
{
while (DeviceExtension->LunExtensionList[Lun])
{
Ptr = DeviceExtension->LunExtensionList[Lun];
DeviceExtension->LunExtensionList[Lun] = DeviceExtension->LunExtensionList[Lun]->Next;
ExFreePool(Ptr);
}
}
/* Free common buffer (if it exists) */
if (DeviceExtension->SrbExtensionBuffer != NULL &&
DeviceExtension->CommonBufferLength != 0)
{
if (!DeviceExtension->AdapterObject)
{
ExFreePool(DeviceExtension->SrbExtensionBuffer);
}
else
{
#if 0
HalFreeCommonBuffer(DeviceExtension->AdapterObject,
DeviceExtension->CommonBufferLength,
DeviceExtension->PhysicalCommonBuffer,
DeviceExtension->SrbExtensionBuffer,
FALSE);
#endif
}
}
/* Free SRB info */
if (DeviceExtension->SrbInfo != NULL)
ExFreePool(DeviceExtension->SrbInfo);
/* Unmap mapped addresses */
while (DeviceExtension->MappedAddressList != NULL)
{
MmUnmapIoSpace(DeviceExtension->MappedAddressList->MappedAddress,
DeviceExtension->MappedAddressList->NumberOfBytes);
Ptr = DeviceExtension->MappedAddressList;
DeviceExtension->MappedAddressList = DeviceExtension->MappedAddressList->NextMappedAddress;
ExFreePool(Ptr);
}
/* Finally delete the device object */
DPRINT("Deleting device %p\n", DeviceExtension->DeviceObject);
IoDeleteDevice(DeviceExtension->DeviceObject);
}
/*
* @unimplemented
*/
VOID STDCALL
ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb,
IN PVOID LogicalAddress,
IN ULONG Length)
{
DPRINT1("ScsiPortIoMapTransfer()\n");
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID STDCALL
ScsiPortLogError(IN PVOID HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun,
IN ULONG ErrorCode,
IN ULONG UniqueId)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
DPRINT1("ScsiPortLogError() called\n");
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
DPRINT("ScsiPortLogError() done\n");
}
/*
* @implemented
*/
VOID STDCALL
ScsiPortMoveMemory(OUT PVOID Destination,
IN PVOID Source,
IN ULONG Length)
{
RtlMoveMemory(Destination,
Source,
Length);
}
/*
* @implemented
*/
VOID
ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
IN PVOID HwDeviceExtension,
...)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
va_list ap;
DPRINT("ScsiPortNotification() called\n");
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
DPRINT("DeviceExtension %p\n", DeviceExtension);
va_start(ap, HwDeviceExtension);
switch (NotificationType)
{
case RequestComplete:
{
PSCSI_REQUEST_BLOCK Srb;
PSCSI_REQUEST_BLOCK_INFO SrbData;
Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);
DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
/* Make sure Srb is allright */
ASSERT(Srb->SrbStatus != SRB_STATUS_PENDING);
ASSERT(Srb->Function != SRB_FUNCTION_EXECUTE_SCSI || Srb->SrbStatus != SRB_STATUS_SUCCESS || Srb->ScsiStatus == SCSISTAT_GOOD);
if (!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE))
{
/* It's been already completed */
va_end(ap);
return;
}
/* It's not active anymore */
Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
{
/* TODO: Treat it specially */
ASSERT(FALSE);
}
else
{
/* Get the SRB data */
SrbData = SpiGetSrbData(DeviceExtension,
Srb->PathId,
Srb->TargetId,
Srb->Lun,
Srb->QueueTag);
/* Make sure there are no CompletedRequests and there is a Srb */
ASSERT(SrbData->CompletedRequests == NULL && SrbData->Srb != NULL);
/* If it's a read/write request, make sure it has data inside it */
if ((Srb->SrbStatus == SRB_STATUS_SUCCESS) &&
((Srb->Cdb[0] == SCSIOP_READ) || (Srb->Cdb[0] == SCSIOP_WRITE)))
{
ASSERT(Srb->DataTransferLength);
}
SrbData->CompletedRequests = DeviceExtension->InterruptData.CompletedRequests;
DeviceExtension->InterruptData.CompletedRequests = SrbData;
}
}
break;
case NextRequest:
DPRINT("Notify: NextRequest\n");
DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
break;
case NextLuRequest:
{
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
PathId = (UCHAR) va_arg (ap, int);
TargetId = (UCHAR) va_arg (ap, int);
Lun = (UCHAR) va_arg (ap, int);
DPRINT1 ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
PathId, TargetId, Lun);
/* FIXME: Implement it! */
ASSERT(FALSE);
// DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
// DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
/* Hack! */
// DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
}
break;
case ResetDetected:
DPRINT1("Notify: ResetDetected\n");
/* FIXME: ??? */
break;
default:
DPRINT1 ("Unsupported notification %lu\n", NotificationType);
break;
}
va_end(ap);
/* Request a DPC after we're done with the interrupt */
DeviceExtension->InterruptData.Flags |= SCSI_PORT_NOTIFICATION_NEEDED;
}
/*
* @implemented
*/
ULONG STDCALL
ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
IN ULONG BusDataType,
IN ULONG SystemIoBusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length)
{
DPRINT("ScsiPortSetBusDataByOffset()\n");
return(HalSetBusDataByOffset(BusDataType,
SystemIoBusNumber,
SlotNumber,
Buffer,
Offset,
Length));
}
/*
* @implemented
*/
BOOLEAN STDCALL
ScsiPortValidateRange(IN PVOID HwDeviceExtension,
IN INTERFACE_TYPE BusType,
IN ULONG SystemIoBusNumber,
IN SCSI_PHYSICAL_ADDRESS IoAddress,
IN ULONG NumberOfBytes,
IN BOOLEAN InIoSpace)
{
DPRINT("ScsiPortValidateRange()\n");
return(TRUE);
}
/* INTERNAL FUNCTIONS ********************************************************/
static VOID
SpiResourceToConfig(IN PHW_INITIALIZATION_DATA HwInitializationData,
IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor,
IN PPORT_CONFIGURATION_INFORMATION PortConfig)
{
PACCESS_RANGE AccessRange;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData;
ULONG RangeNumber;
ULONG Index;
RangeNumber = 0;
/* Loop through all entries */
for (Index = 0; Index < ResourceDescriptor->PartialResourceList.Count; Index++)
{
PartialData = &ResourceDescriptor->PartialResourceList.PartialDescriptors[Index];
switch (PartialData->Type)
{
case CmResourceTypePort:
/* Copy access ranges */
if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
{
AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);
AccessRange->RangeStart = PartialData->u.Port.Start;
AccessRange->RangeLength = PartialData->u.Port.Length;
AccessRange->RangeInMemory = FALSE;
RangeNumber++;
}
break;
case CmResourceTypeMemory:
/* Copy access ranges */
if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
{
AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);
AccessRange->RangeStart = PartialData->u.Memory.Start;
AccessRange->RangeLength = PartialData->u.Memory.Length;
AccessRange->RangeInMemory = TRUE;
RangeNumber++;
}
break;
case CmResourceTypeInterrupt:
/* Copy interrupt data */
PortConfig->BusInterruptLevel = PartialData->u.Interrupt.Level;
PortConfig->BusInterruptVector = PartialData->u.Interrupt.Vector;
/* Set interrupt mode accordingly to the resource */
if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
{
PortConfig->InterruptMode = Latched;
}
else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
{
PortConfig->InterruptMode = LevelSensitive;
}
break;
case CmResourceTypeDma:
PortConfig->DmaChannel = PartialData->u.Dma.Channel;
PortConfig->DmaPort = PartialData->u.Dma.Port;
break;
}
}
}
static PCM_RESOURCE_LIST
SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PPORT_CONFIGURATION_INFORMATION PortConfig)
{
PCONFIGURATION_INFORMATION ConfigInfo;
PCM_RESOURCE_LIST ResourceList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
PACCESS_RANGE AccessRange;
BOOLEAN Dma;
ULONG ListLength = 0, i, FullSize;
ULONG Interrupt;
/* Get current Atdisk usage from the system */
ConfigInfo = IoGetConfigurationInformation();
if (PortConfig->AtdiskPrimaryClaimed)
ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE;
if (PortConfig->AtdiskSecondaryClaimed)
ConfigInfo->AtDiskSecondaryAddressClaimed = TRUE;
/* Do we use DMA? */
if (PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE ||
PortConfig->DmaPort != SP_UNINITIALIZED_VALUE)
{
Dma = TRUE;
ListLength++;
}
else
{
Dma = FALSE;
}
/* How many interrupts to we have? */
if (DeviceExtension->HwInterrupt == NULL ||
(PortConfig->BusInterruptLevel == 0 &&
PortConfig->BusInterruptVector == 0))
{
Interrupt = 0;
}
else
{
Interrupt = 1;
ListLength++;
}
if (DeviceExtension->HwInterrupt != NULL &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -