diff --git a/drivers/usb/usbstor/disk.c b/drivers/usb/usbstor/disk.c index fa5d464442b..f185385fdcf 100644 --- a/drivers/usb/usbstor/disk.c +++ b/drivers/usb/usbstor/disk.c @@ -20,6 +20,7 @@ USBSTOR_HandleExecuteSCSI( { PCDB pCDB; NTSTATUS Status; + ULONG TransferredLength; // // get SCSI command data block @@ -73,6 +74,35 @@ USBSTOR_HandleExecuteSCSI( 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 capacity + // + 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 18a5680f9ee..9706c138915 100644 --- a/drivers/usb/usbstor/scsi.c +++ b/drivers/usb/usbstor/scsi.c @@ -435,7 +435,7 @@ USBSTOR_SendCapacityCmd( } // - // initialize inquiry cmd + // initialize capacity cmd // RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD)); Cmd.Code = SCSIOP_INQUIRY; @@ -443,7 +443,7 @@ USBSTOR_SendCapacityCmd( Cmd.AllocationLength = sizeof(UFI_INQUIRY_RESPONSE); // - // now send inquiry cmd + // now send capacity cmd // Status = USBSTOR_SendCBW(DeviceObject, UFI_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_CAPACITY_RESPONSE), &OutControl); if (!NT_SUCCESS(Status)) @@ -523,3 +523,123 @@ USBSTOR_SendCapacityCmd( return Status; } +NTSTATUS +USBSTOR_SendModeSenseCmd( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PSCSI_REQUEST_BLOCK Request, + OUT PULONG TransferBufferLength) +{ + UFI_SENSE_CMD Cmd; + CSW CSW; + NTSTATUS Status; + PVOID Response; + PPDO_DEVICE_EXTENSION PDODeviceExtension; + PCBW OutControl; + PCDB pCDB; + + // + // get SCSI command data block + // + pCDB = (PCDB)Request->Cdb; + + // + // get PDO device extension + // + PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // allocate sense response from non paged pool + // + Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, Request->DataTransferLength); + if (!Response) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // initialize mode sense cmd + // + RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD)); + Cmd.Code = SCSIOP_MODE_SENSE; + Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN); + Cmd.PageCode = pCDB->MODE_SENSE.PageCode; + Cmd.PC = pCDB->MODE_SENSE.Pc; + Cmd.AllocationLength = pCDB->MODE_SENSE.AllocationLength; + + // + // now send mode sense cmd + // + Status = USBSTOR_SendCBW(DeviceObject, UFI_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, &OutControl); + if (!NT_SUCCESS(Status)) + { + // + // failed to send CBW + // + DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status); + FreeItem(Response); + ASSERT(FALSE); + return Status; + } + + // + // now send data block response + // + Status = USBSTOR_SendData(DeviceObject, Request->DataTransferLength, Response); + if (!NT_SUCCESS(Status)) + { + // + // failed to send CBW + // + DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status); + FreeItem(Response); + ASSERT(FALSE); + return Status; + } + + // + // 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; +} + diff --git a/drivers/usb/usbstor/usbstor.h b/drivers/usb/usbstor/usbstor.h index 7f663dc5116..78a8e8a51a8 100644 --- a/drivers/usb/usbstor/usbstor.h +++ b/drivers/usb/usbstor/usbstor.h @@ -149,6 +149,22 @@ typedef struct ULONG BlockLength; // block length in bytes }UFI_CAPACITY_RESPONSE, *PUFI_CAPACITY_RESPONSE; +//-------------------------------------------------------------------------------------------------------------------------------------------- +// +// UFI sense mode cmd +// +typedef struct +{ + UCHAR Code; // operation code + UCHAR LUN; // lun address + UCHAR PageCode:6; // page code selector + UCHAR PC:2; // type of parameters to be returned + UCHAR Reserved[4]; // reserved 0x00 + USHORT AllocationLength; // parameters length + UCHAR Reserved1[3]; +}UFI_SENSE_CMD, *PUFI_SENSE_CMD; + +C_ASSERT(sizeof(UFI_CAPACITY_CMD) == 12); //--------------------------------------------------------------------- // @@ -248,6 +264,12 @@ USBSTOR_SendCapacityCmd( OUT PREAD_CAPACITY_DATA_EX CapacityDataEx, OUT PREAD_CAPACITY_DATA CapacityData); +NTSTATUS +USBSTOR_SendModeSenseCmd( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PSCSI_REQUEST_BLOCK Request, + OUT PULONG TransferBufferLength); + //--------------------------------------------------------------------- // // disk.c routines @@ -261,3 +283,5 @@ NTSTATUS USBSTOR_HandleDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); + +