- Implemented ScsiPortGetPhysicalAddress also for addresses from sense info buffer.

- Allocated the sense info buffer within contiguous physical memory.
- Don't send an sence request after an error if the miniport driver is autosense-capable.

svn path=/trunk/; revision=9487
This commit is contained in:
Hartmut Birr 2004-05-24 20:33:41 +00:00
parent b718b8e348
commit e58206820b

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: scsiport.c,v 1.56 2004/05/15 22:45:50 hbirr Exp $ /* $Id: scsiport.c,v 1.57 2004/05/24 20:33:41 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -433,26 +433,37 @@ ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION, SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension); MiniPortDeviceExtension);
*Length = 0; if (Length != NULL)
{
*Length = 0;
}
if (Srb == NULL) if (Srb == NULL)
{ {
if ((ULONG_PTR)DeviceExtension->VirtualAddress > (ULONG_PTR)VirtualAddress) EndAddress = DeviceExtension->VirtualAddress + DeviceExtension->CommonBufferLength;
{ if (VirtualAddress >= DeviceExtension->VirtualAddress && VirtualAddress < EndAddress)
PhysicalAddress.QuadPart = 0ULL; {
return PhysicalAddress; Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset;
BufferLength = (ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress;
} }
else
Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress; {
if (Offset >= DeviceExtension->CommonBufferLength) /*
{ * The given virtual address is not within the range
PhysicalAddress.QuadPart = 0ULL; * of the drivers uncached extension or srb extension.
return PhysicalAddress; */
/*
* FIXME:
* Check if the address is a sense info buffer of an active srb.
*/
PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
if (PhysicalAddress.QuadPart == 0LL)
{
CHECKPOINT;
return PhysicalAddress;
}
BufferLength = PAGE_SIZE - PhysicalAddress.u.LowPart % PAGE_SIZE;
} }
PhysicalAddress.QuadPart =
DeviceExtension->PhysicalAddress.QuadPart + (ULONGLONG)Offset;
BufferLength = DeviceExtension->CommonBufferLength - Offset;
} }
else else
{ {
@ -463,30 +474,27 @@ ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
} }
else if (VirtualAddress < Srb->DataBuffer || VirtualAddress >= EndAddress) else if (VirtualAddress < Srb->DataBuffer || VirtualAddress >= EndAddress)
{ {
PhysicalAddress.QuadPart = 0LL; EndAddress = Srb->SenseInfoBuffer + Srb->SenseInfoBufferLength;
return PhysicalAddress; if (VirtualAddress < Srb->SenseInfoBuffer || VirtualAddress >= EndAddress)
{
PhysicalAddress.QuadPart = 0LL;
CHECKPOINT;
return PhysicalAddress;
}
} }
PhysicalAddress = MmGetPhysicalAddress(VirtualAddress); PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
if (PhysicalAddress.QuadPart == 0LL) if (PhysicalAddress.QuadPart == 0LL)
{ {
CHECKPOINT;
return PhysicalAddress; return PhysicalAddress;
} }
Offset = (ULONG_PTR)VirtualAddress & (PAGE_SIZE - 1); BufferLength = PAGE_SIZE - (ULONG_PTR)VirtualAddress % PAGE_SIZE;
#if 1
/*
* FIXME:
* MmGetPhysicalAddress doesn't return the offset within the page.
* We must set the correct offset.
*/
PhysicalAddress.u.LowPart = (PhysicalAddress.u.LowPart & ~(PAGE_SIZE - 1)) + Offset;
#endif
BufferLength += PAGE_SIZE - Offset;
while (VirtualAddress + BufferLength < EndAddress) while (VirtualAddress + BufferLength < EndAddress)
{ {
NextPhysicalAddress = MmGetPhysicalAddress(VirtualAddress + BufferLength); NextPhysicalAddress = MmGetPhysicalAddress(VirtualAddress + BufferLength);
if (PhysicalAddress.QuadPart + (ULONGLONG)BufferLength != NextPhysicalAddress.QuadPart) if (PhysicalAddress.QuadPart + BufferLength != NextPhysicalAddress.QuadPart)
{ {
break; break;
} }
@ -497,9 +505,11 @@ ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
BufferLength = EndAddress - VirtualAddress; BufferLength = EndAddress - VirtualAddress;
} }
} }
if (Length != NULL)
*Length = BufferLength; {
*Length = BufferLength;
}
DPRINT("Address %I64x, Length %d\n", PhysicalAddress.QuadPart, BufferLength);
return PhysicalAddress; return PhysicalAddress;
} }
@ -758,13 +768,11 @@ ScsiPortInitialize(IN PVOID Argument1,
DeviceExtension->HwStartIo = HwInitializationData->HwStartIo; DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt; DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
#if 0
DeviceExtension->AdapterObject = NULL; DeviceExtension->AdapterObject = NULL;
DeviceExtension->MapRegisterCount = 0; DeviceExtension->MapRegisterCount = 0;
DeviceExtension->PhysicalAddress.QuadPart = 0ULL; DeviceExtension->PhysicalAddress.QuadPart = 0ULL;
DeviceExtension->VirtualAddress = NULL; DeviceExtension->VirtualAddress = NULL;
DeviceExtension->CommonBufferLength = 0; DeviceExtension->CommonBufferLength = 0;
#endif
/* Initialize the device base list */ /* Initialize the device base list */
InitializeListHead (&DeviceExtension->DeviceBaseListHead); InitializeListHead (&DeviceExtension->DeviceBaseListHead);
@ -814,36 +822,36 @@ ScsiPortInitialize(IN PVOID Argument1,
PortConfig->NumberOfPhysicalBreaks = SP_UNINITIALIZED_VALUE; PortConfig->NumberOfPhysicalBreaks = SP_UNINITIALIZED_VALUE;
PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE; PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE;
PortConfig->DmaPort = SP_UNINITIALIZED_VALUE; PortConfig->DmaPort = SP_UNINITIALIZED_VALUE;
// PortConfig->DmaWidth = PortConfig->DmaWidth = 0;
// PortConfig->DmaSpeed = PortConfig->DmaSpeed = Compatible;
// PortConfig->AlignmentMask = PortConfig->AlignmentMask = 0;
PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges; PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
// PortConfig->NumberOfBuses = PortConfig->NumberOfBuses = 0;
for (i = 0; i < SCSI_MAXIMUM_BUSES; i++) for (i = 0; i < SCSI_MAXIMUM_BUSES; i++)
PortConfig->InitiatorBusId[i] = 255; PortConfig->InitiatorBusId[i] = 255;
// PortConfig->ScatterGather = PortConfig->ScatterGather = FALSE;
// PortConfig->Master = PortConfig->Master = FALSE;
// PortConfig->CachesData = PortConfig->CachesData = FALSE;
// PortConfig->AdapterScansDown = PortConfig->AdapterScansDown = FALSE;
PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed; PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed; PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
// PortConfig->Dma32BitAddresses = PortConfig->Dma32BitAddresses = FALSE;
// PortConfig->DemandMode = PortConfig->DemandMode = FALSE;
PortConfig->MapBuffers = HwInitializationData->MapBuffers; PortConfig->MapBuffers = HwInitializationData->MapBuffers;
PortConfig->NeedPhysicalAddresses = HwInitializationData->NeedPhysicalAddresses; PortConfig->NeedPhysicalAddresses = HwInitializationData->NeedPhysicalAddresses;
PortConfig->TaggedQueuing = HwInitializationData->TaggedQueueing; PortConfig->TaggedQueuing = HwInitializationData->TaggedQueueing;
PortConfig->AutoRequestSense = HwInitializationData->AutoRequestSense; PortConfig->AutoRequestSense = HwInitializationData->AutoRequestSense;
PortConfig->MultipleRequestPerLu = HwInitializationData->MultipleRequestPerLu; PortConfig->MultipleRequestPerLu = HwInitializationData->MultipleRequestPerLu;
PortConfig->ReceiveEvent = HwInitializationData->ReceiveEvent; PortConfig->ReceiveEvent = HwInitializationData->ReceiveEvent;
// PortConfig->RealModeInitialized = PortConfig->RealModeInitialized = FALSE;
// PortConfig->BufferAccessScsiPortControlled = PortConfig->BufferAccessScsiPortControlled = FALSE;
PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS; PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
// PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS; // PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
PortConfig->SrbExtensionSize = HwInitializationData->SrbExtensionSize; PortConfig->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
PortConfig->SpecificLuExtensionSize = HwInitializationData->SpecificLuExtensionSize; PortConfig->SpecificLuExtensionSize = HwInitializationData->SpecificLuExtensionSize;
PortConfig->SlotNumber = SlotNumber.u.AsULONG; PortConfig->SlotNumber = SlotNumber.u.AsULONG;
@ -1903,6 +1911,7 @@ SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
else else
{ {
SpiRemoveLunExtension (LunExtension); SpiRemoveLunExtension (LunExtension);
break;
} }
} }
} }
@ -2070,14 +2079,19 @@ static PSCSI_REQUEST_BLOCK
ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb) ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb)
{ {
PSCSI_REQUEST_BLOCK Srb; PSCSI_REQUEST_BLOCK Srb;
ULONG Length;
PCDB Cdb; PCDB Cdb;
Length = sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA) + 32;
Srb = ExAllocatePoolWithTag(NonPagedPool, Srb = ExAllocatePoolWithTag(NonPagedPool,
sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA), Length,
TAG('S', 'S', 'r', 'b')); TAG('S', 'S', 'r', 'b'));
if (Srb == NULL)
{
return NULL;
}
RtlZeroMemory(Srb, RtlZeroMemory(Srb, Length);
sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA));
Srb->PathId = OriginalSrb->PathId; Srb->PathId = OriginalSrb->PathId;
Srb->TargetId = OriginalSrb->TargetId; Srb->TargetId = OriginalSrb->TargetId;
@ -2089,7 +2103,12 @@ ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb)
Srb->TimeOutValue = 4; Srb->TimeOutValue = 4;
Srb->CdbLength = 6; Srb->CdbLength = 6;
Srb->DataBuffer = Srb + 1; /* The DataBuffer must be located in contiguous physical memory if
* the miniport driver uses dma for the sense info. The size of
* the sense data is 18 byte. If the buffer starts at a 32 byte
* boundary than is the buffer always in one memory page.
*/
Srb->DataBuffer = (PVOID)ROUND_UP((ULONG_PTR)(Srb + 1), 32);
Srb->DataTransferLength = sizeof(SENSE_DATA); Srb->DataTransferLength = sizeof(SENSE_DATA);
Cdb = (PCDB)Srb->Cdb; Cdb = (PCDB)Srb->Cdb;
@ -2625,18 +2644,18 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
DPRINT("SenseCode: %x\n", SenseInfoBuffer->AdditionalSenseCode); DPRINT("SenseCode: %x\n", SenseInfoBuffer->AdditionalSenseCode);
/* Copy sense data */ /* Copy sense data */
if (OriginalSrb->SenseInfoBufferLength != 0) RtlCopyMemory(OriginalSrb->SenseInfoBuffer,
{ SenseInfoBuffer,
RtlCopyMemory(OriginalSrb->SenseInfoBuffer, sizeof(SENSE_DATA));
SenseInfoBuffer, OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
sizeof(SENSE_DATA));
OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
}
ExFreePool(Srb); ExFreePool(Srb);
CompleteThisRequest = TRUE; CompleteThisRequest = TRUE;
} }
else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) && else if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS &&
(Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION)) Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION &&
Srb->SenseInfoBuffer != NULL &&
Srb->SenseInfoBufferLength >= sizeof(SENSE_DATA) &&
!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID))
{ {
DPRINT("SCSIOP_REQUEST_SENSE required!\n"); DPRINT("SCSIOP_REQUEST_SENSE required!\n");