branch update for HEAD-2003021201
[reactos.git] / ntoskrnl / io / queue.c
1 /* $Id$
2  *
3  * COPYRIGHT:                See COPYING in the top level directory
4  * PROJECT:                  ReactOS kernel
5  * FILE:                     ntoskrnl/io/queue.c
6  * PURPOSE:                  Implement device queueing
7  * PROGRAMMER:               David Welch (welch@mcmail.com)
8  */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ddk/ntddk.h>
13
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* FUNCTIONS *****************************************************************/
18
19 VOID
20 STDCALL
21 IoStartNextPacketByKey(PDEVICE_OBJECT DeviceObject,
22                             BOOLEAN Cancelable,
23                             ULONG Key)
24 /*
25  * FUNCTION: Dequeues the next packet from the given device object's
26  * associated device queue according to a specified sort-key value and calls
27  * the drivers StartIo routine with that IRP
28  * ARGUMENTS:
29  *      DeviceObject = Device object for which the irp is to dequeued
30  *      Cancelable = True if IRPs in the key can be canceled
31  *      Key = Sort key specifing which entry to remove from the queue
32  */
33 {
34    PKDEVICE_QUEUE_ENTRY entry;
35    PIRP Irp;
36    
37    entry = KeRemoveByKeyDeviceQueue(&DeviceObject->DeviceQueue,
38                                     Key);
39    
40    if (entry != NULL)
41      {
42         Irp = CONTAINING_RECORD(entry,
43                                 IRP,
44                                 Tail.Overlay.DeviceQueueEntry);
45         DeviceObject->CurrentIrp = Irp;
46         DPRINT("Next irp is %x\n", Irp);
47         DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp);
48      }
49    else
50      {
51         DPRINT("No next irp\n");
52         DeviceObject->CurrentIrp = NULL;
53      }   
54 }
55
56 VOID
57 STDCALL
58 IoStartNextPacket(PDEVICE_OBJECT DeviceObject, BOOLEAN Cancelable)
59 /*
60  * FUNCTION: Removes the next packet from the device's queue and calls
61  * the driver's StartIO
62  * ARGUMENTS:
63  *         DeviceObject = Device
64  *         Cancelable = True if irps in the queue can be canceled
65  */
66 {
67    PKDEVICE_QUEUE_ENTRY entry;
68    PIRP Irp;
69    
70    DPRINT("IoStartNextPacket(DeviceObject %x, Cancelable %d)\n",
71           DeviceObject,Cancelable);
72    
73    entry = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
74    
75    if (entry!=NULL)
76      {
77         Irp = CONTAINING_RECORD(entry,IRP,Tail.Overlay.DeviceQueueEntry);
78         DeviceObject->CurrentIrp = Irp;
79         DeviceObject->DriverObject->DriverStartIo(DeviceObject,Irp);    
80      }
81    else
82      {
83         DeviceObject->CurrentIrp = NULL;
84      }
85 }
86
87 VOID
88 STDCALL
89 IoStartPacket(PDEVICE_OBJECT DeviceObject,
90                    PIRP Irp, PULONG Key, PDRIVER_CANCEL CancelFunction)
91 /*
92  * FUNCTION: Either call the device's StartIO routine with the packet or,
93  * if the device is busy, queue it.
94  * ARGUMENTS:
95  *       DeviceObject = Device to start the packet on
96  *       Irp = Irp to queue
97  *       Key = Where to insert the irp
98  *             If zero then insert in the tail of the queue
99  *       CancelFunction = Optional function to cancel the irqp
100  */
101 {
102    BOOLEAN stat;
103    KIRQL oldirql;
104    
105    DPRINT("IoStartPacket(Irp %x)\n", Irp);
106    
107    ASSERT_IRQL(DISPATCH_LEVEL);
108    
109    IoAcquireCancelSpinLock(&oldirql);
110    
111    if (CancelFunction != NULL)
112      {
113         Irp->CancelRoutine = CancelFunction;
114      }
115    
116    if (Key!=0)
117      {
118         stat = KeInsertByKeyDeviceQueue(&DeviceObject->DeviceQueue,
119                                         &Irp->Tail.Overlay.DeviceQueueEntry,
120                                         *Key);
121      }
122    else
123      {
124         stat = KeInsertDeviceQueue(&DeviceObject->DeviceQueue,
125                                    &Irp->Tail.Overlay.DeviceQueueEntry);
126      }
127    
128    IoReleaseCancelSpinLock(oldirql);
129    
130    if (!stat)
131      {                     
132         DeviceObject->CurrentIrp = Irp;
133         DeviceObject->DriverObject->DriverStartIo(DeviceObject,Irp);
134      }
135 }
136
137
138 /* EOF */