diff --git a/drivers/usb/usbstor/disk.c b/drivers/usb/usbstor/disk.c index 4384c4fc591..aefbd015e6f 100644 --- a/drivers/usb/usbstor/disk.c +++ b/drivers/usb/usbstor/disk.c @@ -103,6 +103,35 @@ USBSTOR_HandleExecuteSCSI( 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 retrieve sense data + // + Irp->IoStatus.Information = 0; + Request->SrbStatus = SRB_STATUS_ERROR; + } + } + else { UNIMPLEMENTED; diff --git a/drivers/usb/usbstor/scsi.c b/drivers/usb/usbstor/scsi.c index 8b97c514ac3..259335e0562 100644 --- a/drivers/usb/usbstor/scsi.c +++ b/drivers/usb/usbstor/scsi.c @@ -489,6 +489,12 @@ USBSTOR_SendCapacityCmd( CapacityData->BytesPerBlock = Response->BlockLength; } + // + // store result in device extension + // + PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress); + PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength); + // // send csw // @@ -672,3 +678,138 @@ USBSTOR_SendModeSenseCmd( return Status; } +NTSTATUS +USBSTOR_SendReadCmd( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PSCSI_REQUEST_BLOCK Request, + OUT PULONG TransferBufferLength) +{ + UFI_READ_CMD Cmd; + CSW CSW; + NTSTATUS Status; + PVOID Response; + PPDO_DEVICE_EXTENSION PDODeviceExtension; + PCBW OutControl; + PCDB pCDB; + ULONG BlockCount; + + // + // get SCSI command data block + // + pCDB = (PCDB)Request->Cdb; + + // + // get PDO device extension + // + PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // allocate read buffer response from non paged pool + // + Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, Request->DataTransferLength); + if (!Response) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // FIXME: support more logical blocks + // + ASSERT(Request->DataTransferLength == PDODeviceExtension->BlockLength); + + // + // block count + // + BlockCount = Request->DataTransferLength / PDODeviceExtension->BlockLength; + + // + // initialize read sense cmd + // + RtlZeroMemory(&Cmd, sizeof(UFI_READ_CMD)); + Cmd.Code = SCSIOP_READ; + Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN); + Cmd.ContiguousLogicBlocks = _byteswap_ushort(BlockCount); + + RtlCopyMemory(&Cmd.LogicalBlockAddress, pCDB->READ12.LogicalBlock, sizeof(UCHAR) * 4); + + DPRINT1("BlockAddress %lu BlockCount %lu BlockLength %lu\n", NTOHL(Cmd.LogicalBlockAddress), BlockCount, PDODeviceExtension->BlockLength); + + // + // now send read cmd + // + Status = USBSTOR_SendCBW(DeviceObject, UFI_READ_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, &OutControl); + if (!NT_SUCCESS(Status)) + { + // + // failed to send CBW + // + DPRINT1("USBSTOR_SendReadCmd> USBSTOR_SendCBW failed with %x\n", Status); + FreeItem(Response); + ASSERT(FALSE); + return Status; + } + + // + // now read the logical block + // + Status = USBSTOR_SendData(DeviceObject, Request->DataTransferLength, Response); + if (!NT_SUCCESS(Status)) + { + // + // failed to read logical block + // + DPRINT1("USBSTOR_SendReadCmd> USBSTOR_SendData failed with %x\n", Status); + FreeItem(Response); + ASSERT(FALSE); + return Status; + } + + + DbgBreakPoint(); + + // + // send csw + // + Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW); + + DPRINT1("------------------------\n"); + DPRINT1("CSW %p\n", &CSW); + DPRINT1("Signature %x\n", CSW.Signature); + DPRINT1("Tag %x\n", CSW.Tag); + DPRINT1("DataResidue %x\n", CSW.DataResidue); + DPRINT1("Status %x\n", CSW.Status); + + // + // FIXME: handle error + // + ASSERT(CSW.Status == 0); + ASSERT(CSW.DataResidue == 0); + + // + // calculate transfer length + // + *TransferBufferLength = Request->DataTransferLength - CSW.DataResidue; + + // + // copy buffer + // + RtlCopyMemory(Request->DataBuffer, Response, *TransferBufferLength); + + // + // free item + // + FreeItem(OutControl); + + // + // free response + // + FreeItem(Response); + + // + // done + // + return Status; +}