update for HEAD-2003091401
[reactos.git] / ntoskrnl / io / cntrller.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            ntoskrnl/io/cntrller.c
6  * PURPOSE:         Implements the controller object
7  * PROGRAMMER:      David Welch (welch@mcmail.com)
8  * UPDATE HISTORY:
9  *                  Created 22/05/98
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/pool.h>
16
17 #include <internal/debug.h>
18
19 /* GLOBALS *******************************************************************/
20
21 #define TAG_CQE                    TAG('C', 'Q', 'E', ' ')
22 #define TAG_CONTROLLER             TAG('C', 'N', 'T', 'R')
23 #define TAG_CONTROLLER_EXTENSION   TAG('C', 'E', 'X', 'T')
24
25 /* TYPES ********************************************************************/
26
27 typedef struct
28 /*
29  * PURPOSE: A entry in the queue waiting for a controller object
30  */
31 {
32    KDEVICE_QUEUE_ENTRY Entry;
33    PDEVICE_OBJECT DeviceObject;
34    PDRIVER_CONTROL ExecutionRoutine;
35    PVOID Context;
36 } CONTROLLER_QUEUE_ENTRY, *PCONTROLLER_QUEUE_ENTRY;
37
38 /* FUNCTIONS *****************************************************************/
39
40 /*
41  * @implemented
42  */
43 VOID
44 STDCALL
45 IoAllocateController(PCONTROLLER_OBJECT ControllerObject,
46                           PDEVICE_OBJECT DeviceObject,
47                           PDRIVER_CONTROL ExecutionRoutine,
48                           PVOID Context)
49 /*
50  * FUNCTION: Sets up a call to a driver-supplied ControllerControl routine
51  * as soon as the device controller, represented by the given controller
52  * object, is available to carry out an I/O operation for the target device,
53  * represented by the given device object.
54  * ARGUMENTS:
55  *       ControllerObject = Driver created controller object
56  *       DeviceObject = Target device for the current irp
57  *       ExecutionRoutine = Routine to be called when the device is available
58  *       Context = Driver supplied context to be passed on to the above routine
59  * NOTE: Is the below implementation correct. 
60  */
61 {
62    PCONTROLLER_QUEUE_ENTRY entry;
63    IO_ALLOCATION_ACTION Result;
64
65    assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
66
67    entry = 
68      ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROLLER_QUEUE_ENTRY),
69                            TAG_CQE);
70    assert(entry!=NULL);
71    
72    entry->DeviceObject = DeviceObject;
73    entry->ExecutionRoutine = ExecutionRoutine;
74    entry->Context = Context;
75    
76    if (KeInsertDeviceQueue(&ControllerObject->DeviceWaitQueue,&entry->Entry))
77      {
78         return;
79      }   
80    Result = ExecutionRoutine(DeviceObject,DeviceObject->CurrentIrp,
81                              NULL,Context);
82    if (Result == DeallocateObject)
83      {
84         IoFreeController(ControllerObject);
85      }
86    ExFreePool(entry);
87 }
88
89 /*
90  * @implemented
91  */
92 PCONTROLLER_OBJECT
93 STDCALL
94 IoCreateController(ULONG Size)
95 /*
96  * FUNCTION: Allocates memory and initializes a controller object
97  * ARGUMENTS:
98  *        Size = Size (in bytes) to be allocated for the controller extension
99  * RETURNS: A pointer to the created object
100  */
101 {
102    PCONTROLLER_OBJECT controller;
103    
104    assert_irql(PASSIVE_LEVEL);
105    
106    controller = 
107      ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROLLER_OBJECT),
108                            TAG_CONTROLLER);
109    if (controller==NULL)
110      {
111         return(NULL);
112      }
113    
114    controller->ControllerExtension = 
115      ExAllocatePoolWithTag(NonPagedPool, Size, TAG_CONTROLLER_EXTENSION);
116    if (controller->ControllerExtension==NULL)
117      {
118         ExFreePool(controller);
119         return(NULL);
120      }
121
122    KeInitializeDeviceQueue(&controller->DeviceWaitQueue);
123    return(controller);
124 }
125
126 /*
127  * @implemented
128  */
129 VOID
130 STDCALL
131 IoDeleteController(PCONTROLLER_OBJECT ControllerObject)
132 /*
133  * FUNCTION: Removes a given controller object from the system
134  * ARGUMENTS:
135  *        ControllerObject = Controller object to be released
136  */
137 {
138    assert_irql(PASSIVE_LEVEL);
139
140    ExFreePool(ControllerObject->ControllerExtension);
141    ExFreePool(ControllerObject);
142 }
143
144 /*
145  * @implemented
146  */
147 VOID
148 STDCALL
149 IoFreeController(PCONTROLLER_OBJECT ControllerObject)
150 /*
151  * FUNCTION: Releases a previously allocated controller object when a 
152  * device has finished an I/O request
153  * ARGUMENTS:
154  *       ControllerObject = Controller object to be released
155  */
156 {
157    PKDEVICE_QUEUE_ENTRY QEntry;
158    CONTROLLER_QUEUE_ENTRY* Entry;
159    IO_ALLOCATION_ACTION Result;
160
161    do
162      {
163         QEntry = KeRemoveDeviceQueue(&ControllerObject->DeviceWaitQueue);
164         Entry = CONTAINING_RECORD(QEntry,CONTROLLER_QUEUE_ENTRY,Entry);
165         if (QEntry==NULL)
166           {
167              return;
168           }
169         Result = Entry->ExecutionRoutine(Entry->DeviceObject,
170                                          Entry->DeviceObject->CurrentIrp,
171                                          NULL,                                   
172                                          Entry->Context);
173         ExFreePool(Entry);
174      } while (Result == DeallocateObject);
175 }
176
177
178 /* EOF */