[USBSTOR]
[reactos.git] / drivers / usb / usbstor / error.c
1 /*
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.
6 * PROGRAMMERS:
7 * James Tabor
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
10 */
11
12 #include "usbstor.h"
13
14 NTSTATUS
15 USBSTOR_ResetPipeWithHandle(
16 IN PDEVICE_OBJECT DeviceObject,
17 IN USBD_PIPE_HANDLE PipeHandle)
18 {
19 PURB Urb;
20 NTSTATUS Status;
21
22 //
23 // allocate urb
24 //
25 DPRINT1("Allocating URB\n");
26 Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
27 if (!Urb)
28 {
29 //
30 // out of memory
31 //
32 DPRINT1("OutofMemory!\n");
33 return STATUS_INSUFFICIENT_RESOURCES;
34 }
35
36 //
37 // initialize the urb
38 //
39 Urb->UrbPipeRequest.Hdr.Length = sizeof(struct _URB_PIPE_REQUEST);
40 Urb->UrbPipeRequest.Hdr.Function = URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL;
41 Urb->UrbPipeRequest.PipeHandle = PipeHandle;
42
43 //
44 // send the request
45 //
46 DPRINT1("Sending Request DeviceObject %x, Urb %x\n", DeviceObject, Urb);
47 Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
48
49 //
50 // free urb
51 //
52 FreeItem(Urb);
53
54 //
55 // done
56 //
57 return Status;
58 }
59
60 NTSTATUS
61 USBSTOR_HandleTransferError(
62 PDEVICE_OBJECT DeviceObject,
63 PIRP_CONTEXT Context)
64 {
65 NTSTATUS Status;
66 PIO_STACK_LOCATION Stack;
67 USBD_PIPE_HANDLE PipeHandle;
68 PSCSI_REQUEST_BLOCK Request;
69 PCDB pCDB;
70
71 DPRINT1("Entered Handle Transfer Error\n");
72 //
73 // Determine pipehandle
74 //
75 if (Context->cbw->CommandBlock[0] == SCSIOP_WRITE)
76 {
77 //
78 // write request used bulk out pipe
79 //
80 PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle;
81 }
82 else
83 {
84 //
85 // default bulk in pipe
86 //
87 PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle;
88 }
89
90 switch (Context->Urb.UrbHeader.Status)
91 {
92 case USBD_STATUS_STALL_PID:
93 {
94 //
95 // First attempt to reset the pipe
96 //
97 DPRINT1("Resetting Pipe\n");
98 Status = USBSTOR_ResetPipeWithHandle(DeviceObject, PipeHandle);
99 if (NT_SUCCESS(Status))
100 {
101 Status = STATUS_SUCCESS;
102 break;
103 }
104
105 DPRINT1("Failed to reset pipe %x\n", Status);
106
107 //
108 // FIXME: Reset of pipe failed, attempt to reset port
109 //
110
111 Status = STATUS_UNSUCCESSFUL;
112 break;
113 }
114 //
115 // FIXME: Handle more errors
116 //
117 default:
118 {
119 DPRINT1("Error not handled\n");
120 Status = STATUS_UNSUCCESSFUL;
121 }
122 }
123
124 Stack = IoGetCurrentIrpStackLocation(Context->Irp);
125 Request = (PSCSI_REQUEST_BLOCK)Stack->Parameters.Others.Argument1;
126 pCDB = (PCDB)Request->Cdb;
127 if (Status != STATUS_SUCCESS)
128 {
129 /* Complete the master IRP */
130 Context->Irp->IoStatus.Status = Status;
131 Context->Irp->IoStatus.Information = 0;
132 IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
133
134 /* Start the next request */
135 USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, TRUE);
136 USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
137
138 /* Signal the context event */
139 if (Context->Event)
140 KeSetEvent(Context->Event, 0, FALSE);
141
142 /* Cleanup the IRP context */
143 if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
144 FreeItem(Context->TransferData);
145 FreeItem(Context->cbw);
146 FreeItem(Context);
147 }
148 else
149 {
150
151 DPRINT1("Retrying\n");
152 Status = USBSTOR_HandleExecuteSCSI(DeviceObject, Context->Irp);
153
154 /* Cleanup the old IRP context */
155 if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
156 FreeItem(Context->TransferData);
157 FreeItem(Context->cbw);
158 FreeItem(Context);
159 }
160
161 DPRINT1("USBSTOR_HandleTransferError returning with Status %x\n", Status);
162 return Status;
163 }
164
165 VOID
166 NTAPI
167 ErrorHandlerWorkItemRoutine(
168 PVOID Context)
169 {
170 NTSTATUS Status;
171 PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
172
173 Status = USBSTOR_HandleTransferError(WorkItemData->DeviceObject, WorkItemData->Context);
174
175 //
176 // Free Work Item Data
177 //
178 ExFreePool(WorkItemData);
179 }