VOID NTAPI USBSTOR_Cancel( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PFDO_DEVICE_EXTENSION FDODeviceExtension; // // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); ASSERT(FDODeviceExtension->Common.IsFDO); // // acquire irp list lock // KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock); // // remove the irp from the list // RemoveEntryList(&Irp->Tail.Overlay.ListEntry); // // release irp list lock // KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock); // // now release the cancel lock // IoReleaseCancelSpinLock(Irp->CancelIrql); // // set cancel status // Irp->IoStatus.Status = STATUS_CANCELLED; // // now cancel the irp // USBSTOR_QueueTerminateRequest(DeviceObject, Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); // // start the next one // USBSTOR_QueueNextRequest(DeviceObject); }
VOID NTAPI USBSTOR_CancelIo( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PFDO_DEVICE_EXTENSION FDODeviceExtension; // // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); ASSERT(FDODeviceExtension->Common.IsFDO); // // this IRP isn't in our list here // // // now release the cancel lock // IoReleaseCancelSpinLock(Irp->CancelIrql); // // set cancel status // Irp->IoStatus.Status = STATUS_CANCELLED; // // now cancel the irp // USBSTOR_QueueTerminateRequest(DeviceObject, Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); // // start the next one // USBSTOR_QueueNextRequest(DeviceObject); }
VOID NTAPI USBSTOR_StartIo( PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION IoStack; PFDO_DEVICE_EXTENSION FDODeviceExtension; PPDO_DEVICE_EXTENSION PDODeviceExtension; KIRQL OldLevel; BOOLEAN ResetInProgress; DPRINT("USBSTOR_StartIo\n"); // // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO); // // acquire cancel spinlock // IoAcquireCancelSpinLock(&OldLevel); // // set cancel routine to zero // IoSetCancelRoutine(Irp, NULL); // // check if the irp has been cancelled // if (Irp->Cancel) { // // irp has been cancelled, release cancel spinlock // IoReleaseCancelSpinLock(OldLevel); // // irp is cancelled // Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; // // terminate request // USBSTOR_QueueTerminateRequest(DeviceObject, Irp); // // complete request // IoCompleteRequest(Irp, IO_NO_INCREMENT); // // queue next request // USBSTOR_QueueNextRequest(DeviceObject); // // done // return; } // // release cancel spinlock // IoReleaseCancelSpinLock(OldLevel); // // acquire lock // KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); // // check reset is in progress // ResetInProgress = FDODeviceExtension->ResetInProgress; ASSERT(ResetInProgress == FALSE); // // release lock // KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); // // get current irp stack location // IoStack = IoGetCurrentIrpStackLocation(Irp); // // get pdo device extension // PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension; // // sanity check // ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); // // is a reset in progress // if (ResetInProgress) { // // hard reset is in progress // Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; USBSTOR_QueueTerminateRequest(DeviceObject, Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); return; } // // execute scsi // USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp, 0); // // FIXME: handle error // }
NTSTATUS USBSTOR_SendModeSense( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG RetryCount) { #if 0 UFI_SENSE_CMD Cmd; NTSTATUS Status; PVOID Response; PCBW OutControl; PCDB pCDB; PUFI_MODE_PARAMETER_HEADER Header; #endif PPDO_DEVICE_EXTENSION PDODeviceExtension; PIO_STACK_LOCATION IoStack; PSCSI_REQUEST_BLOCK Request; // // get PDO device extension // PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); // // get current stack location // IoStack = IoGetCurrentIrpStackLocation(Irp); // // get request block // Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; RtlZeroMemory(Request->DataBuffer, Request->DataTransferLength); Request->SrbStatus = SRB_STATUS_SUCCESS; Irp->IoStatus.Information = Request->DataTransferLength; Irp->IoStatus.Status = STATUS_SUCCESS; USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); // // start next request // USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject); return STATUS_SUCCESS; #if 0 // // 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; } // // sanity check // // Supported pages // MODE_PAGE_ERROR_RECOVERY // MODE_PAGE_FLEXIBILE // MODE_PAGE_LUN_MAPPING // MODE_PAGE_FAULT_REPORTING // MODE_SENSE_RETURN_ALL // // 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 = HTONS(pCDB->MODE_SENSE.AllocationLength); DPRINT1("PageCode %x\n", pCDB->MODE_SENSE.PageCode); DPRINT1("PC %x\n", pCDB->MODE_SENSE.Pc); // // now send mode sense cmd // Status = USBSTOR_SendCBW(DeviceObject, UFI_SENSE_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; } Header = (PUFI_MODE_PARAMETER_HEADER)Response; // // TODO: build layout // // first struct is the header // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10 // // followed by // MODE_PARAMETER_BLOCK // // UNIMPLEMENTED // // 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; #endif }
NTSTATUS NTAPI USBSTOR_CSWCompletionRoutine( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Ctx) { PIRP_CONTEXT Context; PIO_STACK_LOCATION IoStack; PSCSI_REQUEST_BLOCK Request; PCDB pCDB; PREAD_CAPACITY_DATA_EX CapacityDataEx; PREAD_CAPACITY_DATA CapacityData; PUFI_CAPACITY_RESPONSE Response; NTSTATUS Status; PURB Urb; // // access context // Context = (PIRP_CONTEXT)Ctx; // // is there a mdl // if (Context->TransferBufferMDL) { // // is there an irp associated // if (Context->Irp) { // // did we allocate the mdl // if (Context->TransferBufferMDL != Context->Irp->MdlAddress) { // // free mdl // IoFreeMdl(Context->TransferBufferMDL); } } else { // // free mdl // IoFreeMdl(Context->TransferBufferMDL); } } DPRINT("USBSTOR_CSWCompletionRoutine Status %x\n", Irp->IoStatus.Status); if (!NT_SUCCESS(Irp->IoStatus.Information)) { if (Context->ErrorIndex == 0) { // // increment error index // Context->ErrorIndex = 1; // // clear stall and resend cbw // Status = USBSTOR_QueueWorkItem(Context, Irp); ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED); return STATUS_MORE_PROCESSING_REQUIRED; } // // perform reset recovery // Context->ErrorIndex = 2; IoFreeIrp(Irp); Status = USBSTOR_QueueWorkItem(Context, NULL); ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED); return STATUS_MORE_PROCESSING_REQUIRED; } if (!USBSTOR_IsCSWValid(Context)) { // // perform reset recovery // Context->ErrorIndex = 2; IoFreeIrp(Irp); Status = USBSTOR_QueueWorkItem(Context, NULL); ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED); return STATUS_MORE_PROCESSING_REQUIRED; } // // get current stack location // IoStack = IoGetCurrentIrpStackLocation(Context->Irp); // // get request block // Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; ASSERT(Request); Status = Irp->IoStatus.Status; Urb = &Context->Urb; // // get SCSI command data block // pCDB = (PCDB)Request->Cdb; Request->SrbStatus = SRB_STATUS_SUCCESS; // // read capacity needs special work // if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY) { // // get output buffer // Response = (PUFI_CAPACITY_RESPONSE)Context->TransferData; // // store in pdo // Context->PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength); Context->PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress); if (Request->DataTransferLength == sizeof(READ_CAPACITY_DATA_EX)) { // // get input buffer // CapacityDataEx = (PREAD_CAPACITY_DATA_EX)Request->DataBuffer; // // set result // CapacityDataEx->BytesPerBlock = Response->BlockLength; CapacityDataEx->LogicalBlockAddress.QuadPart = Response->LastLogicalBlockAddress; Irp->IoStatus.Information = sizeof(READ_CAPACITY_DATA_EX); } else { // // get input buffer // CapacityData = (PREAD_CAPACITY_DATA)Request->DataBuffer; // // set result // CapacityData->BytesPerBlock = Response->BlockLength; CapacityData->LogicalBlockAddress = Response->LastLogicalBlockAddress; Irp->IoStatus.Information = sizeof(READ_CAPACITY_DATA); } // // free response // FreeItem(Context->TransferData); } // // free cbw // FreeItem(Context->cbw); // // FIXME: check status // Context->Irp->IoStatus.Status = Irp->IoStatus.Status; Context->Irp->IoStatus.Information = Context->TransferDataLength; // // terminate current request // USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, Context->Irp); // // complete request // IoCompleteRequest(Context->Irp, IO_NO_INCREMENT); // // start next request // USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject); // // free our allocated irp // IoFreeIrp(Irp); // // free context // FreeItem(Context); // // done // return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS USBSTOR_HandleExecuteSCSI( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG RetryCount) { PCDB pCDB; NTSTATUS Status; PIO_STACK_LOCATION IoStack; PSCSI_REQUEST_BLOCK Request; PPDO_DEVICE_EXTENSION PDODeviceExtension; // // get PDO device extension // PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); // // get current stack location // IoStack = IoGetCurrentIrpStackLocation(Irp); // // get request block // Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; // // get SCSI command data block // pCDB = (PCDB)Request->Cdb; DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]); if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY) { // // sanity checks // ASSERT(Request->DataBuffer); DPRINT("SCSIOP_READ_CAPACITY Length %lu\n", Request->DataTransferLength); Status = USBSTOR_SendCapacity(DeviceObject, Irp, RetryCount); } else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE) { DPRINT("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request->DataTransferLength); ASSERT(pCDB->MODE_SENSE.AllocationLength == Request->DataTransferLength); ASSERT(Request->DataBuffer); // // send mode sense command // Status = USBSTOR_SendModeSense(DeviceObject, Irp, RetryCount); } else if (pCDB->AsByte[0] == SCSIOP_READ_FORMATTED_CAPACITY) { DPRINT("SCSIOP_READ_FORMATTED_CAPACITY DataTransferLength %lu\n", Request->DataTransferLength); // // send read format capacity // Status = USBSTOR_SendFormatCapacity(DeviceObject, Irp, RetryCount); } else if (pCDB->AsByte[0] == SCSIOP_INQUIRY) { DPRINT("SCSIOP_INQUIRY DataTransferLength %lu\n", Request->DataTransferLength); // // send read format capacity // Status = USBSTOR_SendInquiry(DeviceObject, Irp, RetryCount); } else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ || pCDB->MODE_SENSE.OperationCode == SCSIOP_WRITE) { DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request->DataTransferLength); // // send read / write command // Status = USBSTOR_SendReadWrite(DeviceObject, Irp, RetryCount); } else if (pCDB->AsByte[0] == SCSIOP_MEDIUM_REMOVAL) { DPRINT("SCSIOP_MEDIUM_REMOVAL\n"); // // just complete the request // Request->SrbStatus = SRB_STATUS_SUCCESS; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = Request->DataTransferLength; USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); // // start next request // USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject); return STATUS_SUCCESS; } else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY) { DPRINT("SCSIOP_TEST_UNIT_READY\n"); // // send test unit command // Status = USBSTOR_SendTestUnit(DeviceObject, Irp, RetryCount); } else { // Unknown request. Simply forward DPRINT1("Forwarding unknown Operation Code %x\n", pCDB->AsByte[0]); Status = USBSTOR_SendUnknownRequest(DeviceObject, Irp, RetryCount); } return Status; }