Something went wrong. Try again.
Reactos
Something went wrong. Try again.
14 kB · 670 lines
C
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671/* * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver * LICENSE: GPL - See COPYING in the top level directory * FILE: drivers/usb/usbstor/queue.c * PURPOSE: USB block storage device driver. * PROGRAMMERS: * James Tabor * Michael Martin (michael.martin@reactos.org) * Johannes Anderwald (johannes.anderwald@reactos.org) */
#include "usbstor.h"
#define NDEBUG#include <debug.h>
VOIDUSBSTOR_QueueInitialize( PFDO_DEVICE_EXTENSION FDODeviceExtension){ // // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO);
// // initialize queue lock // KeInitializeSpinLock(&FDODeviceExtension->IrpListLock);
// // initialize irp list head // InitializeListHead(&FDODeviceExtension->IrpListHead);
// // initialize event // KeInitializeEvent(&FDODeviceExtension->NoPendingRequests, NotificationEvent, TRUE);}
VOIDNTAPIUSBSTOR_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);}
VOIDNTAPIUSBSTOR_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);}
BOOLEANUSBSTOR_QueueAddIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PDRIVER_CANCEL OldDriverCancel; KIRQL OldLevel; PFDO_DEVICE_EXTENSION FDODeviceExtension; BOOLEAN IrpListFreeze; BOOLEAN SrbProcessing; PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
// // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
// // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO);
// // mark irp pending // IoMarkIrpPending(Irp);
// // acquire lock // KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
// // check if there are irp pending // SrbProcessing = FDODeviceExtension->IrpPendingCount != 0;
if (SrbProcessing) { // // add irp to queue // InsertTailList(&FDODeviceExtension->IrpListHead, &Irp->Tail.Overlay.ListEntry); }
// // increment pending count // FDODeviceExtension->IrpPendingCount++;
// // clear the no requests pending event // KeClearEvent(&FDODeviceExtension->NoPendingRequests);
// // check if queue is freezed // IrpListFreeze = FDODeviceExtension->IrpListFreeze;
// // release list lock // KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
// // synchronize with cancellations by holding the cancel lock // IoAcquireCancelSpinLock(&Irp->CancelIrql);
// // now set the driver cancel routine // if (SrbProcessing) { ASSERT(FDODeviceExtension->ActiveSrb != NULL);
OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_Cancel); } else { ASSERT(FDODeviceExtension->ActiveSrb == NULL);
FDODeviceExtension->ActiveSrb = Request; OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_CancelIo); }
// // check if the irp has already been cancelled // if (Irp->Cancel && OldDriverCancel == NULL) { // // cancel irp // Irp->CancelRoutine(DeviceObject, Irp);
// // irp was cancelled // return FALSE; }
// // release the cancel lock // IoReleaseCancelSpinLock(Irp->CancelIrql);
// // if list is freezed, dont start this packet // DPRINT("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze, FDODeviceExtension->IrpPendingCount);
return (IrpListFreeze || SrbProcessing);}
PIRPUSBSTOR_RemoveIrp( IN PDEVICE_OBJECT DeviceObject){ KIRQL OldLevel; PFDO_DEVICE_EXTENSION FDODeviceExtension; PLIST_ENTRY Entry; PIRP Irp = NULL;
// // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
// // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO);
// // acquire lock // KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
// // check if list is empty // if (!IsListEmpty(&FDODeviceExtension->IrpListHead)) { // // remove entry // Entry = RemoveHeadList(&FDODeviceExtension->IrpListHead);
// // get offset to start of irp // Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); }
// // release list lock // KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
// // return result // return Irp;}
VOIDUSBSTOR_QueueWaitForPendingRequests( IN PDEVICE_OBJECT DeviceObject){ PFDO_DEVICE_EXTENSION FDODeviceExtension;
// // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
// // perform the wait // KeWaitForSingleObject(&FDODeviceExtension->NoPendingRequests, Executive, KernelMode, FALSE, NULL);}
VOIDUSBSTOR_QueueTerminateRequest( IN PDEVICE_OBJECT FDODeviceObject, IN PIRP Irp){ KIRQL OldLevel; PFDO_DEVICE_EXTENSION FDODeviceExtension; PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
// // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)FDODeviceObject->DeviceExtension;
// // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO);
// // acquire lock // KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
// // decrement pending irp count // FDODeviceExtension->IrpPendingCount--;
// // check if this was our current active SRB // if (FDODeviceExtension->ActiveSrb == Request) { // // indicate processing is completed // FDODeviceExtension->ActiveSrb = NULL; }
// // Set the event if nothing else is pending // if (FDODeviceExtension->IrpPendingCount == 0 && FDODeviceExtension->ActiveSrb == NULL) { KeSetEvent(&FDODeviceExtension->NoPendingRequests, IO_NO_INCREMENT, FALSE); }
// // release lock // KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
}
VOIDUSBSTOR_QueueNextRequest( IN PDEVICE_OBJECT DeviceObject){ PFDO_DEVICE_EXTENSION FDODeviceExtension; PIRP Irp; PIO_STACK_LOCATION IoStack; PSCSI_REQUEST_BLOCK Request;
// // get pdo device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
// // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO);
// // check first if there's already a request pending or the queue is frozen // if (FDODeviceExtension->ActiveSrb != NULL || FDODeviceExtension->IrpListFreeze) { // // no work to do yet // return; }
// // remove first irp from list // Irp = USBSTOR_RemoveIrp(DeviceObject);
// // is there an irp pending // if (!Irp) { // // no work to do // IoStartNextPacket(DeviceObject, TRUE); return; }
// // get current stack location // IoStack = IoGetCurrentIrpStackLocation(Irp);
// // get srb // Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
// // sanity check // ASSERT(Request);
// // set the active SRB // FDODeviceExtension->ActiveSrb = Request;
// // start next packet // IoStartPacket(DeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
// // start next request // IoStartNextPacket(DeviceObject, TRUE);}
VOIDUSBSTOR_QueueRelease( IN PDEVICE_OBJECT DeviceObject){ PFDO_DEVICE_EXTENSION FDODeviceExtension; PIRP Irp; KIRQL OldLevel; PIO_STACK_LOCATION IoStack; PSCSI_REQUEST_BLOCK Request;
// // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
// // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO);
// // acquire lock // KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
// // clear freezed status // FDODeviceExtension->IrpListFreeze = FALSE;
// // release irp list lock // KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
// // grab newest irp // Irp = USBSTOR_RemoveIrp(DeviceObject);
// // is there an irp // if (!Irp) { // // no irp // return; }
// // get current irp stack location // IoStack = IoGetCurrentIrpStackLocation(Irp);
// // get srb // Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
// // start new packet // IoStartPacket(DeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);}
VOIDNTAPIUSBSTOR_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 //}