:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[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 VOID
41 STDCALL
42 IoAllocateController(PCONTROLLER_OBJECT ControllerObject,
43                           PDEVICE_OBJECT DeviceObject,
44                           PDRIVER_CONTROL ExecutionRoutine,
45                           PVOID Context)
46 /*
47  * FUNCTION: Sets up a call to a driver-supplied ControllerControl routine
48  * as soon as the device controller, represented by the given controller
49  * object, is available to carry out an I/O operation for the target device,
50  * represented by the given device object.
51  * ARGUMENTS:
52  *       ControllerObject = Driver created controller object
53  *       DeviceObject = Target device for the current irp
54  *       ExecutionRoutine = Routine to be called when the device is available
55  *       Context = Driver supplied context to be passed on to the above routine
56  * NOTE: Is the below implementation correct. 
57  */
58 {
59    PCONTROLLER_QUEUE_ENTRY entry;
60    IO_ALLOCATION_ACTION Result;
61
62    assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
63
64    entry = 
65      ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROLLER_QUEUE_ENTRY),
66                            TAG_CQE);
67    assert(entry!=NULL);
68    
69    entry->DeviceObject = DeviceObject;
70    entry->ExecutionRoutine = ExecutionRoutine;
71    entry->Context = Context;
72    
73    if (KeInsertDeviceQueue(&ControllerObject->DeviceWaitQueue,&entry->Entry))
74      {
75         return;
76      }   
77    Result = ExecutionRoutine(DeviceObject,DeviceObject->CurrentIrp,
78                              NULL,Context);
79    if (Result == DeallocateObject)
80      {
81         IoFreeController(ControllerObject);
82      }
83    ExFreePool(entry);
84 }
85
86 PCONTROLLER_OBJECT
87 STDCALL
88 IoCreateController(ULONG Size)
89 /*
90  * FUNCTION: Allocates memory and initializes a controller object
91  * ARGUMENTS:
92  *        Size = Size (in bytes) to be allocated for the controller extension
93  * RETURNS: A pointer to the created object
94  */
95 {
96    PCONTROLLER_OBJECT controller;
97    
98    assert_irql(PASSIVE_LEVEL);
99    
100    controller = 
101      ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROLLER_OBJECT),
102                            TAG_CONTROLLER);
103    if (controller==NULL)
104      {
105         return(NULL);
106      }
107    
108    controller->ControllerExtension = 
109      ExAllocatePoolWithTag(NonPagedPool, Size, TAG_CONTROLLER_EXTENSION);
110    if (controller->ControllerExtension==NULL)
111      {
112         ExFreePool(controller);
113         return(NULL);
114      }
115
116    KeInitializeDeviceQueue(&controller->DeviceWaitQueue);
117    return(controller);
118 }
119
120 VOID
121 STDCALL
122 IoDeleteController(PCONTROLLER_OBJECT ControllerObject)
123 /*
124  * FUNCTION: Removes a given controller object from the system
125  * ARGUMENTS:
126  *        ControllerObject = Controller object to be released
127  */
128 {
129    assert_irql(PASSIVE_LEVEL);
130
131    ExFreePool(ControllerObject->ControllerExtension);
132    ExFreePool(ControllerObject);
133 }
134
135 VOID
136 STDCALL
137 IoFreeController(PCONTROLLER_OBJECT ControllerObject)
138 /*
139  * FUNCTION: Releases a previously allocated controller object when a 
140  * device has finished an I/O request
141  * ARGUMENTS:
142  *       ControllerObject = Controller object to be released
143  */
144 {
145    PKDEVICE_QUEUE_ENTRY QEntry;
146    CONTROLLER_QUEUE_ENTRY* Entry;
147    IO_ALLOCATION_ACTION Result;
148
149    do
150      {
151         QEntry = KeRemoveDeviceQueue(&ControllerObject->DeviceWaitQueue);
152         Entry = CONTAINING_RECORD(QEntry,CONTROLLER_QUEUE_ENTRY,Entry);
153         if (QEntry==NULL)
154           {
155              return;
156           }
157         Result = Entry->ExecutionRoutine(Entry->DeviceObject,
158                                          Entry->DeviceObject->CurrentIrp,
159                                          NULL,                                   
160                                          Entry->Context);
161         ExFreePool(Entry);
162      } while (Result == DeallocateObject);
163 }
164
165
166 /* EOF */