#include "usbstor.h"
-NTSTATUS
-USBSTOR_HandleExecuteSCSI(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN OUT PSCSI_REQUEST_BLOCK Request,
- IN PPDO_DEVICE_EXTENSION PDODeviceExtension)
-{
- PCDB pCDB;
- NTSTATUS Status;
- ULONG TransferredLength;
-
- //
- // get SCSI command data block
- //
- pCDB = (PCDB)Request->Cdb;
-
- DPRINT1("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]);
-
- if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
- {
- //
- // sanity checks
- //
- ASSERT(Request->DataBuffer);
-
- if (Request->DataTransferLength == sizeof(READ_CAPACITY_DATA_EX))
- {
- //
- // retrieve capacity extended structure
- //
- Status = USBSTOR_SendCapacityCmd(DeviceObject, (PREAD_CAPACITY_DATA_EX)Request->DataBuffer, NULL);
- }
- else
- {
- //
- // sanity check
- //
- ASSERT(Request->DataTransferLength == sizeof(READ_CAPACITY_DATA));
-
- //
- // retrieve capacity
- //
- Status = USBSTOR_SendCapacityCmd(DeviceObject, NULL, (PREAD_CAPACITY_DATA)Request->DataBuffer);
- }
- DPRINT1("USBSTOR_SendCapacityCmd %x\n", Status);
-
- if (NT_SUCCESS(Status))
- {
- //
- // store returned info length
- //
- Irp->IoStatus.Information = Request->DataTransferLength;
- Request->SrbStatus = SRB_STATUS_SUCCESS;
- }
- else
- {
- //
- // failed to retrieve capacity
- //
- Irp->IoStatus.Information = 0;
- Request->SrbStatus = SRB_STATUS_ERROR;
- }
- }
- else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE)
- {
- DPRINT1("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request->DataTransferLength);
- ASSERT(pCDB->MODE_SENSE.AllocationLength == Request->DataTransferLength);
- ASSERT(Request->DataBuffer);
-
- //
- // send mode sense command
- //
- Status = USBSTOR_SendModeSenseCmd(DeviceObject, Request, &TransferredLength);
- DPRINT1("USBSTOR_SendModeSenseCmd Status %x BytesReturned %lu\n", Status, TransferredLength);
-
- if (NT_SUCCESS(Status))
- {
- //
- // store returned info length
- //
- Irp->IoStatus.Information = TransferredLength;
- Request->SrbStatus = SRB_STATUS_SUCCESS;
- }
- else
- {
- //
- // failed to retrieve sense data
- //
- Irp->IoStatus.Information = 0;
- Request->SrbStatus = SRB_STATUS_ERROR;
- }
- }
- else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ)
- {
- DPRINT1("SCSIOP_READ DataTransferLength %lu\n", Request->DataTransferLength);
- ASSERT(Request->DataBuffer);
-
- //
- // send read command
- //
- Status = USBSTOR_SendReadCmd(DeviceObject, Request, &TransferredLength);
- DPRINT1("USBSTOR_SendReadCmd Status %x BytesReturned %lu\n", Status, TransferredLength);
-
- if (NT_SUCCESS(Status))
- {
- //
- // store returned info length
- //
- Irp->IoStatus.Information = TransferredLength;
- Request->SrbStatus = SRB_STATUS_SUCCESS;
- }
- else
- {
- //
- // failed to read
- //
- Irp->IoStatus.Information = 0;
- Request->SrbStatus = SRB_STATUS_ERROR;
- }
- }
- else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY)
- {
- DPRINT1("SCSIOP_TEST_UNIT_READY\n");
-
- //
- // send test unit command
- //
- Status = USBSTOR_SendTestUnitCmd(DeviceObject, Request);
-
- if (NT_SUCCESS(Status))
- {
- //
- // store returned info length
- //
- Request->SrbStatus = SRB_STATUS_SUCCESS;
- }
- else
- {
- //
- // test unit command failed
- //
- Request->SrbStatus = SRB_STATUS_ERROR;
- }
- }
- else
- {
- UNIMPLEMENTED;
- Request->SrbStatus = SRB_STATUS_ERROR;
- Status = STATUS_NOT_SUPPORTED;
- DbgBreakPoint();
- }
-
- return Status;
-}
-
NTSTATUS
USBSTOR_HandleInternalDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
//
Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+ //
+ // sanity check
+ //
+ ASSERT(Request);
+
//
// get device extension
//
//
// sanity check
//
- ASSERT(Request);
- ASSERT(PDODeviceExtension);
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
switch(Request->Function)
{
case SRB_FUNCTION_EXECUTE_SCSI:
{
- DPRINT1("SRB_FUNCTION_EXECUTE_SCSI\n");
- Status = USBSTOR_HandleExecuteSCSI(DeviceObject, Irp, Request, PDODeviceExtension);
- break;
+ DPRINT("SRB_FUNCTION_EXECUTE_SCSI\n");
+
+ //
+ // check if request is valid
+ //
+ if (Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT))
+ {
+ //
+ // data is transferred with this irp
+ //
+ if ((Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)) == (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT) ||
+ Request->DataTransferLength == 0 ||
+ Irp->MdlAddress == NULL)
+ {
+ //
+ // invalid parameter
+ //
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ }
+ else
+ {
+ //
+ // sense buffer request
+ //
+ if (Request->DataTransferLength ||
+ Request->DataBuffer ||
+ Irp->MdlAddress)
+ {
+ //
+ // invalid parameter
+ //
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ }
+
+ //
+ // add the request
+ //
+ if (!USBSTOR_QueueAddIrp(PDODeviceExtension->LowerDeviceObject, Irp))
+ {
+ //
+ // irp was not added to the queue
+ //
+ IoStartPacket(PDODeviceExtension->LowerDeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
+ }
+
+ //
+ // irp pending
+ //
+ return STATUS_PENDING;
}
case SRB_FUNCTION_RELEASE_DEVICE:
{
//
// release claim
//
- PDODeviceExtension->Claimed = TRUE;
+ PDODeviceExtension->Claimed = FALSE;
Status = STATUS_SUCCESS;
break;
}
}
case SRB_FUNCTION_RELEASE_QUEUE:
{
- DPRINT1("SRB_FUNCTION_RELEASE_QUEUE UNIMPLEMENTED\n");
- Status = STATUS_NOT_IMPLEMENTED;
+ DPRINT1("SRB_FUNCTION_RELEASE_QUEUE\n");
+
+ //
+ // release queue
+ //
+ USBSTOR_QueueRelease(PDODeviceExtension->LowerDeviceObject);
+
+ //
+ // set status success
+ //
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
break;
}
+
case SRB_FUNCTION_FLUSH:
+ case SRB_FUNCTION_FLUSH_QUEUE:
{
- DPRINT1("SRB_FUNCTION_FLUSH UNIMPLEMENTED\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
- }
- case SRB_FUNCTION_SET_LINK_TIMEOUT:
- {
- DPRINT1("SRB_FUNCTION_FLUSH UNIMPLEMENTED\n");
- Status = STATUS_NOT_IMPLEMENTED;
+ DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE\n");
+
+ //
+ // flush all requests
+ //
+ USBSTOR_QueueFlushIrps(PDODeviceExtension->LowerDeviceObject);
+
+ //
+ // set status success
+ //
+ Request->SrbStatus = SRB_STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
break;
}
default:
}
}
+ //
+ // complete request
+ //
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
PSTORAGE_PROPERTY_QUERY PropertyQuery;
PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader;
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor;
- ULONG FieldLengthVendor, FieldLengthProduct, FieldLengthRevision, TotalLength;
+ ULONG FieldLengthVendor, FieldLengthProduct, FieldLengthRevision, TotalLength, FieldLengthSerialNumber;
PPDO_DEVICE_EXTENSION PDODeviceExtension;
PUFI_INQUIRY_RESPONSE InquiryData;
PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor;
PUCHAR Buffer;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ UNICODE_STRING SerialNumber;
+ ANSI_STRING AnsiString;
+ NTSTATUS Status;
DPRINT1("USBSTOR_HandleQueryProperty\n");
//
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(PDODeviceExtension);
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+ //
+ // get device extension
+ //
+ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+ ASSERT(FDODeviceExtension);
+ ASSERT(FDODeviceExtension->Common.IsFDO);
//
// get inquiry data
FieldLengthRevision = USBSTOR_GetFieldLength(InquiryData->Revision, 4);
//
- // FIXME handle serial number
+ // is there a serial number
//
+ if (FDODeviceExtension->SerialNumber)
+ {
+ //
+ // get length
+ //
+ FieldLengthSerialNumber = wcslen(FDODeviceExtension->SerialNumber->bString);
+ }
+ else
+ {
+ //
+ // no serial number
+ //
+ FieldLengthSerialNumber = 0;
+ }
//
- // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 3 extra null bytes - 1
+ // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 4 extra null bytes - 1
// -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data
//
- TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + 2;
+ TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + FieldLengthSerialNumber + 3;
//
// check if output buffer is long enough
DeviceDescriptor->VendorIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR);
DeviceDescriptor->ProductIdOffset = DeviceDescriptor->VendorIdOffset + FieldLengthVendor + 1;
DeviceDescriptor->ProductRevisionOffset = DeviceDescriptor->ProductIdOffset + FieldLengthProduct + 1;
- DeviceDescriptor->SerialNumberOffset = 0; //FIXME
- DeviceDescriptor->RawPropertiesLength = FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + 3;
+ DeviceDescriptor->SerialNumberOffset = (FieldLengthSerialNumber > 0 ? DeviceDescriptor->ProductRevisionOffset + FieldLengthRevision + 1 : 0);
+ DeviceDescriptor->RawPropertiesLength = FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + FieldLengthSerialNumber + 3 + (FieldLengthSerialNumber > 0 ? + 1 : 0);
//
// copy descriptors
Buffer += FieldLengthRevision + 1;
//
- // TODO: copy revision
+ // copy serial number
//
+ if (FieldLengthSerialNumber)
+ {
+ //
+ // init unicode string
+ //
+ RtlInitUnicodeString(&SerialNumber, FDODeviceExtension->SerialNumber->bString);
+
+ //
+ // init ansi string
+ //
+ AnsiString.Buffer = (PCHAR)Buffer;
+ AnsiString.Length = 0;
+ AnsiString.MaximumLength = FieldLengthSerialNumber * sizeof(WCHAR);
+
+ //
+ // convert to ansi code
+ //
+ Status = RtlUnicodeStringToAnsiString(&AnsiString, &SerialNumber, FALSE);
+ ASSERT(Status == STATUS_SUCCESS);
+ }
+
DPRINT("Vendor %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->VendorIdOffset));
DPRINT("Product %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductIdOffset));
DPRINT("Revision %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductRevisionOffset));
+ DPRINT("Serial %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->SerialNumberOffset));
//
// done
{
PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PSCSI_ADAPTER_BUS_INFO BusInfo;
+ PSCSI_INQUIRY_DATA InquiryData;
+ PINQUIRYDATA ScsiInquiryData;
+ PUFI_INQUIRY_RESPONSE UFIInquiryResponse;
//
// get current stack location
//
Status = USBSTOR_HandleQueryProperty(DeviceObject, Irp);
}
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS)
- {
- //
- // query get scsi address
- //
- DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_GET_ADDRESS NOT implemented\n");
- Status = STATUS_NOT_SUPPORTED;
- }
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH)
{
//
DPRINT1("USBSTOR_HandleDeviceControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER NOT implemented\n");
Status = STATUS_NOT_SUPPORTED;
}
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_CAPABILITIES)
+ {
+ PIO_SCSI_CAPABILITIES Capabilities;
+
+ /* Legacy port capability query */
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(PVOID))
+ {
+ Capabilities = *((PVOID *)Irp->AssociatedIrp.SystemBuffer) = ExAllocatePool(NonPagedPool, sizeof(IO_SCSI_CAPABILITIES));
+ Irp->IoStatus.Information = sizeof(PVOID);
+ }
+ else
+ {
+ Capabilities = Irp->AssociatedIrp.SystemBuffer;
+ Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
+ }
+
+ if (Capabilities)
+ {
+ Capabilities->MaximumTransferLength = MAXULONG;
+ Capabilities->MaximumPhysicalPages = 25;
+ Capabilities->SupportedAsynchronousEvents = 0;
+ Capabilities->AlignmentMask = 0;
+ Capabilities->TaggedQueuing = FALSE;
+ Capabilities->AdapterScansDown = FALSE;
+ Capabilities->AdapterUsesPio = FALSE;
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_INQUIRY_DATA)
+ {
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ASSERT(PDODeviceExtension);
+ ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+ //
+ // get parameters
+ //
+ BusInfo = Irp->AssociatedIrp.SystemBuffer;
+ InquiryData = (PSCSI_INQUIRY_DATA)(BusInfo + 1);
+ ScsiInquiryData = (PINQUIRYDATA)InquiryData->InquiryData;
+
+
+ //
+ // get inquiry data
+ //
+ UFIInquiryResponse = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
+ ASSERT(UFIInquiryResponse);
+
+
+ BusInfo->NumberOfBuses = 1;
+ BusInfo->BusData[0].NumberOfLogicalUnits = 1; //FIXME
+ BusInfo->BusData[0].InitiatorBusId = 0;
+ BusInfo->BusData[0].InquiryDataOffset = sizeof(SCSI_ADAPTER_BUS_INFO);
+
+ InquiryData->PathId = 0;
+ InquiryData->TargetId = 0;
+ InquiryData->Lun = PDODeviceExtension->LUN & MAX_LUN;
+ InquiryData->DeviceClaimed = PDODeviceExtension->Claimed;
+ InquiryData->InquiryDataLength = sizeof(INQUIRYDATA);
+ InquiryData->NextInquiryDataOffset = 0;
+
+ RtlZeroMemory(ScsiInquiryData, sizeof(INQUIRYDATA));
+ ScsiInquiryData->DeviceType = UFIInquiryResponse->DeviceType;
+ ScsiInquiryData->DeviceTypeQualifier = (UFIInquiryResponse->RMB & 0x7F);
+
+ /* Hack for IoReadPartitionTable call in disk.sys */
+ ScsiInquiryData->RemovableMedia = (ScsiInquiryData->DeviceType != DIRECT_ACCESS_DEVICE) ? 1 : 0;
+
+ ScsiInquiryData->Versions = 0x04;
+ ScsiInquiryData->ResponseDataFormat = 0x02;
+ ScsiInquiryData->AdditionalLength = 31;
+ ScsiInquiryData->SoftReset = 0;
+ ScsiInquiryData->CommandQueue = 0;
+ ScsiInquiryData->LinkedCommands = 0;
+ ScsiInquiryData->RelativeAddressing = 0;
+
+ RtlCopyMemory(&ScsiInquiryData->VendorId, UFIInquiryResponse->Vendor, USBSTOR_GetFieldLength(UFIInquiryResponse->Vendor, 8));
+ RtlCopyMemory(&ScsiInquiryData->ProductId, UFIInquiryResponse->Product, USBSTOR_GetFieldLength(UFIInquiryResponse->Product, 16));
+
+ Irp->IoStatus.Information = sizeof(SCSI_ADAPTER_BUS_INFO) + sizeof(SCSI_INQUIRY_DATA) + sizeof(INQUIRYDATA) - 1;
+ Status = STATUS_SUCCESS;
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS)
+ {
+ PSCSI_ADDRESS Address = Irp->AssociatedIrp.SystemBuffer;
+
+ Address->Length = sizeof(SCSI_ADDRESS);
+ Address->PortNumber = 0;
+ Address->PathId = 0;
+ Address->TargetId = 0;
+ Address->Lun = (((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LUN & MAX_LUN);
+ Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
+
+ Status = STATUS_SUCCESS;
+ }
else
{
//