1 /* 2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: USB block storage device driver. 5 * COPYRIGHT: 2005-2006 James Tabor 6 * 2011-2012 Michael Martin (michael.martin@reactos.org) 7 * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org) 8 */ 9 10 #include "usbstor.h" 11 12 #define NDEBUG 13 #include <debug.h> 14 15 16 VOID 17 USBSTOR_QueueInitialize( 18 PFDO_DEVICE_EXTENSION FDODeviceExtension) 19 { 20 ASSERT(FDODeviceExtension->Common.IsFDO); 21 KeInitializeSpinLock(&FDODeviceExtension->IrpListLock); 22 InitializeListHead(&FDODeviceExtension->IrpListHead); 23 KeInitializeEvent(&FDODeviceExtension->NoPendingRequests, NotificationEvent, TRUE); 24 } 25 26 VOID 27 NTAPI 28 USBSTOR_CancelIo( 29 IN PDEVICE_OBJECT DeviceObject, 30 IN PIRP Irp) 31 { 32 PFDO_DEVICE_EXTENSION FDODeviceExtension; 33 34 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 35 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL); 36 ASSERT(FDODeviceExtension->Common.IsFDO); 37 38 // this IRP isn't in our list here 39 // now release the cancel lock 40 IoReleaseCancelSpinLock(Irp->CancelIrql); 41 Irp->IoStatus.Status = STATUS_CANCELLED; 42 43 USBSTOR_QueueTerminateRequest(DeviceObject, Irp); 44 IoCompleteRequest(Irp, IO_NO_INCREMENT); 45 46 USBSTOR_QueueNextRequest(DeviceObject); 47 } 48 49 VOID 50 NTAPI 51 USBSTOR_Cancel( 52 IN PDEVICE_OBJECT DeviceObject, 53 IN PIRP Irp) 54 { 55 PFDO_DEVICE_EXTENSION FDODeviceExtension; 56 57 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 58 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL); 59 ASSERT(FDODeviceExtension->Common.IsFDO); 60 61 KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock); 62 RemoveEntryList(&Irp->Tail.Overlay.ListEntry); 63 KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock); 64 65 IoReleaseCancelSpinLock(Irp->CancelIrql); 66 Irp->IoStatus.Status = STATUS_CANCELLED; 67 68 USBSTOR_QueueTerminateRequest(DeviceObject, Irp); 69 IoCompleteRequest(Irp, IO_NO_INCREMENT); 70 71 USBSTOR_QueueNextRequest(DeviceObject); 72 } 73 74 BOOLEAN 75 USBSTOR_QueueAddIrp( 76 IN PDEVICE_OBJECT DeviceObject, 77 IN PIRP Irp) 78 { 79 PDRIVER_CANCEL OldDriverCancel; 80 KIRQL OldLevel; 81 PFDO_DEVICE_EXTENSION FDODeviceExtension; 82 BOOLEAN IrpListFreeze; 83 BOOLEAN SrbProcessing; 84 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); 85 PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 86 87 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 88 ASSERT(FDODeviceExtension->Common.IsFDO); 89 90 IoMarkIrpPending(Irp); 91 92 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); 93 94 SrbProcessing = FDODeviceExtension->IrpPendingCount != 0; 95 96 if (SrbProcessing) 97 { 98 // add irp to queue 99 InsertTailList(&FDODeviceExtension->IrpListHead, &Irp->Tail.Overlay.ListEntry); 100 } 101 102 FDODeviceExtension->IrpPendingCount++; 103 KeClearEvent(&FDODeviceExtension->NoPendingRequests); 104 105 // check if queue is freezed 106 IrpListFreeze = BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE); 107 108 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); 109 110 // synchronize with cancellations by holding the cancel lock 111 IoAcquireCancelSpinLock(&Irp->CancelIrql); 112 113 if (SrbProcessing) 114 { 115 ASSERT(FDODeviceExtension->ActiveSrb != NULL); 116 117 OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_Cancel); 118 } 119 else 120 { 121 ASSERT(FDODeviceExtension->ActiveSrb == NULL); 122 123 FDODeviceExtension->ActiveSrb = Request; 124 OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_CancelIo); 125 } 126 127 // check if the irp has already been cancelled 128 if (Irp->Cancel && OldDriverCancel == NULL) 129 { 130 // cancel irp 131 Irp->CancelRoutine(DeviceObject, Irp); 132 return FALSE; 133 } 134 135 IoReleaseCancelSpinLock(Irp->CancelIrql); 136 137 // if list is freezed, dont start this packet 138 DPRINT("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze, FDODeviceExtension->IrpPendingCount); 139 140 return (IrpListFreeze || SrbProcessing); 141 } 142 143 PIRP 144 USBSTOR_RemoveIrp( 145 IN PDEVICE_OBJECT DeviceObject) 146 { 147 KIRQL OldLevel; 148 PFDO_DEVICE_EXTENSION FDODeviceExtension; 149 PLIST_ENTRY Entry; 150 PIRP Irp = NULL; 151 152 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 153 ASSERT(FDODeviceExtension->Common.IsFDO); 154 155 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); 156 157 if (!IsListEmpty(&FDODeviceExtension->IrpListHead)) 158 { 159 Entry = RemoveHeadList(&FDODeviceExtension->IrpListHead); 160 161 // get offset to start of irp 162 Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); 163 } 164 165 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); 166 167 return Irp; 168 } 169 170 VOID 171 USBSTOR_QueueWaitForPendingRequests( 172 IN PDEVICE_OBJECT DeviceObject) 173 { 174 PFDO_DEVICE_EXTENSION FDODeviceExtension; 175 176 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 177 178 KeWaitForSingleObject(&FDODeviceExtension->NoPendingRequests, 179 Executive, 180 KernelMode, 181 FALSE, 182 NULL); 183 } 184 185 VOID 186 USBSTOR_QueueTerminateRequest( 187 IN PDEVICE_OBJECT FDODeviceObject, 188 IN PIRP Irp) 189 { 190 KIRQL OldLevel; 191 PFDO_DEVICE_EXTENSION FDODeviceExtension; 192 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); 193 PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 194 195 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)FDODeviceObject->DeviceExtension; 196 ASSERT(FDODeviceExtension->Common.IsFDO); 197 198 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); 199 200 FDODeviceExtension->IrpPendingCount--; 201 202 // check if this was our current active SRB 203 if (FDODeviceExtension->ActiveSrb == Request) 204 { 205 // indicate processing is completed 206 FDODeviceExtension->ActiveSrb = NULL; 207 } 208 209 // Set the event if nothing else is pending 210 if (FDODeviceExtension->IrpPendingCount == 0 && 211 FDODeviceExtension->ActiveSrb == NULL) 212 { 213 KeSetEvent(&FDODeviceExtension->NoPendingRequests, IO_NO_INCREMENT, FALSE); 214 } 215 216 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); 217 } 218 219 VOID 220 USBSTOR_QueueNextRequest( 221 IN PDEVICE_OBJECT DeviceObject) 222 { 223 PFDO_DEVICE_EXTENSION FDODeviceExtension; 224 PIRP Irp; 225 PIO_STACK_LOCATION IoStack; 226 PSCSI_REQUEST_BLOCK Request; 227 228 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 229 ASSERT(FDODeviceExtension->Common.IsFDO); 230 231 // check first if there's already a request pending or the queue is frozen 232 if (FDODeviceExtension->ActiveSrb != NULL || 233 BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE)) 234 { 235 // no work to do yet 236 return; 237 } 238 239 // remove first irp from list 240 Irp = USBSTOR_RemoveIrp(DeviceObject); 241 242 // is there an irp pending 243 if (!Irp) 244 { 245 // no work to do 246 IoStartNextPacket(DeviceObject, TRUE); 247 return; 248 } 249 250 IoStack = IoGetCurrentIrpStackLocation(Irp); 251 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 252 ASSERT(Request); 253 254 FDODeviceExtension->ActiveSrb = Request; 255 256 // start next packet 257 IoStartPacket(DeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo); 258 IoStartNextPacket(DeviceObject, TRUE); 259 } 260 261 VOID 262 USBSTOR_QueueRelease( 263 IN PDEVICE_OBJECT DeviceObject) 264 { 265 PFDO_DEVICE_EXTENSION FDODeviceExtension; 266 PIRP Irp; 267 KIRQL OldLevel; 268 PIO_STACK_LOCATION IoStack; 269 PSCSI_REQUEST_BLOCK Request; 270 271 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 272 ASSERT(FDODeviceExtension->Common.IsFDO); 273 274 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); 275 276 // clear freezed status 277 FDODeviceExtension->Flags &= ~USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE; 278 279 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); 280 281 // grab newest irp 282 Irp = USBSTOR_RemoveIrp(DeviceObject); 283 284 if (!Irp) 285 { 286 return; 287 } 288 289 IoStack = IoGetCurrentIrpStackLocation(Irp); 290 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 291 292 IoStartPacket(DeviceObject, 293 Irp, 294 &Request->QueueSortKey, 295 USBSTOR_CancelIo); 296 } 297 298 VOID 299 NTAPI 300 USBSTOR_StartIo( 301 PDEVICE_OBJECT DeviceObject, 302 PIRP Irp) 303 { 304 PIO_STACK_LOCATION IoStack; 305 PSCSI_REQUEST_BLOCK Request; 306 PFDO_DEVICE_EXTENSION FDODeviceExtension; 307 PPDO_DEVICE_EXTENSION PDODeviceExtension; 308 KIRQL OldLevel; 309 BOOLEAN ResetInProgress; 310 311 DPRINT("USBSTOR_StartIo\n"); 312 313 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 314 ASSERT(FDODeviceExtension->Common.IsFDO); 315 316 IoAcquireCancelSpinLock(&OldLevel); 317 318 IoSetCancelRoutine(Irp, NULL); 319 320 // check if the irp has been cancelled 321 if (Irp->Cancel) 322 { 323 IoReleaseCancelSpinLock(OldLevel); 324 325 Irp->IoStatus.Status = STATUS_CANCELLED; 326 Irp->IoStatus.Information = 0; 327 328 USBSTOR_QueueTerminateRequest(DeviceObject, Irp); 329 IoCompleteRequest(Irp, IO_NO_INCREMENT); 330 USBSTOR_QueueNextRequest(DeviceObject); 331 return; 332 } 333 334 IoReleaseCancelSpinLock(OldLevel); 335 336 KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldLevel); 337 ResetInProgress = BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_DEVICE_RESETTING); 338 KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldLevel); 339 340 IoStack = IoGetCurrentIrpStackLocation(Irp); 341 342 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension; 343 Request = IoStack->Parameters.Scsi.Srb; 344 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); 345 346 if (ResetInProgress) 347 { 348 // hard reset is in progress 349 Request->SrbStatus = SRB_STATUS_NO_DEVICE; 350 Request->DataTransferLength = 0; 351 Irp->IoStatus.Information = 0; 352 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; 353 USBSTOR_QueueTerminateRequest(DeviceObject, Irp); 354 IoCompleteRequest(Irp, IO_NO_INCREMENT); 355 USBSTOR_QueueNextRequest(DeviceObject); 356 return; 357 } 358 359 USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp); 360 361 // FIXME: handle error 362 } 363