2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbstor/error.c
5 * PURPOSE: USB block storage device driver.
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
15 USBSTOR_GetEndpointStatus(
16 IN PDEVICE_OBJECT DeviceObject
,
17 IN UCHAR bEndpointAddress
,
26 DPRINT("Allocating URB\n");
27 Urb
= (PURB
)AllocateItem(NonPagedPool
, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
33 DPRINT1("OutofMemory!\n");
34 return STATUS_INSUFFICIENT_RESOURCES
;
40 UsbBuildGetStatusRequest(Urb
, URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
, bEndpointAddress
& 0x0F, Value
, NULL
, NULL
);
45 DPRINT1("Sending Request DeviceObject %x, Urb %x\n", DeviceObject
, Urb
);
46 Status
= USBSTOR_SyncUrbRequest(DeviceObject
, Urb
);
62 USBSTOR_ResetPipeWithHandle(
63 IN PDEVICE_OBJECT DeviceObject
,
64 IN USBD_PIPE_HANDLE PipeHandle
)
72 DPRINT("Allocating URB\n");
73 Urb
= (PURB
)AllocateItem(NonPagedPool
, sizeof(struct _URB_PIPE_REQUEST
));
79 DPRINT1("OutofMemory!\n");
80 return STATUS_INSUFFICIENT_RESOURCES
;
86 Urb
->UrbPipeRequest
.Hdr
.Length
= sizeof(struct _URB_PIPE_REQUEST
);
87 Urb
->UrbPipeRequest
.Hdr
.Function
= URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
;
88 Urb
->UrbPipeRequest
.PipeHandle
= PipeHandle
;
93 DPRINT1("Sending Request DeviceObject %x, Urb %x\n", DeviceObject
, Urb
);
94 Status
= USBSTOR_SyncUrbRequest(DeviceObject
, Urb
);
109 USBSTOR_HandleTransferError(
110 PDEVICE_OBJECT DeviceObject
,
111 PIRP_CONTEXT Context
)
114 PIO_STACK_LOCATION Stack
;
115 USBD_PIPE_HANDLE PipeHandle
;
116 PSCSI_REQUEST_BLOCK Request
;
119 DPRINT1("Entered Handle Transfer Error\n");
121 // Determine pipehandle
123 if (Context
->cbw
->CommandBlock
[0] == SCSIOP_WRITE
)
126 // write request used bulk out pipe
128 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
;
133 // default bulk in pipe
135 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
;
138 switch (Context
->Urb
.UrbHeader
.Status
)
140 case USBD_STATUS_STALL_PID
:
143 // First attempt to reset the pipe
145 DPRINT1("Resetting Pipe\n");
146 Status
= USBSTOR_ResetPipeWithHandle(Context
->FDODeviceExtension
->LowerDeviceObject
, PipeHandle
);
147 if (NT_SUCCESS(Status
))
149 Status
= STATUS_SUCCESS
;
153 DPRINT1("Failed to reset pipe %x\n", Status
);
156 // FIXME: Reset of pipe failed, attempt to reset port
159 Status
= STATUS_UNSUCCESSFUL
;
163 // FIXME: Handle more errors
167 DPRINT1("Error not handled\n");
168 Status
= STATUS_UNSUCCESSFUL
;
172 Stack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
173 Request
= (PSCSI_REQUEST_BLOCK
)Stack
->Parameters
.Others
.Argument1
;
174 pCDB
= (PCDB
)Request
->Cdb
;
175 if (Status
!= STATUS_SUCCESS
)
177 /* Complete the master IRP */
178 Context
->Irp
->IoStatus
.Status
= Status
;
179 Context
->Irp
->IoStatus
.Information
= 0;
180 USBSTOR_QueueTerminateRequest(Context
->PDODeviceExtension
->LowerDeviceObject
, Context
->Irp
);
181 IoCompleteRequest(Context
->Irp
, IO_NO_INCREMENT
);
183 /* Start the next request */
184 USBSTOR_QueueNextRequest(Context
->PDODeviceExtension
->LowerDeviceObject
);
186 /* Signal the context event */
188 KeSetEvent(Context
->Event
, 0, FALSE
);
190 /* Cleanup the IRP context */
191 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
192 FreeItem(Context
->TransferData
);
193 FreeItem(Context
->cbw
);
199 DPRINT1("Retrying\n");
200 Status
= USBSTOR_HandleExecuteSCSI(*Context
->PDODeviceExtension
->PDODeviceObject
, Context
->Irp
);
202 /* Cleanup the old IRP context */
203 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
204 FreeItem(Context
->TransferData
);
205 FreeItem(Context
->cbw
);
209 DPRINT1("USBSTOR_HandleTransferError returning with Status %x\n", Status
);
215 ErrorHandlerWorkItemRoutine(
219 PERRORHANDLER_WORKITEM_DATA WorkItemData
= (PERRORHANDLER_WORKITEM_DATA
)Context
;
221 Status
= USBSTOR_HandleTransferError(WorkItemData
->DeviceObject
, WorkItemData
->Context
);
224 // Free Work Item Data
226 ExFreePool(WorkItemData
);