update for HEAD-2003091401
[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 /*
20  * @implemented
21  */
22 VOID
23 STDCALL
24 IoStartNextPacketByKey(PDEVICE_OBJECT DeviceObject,
25                             BOOLEAN Cancelable,
26                             ULONG Key)
27 /*
28  * FUNCTION: Dequeues the next packet from the given device object's
29  * associated device queue according to a specified sort-key value and calls
30  * the drivers StartIo routine with that IRP
31  * ARGUMENTS:
32  *      DeviceObject = Device object for which the irp is to dequeued
33  *      Cancelable = True if IRPs in the key can be canceled
34  *      Key = Sort key specifing which entry to remove from the queue
35  */
36 {
37    PKDEVICE_QUEUE_ENTRY entry;
38    PIRP Irp;
39    
40    entry = KeRemoveByKeyDeviceQueue(&DeviceObject->DeviceQueue,
41                                     Key);
42    
43    if (entry != NULL)
44      {
45         Irp = CONTAINING_RECORD(entry,
46                                 IRP,
47                                 Tail.Overlay.DeviceQueueEntry);
48         DeviceObject->CurrentIrp = Irp;
49         DPRINT("Next irp is %x\n", Irp);
50         DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp);
51      }
52    else
53      {
54         DPRINT("No next irp\n");
55         DeviceObject->CurrentIrp = NULL;
56      }   
57 }
58
59 /*
60  * @implemented
61  */
62 VOID
63 STDCALL
64 IoStartNextPacket(PDEVICE_OBJECT DeviceObject, BOOLEAN Cancelable)
65 /*
66  * FUNCTION: Removes the next packet from the device's queue and calls
67  * the driver's StartIO
68  * ARGUMENTS:
69  *         DeviceObject = Device
70  *         Cancelable = True if irps in the queue can be canceled
71  */
72 {
73    PKDEVICE_QUEUE_ENTRY entry;
74    PIRP Irp;
75    
76    DPRINT("IoStartNextPacket(DeviceObject %x, Cancelable %d)\n",
77           DeviceObject,Cancelable);
78    
79    entry = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
80    
81    if (entry!=NULL)
82      {
83         Irp = CONTAINING_RECORD(entry,IRP,Tail.Overlay.DeviceQueueEntry);
84         DeviceObject->CurrentIrp = Irp;
85         DeviceObject->DriverObject->DriverStartIo(DeviceObject,Irp);    
86      }
87    else
88      {
89         DeviceObject->CurrentIrp = NULL;
90      }
91 }
92
93 /*
94  * @implemented
95  */
96 VOID
97 STDCALL
98 IoStartPacket(PDEVICE_OBJECT DeviceObject,
99                    PIRP Irp, PULONG Key, PDRIVER_CANCEL CancelFunction)
100 /*
101  * FUNCTION: Either call the device's StartIO routine with the packet or,
102  * if the device is busy, queue it.
103  * ARGUMENTS:
104  *       DeviceObject = Device to start the packet on
105  *       Irp = Irp to queue
106  *       Key = Where to insert the irp
107  *             If zero then insert in the tail of the queue
108  *       CancelFunction = Optional function to cancel the irqp
109  */
110 {
111    BOOLEAN stat;
112    KIRQL oldirql;
113    
114    DPRINT("IoStartPacket(Irp %x)\n", Irp);
115    
116    ASSERT_IRQL(DISPATCH_LEVEL);
117    
118    IoAcquireCancelSpinLock(&oldirql);
119    
120    if (CancelFunction != NULL)
121      {
122         Irp->CancelRoutine = CancelFunction;
123      }
124    
125    if (Key!=0)
126      {
127         stat = KeInsertByKeyDeviceQueue(&DeviceObject->DeviceQueue,
128                                         &Irp->Tail.Overlay.DeviceQueueEntry,
129                                         *Key);
130      }
131    else
132      {
133         stat = KeInsertDeviceQueue(&DeviceObject->DeviceQueue,
134                                    &Irp->Tail.Overlay.DeviceQueueEntry);
135      }
136    
137    IoReleaseCancelSpinLock(oldirql);
138    
139    if (!stat)
140      {                     
141         DeviceObject->CurrentIrp = Irp;
142         DeviceObject->DriverObject->DriverStartIo(DeviceObject,Irp);
143      }
144 }
145
146
147 /* EOF */