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