Sync with trunk revision 64099.
[reactos.git] / drivers / network / tdi / cte / events.c
1 /*
2 * PROJECT: ReactOS TDI driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/network/tdi/cte/events.c
5 * PURPOSE: CTE events support
6 * PROGRAMMERS: Oleg Baikalow (obaikalow@gmail.com)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include "precomp.h"
12
13 typedef struct _CTEBLOCK_EVENT
14 {
15 NTSTATUS Status;
16 KEVENT Event;
17 } CTEBLOCK_EVENT, *PCTEBLOCK_EVENT;
18
19 struct _CTE_DELAYED_EVENT;
20 typedef void (*CTE_WORKER_ROUTINE)(struct _CTE_DELAYED_EVENT *, void *Context);
21
22 typedef struct _CTE_DELAYED_EVENT
23 {
24 BOOLEAN Queued;
25 KSPIN_LOCK Lock;
26 CTE_WORKER_ROUTINE WorkerRoutine;
27 PVOID Context;
28 WORK_QUEUE_ITEM WorkItem;
29 } CTE_DELAYED_EVENT, *PCTE_DELAYED_EVENT;
30
31 /* FUNCTIONS *****************************************************************/
32
33 /*
34 * @implemented
35 */
36 NTSTATUS
37 NTAPI
38 CTEBlock(PCTEBLOCK_EVENT Block)
39 {
40 NTSTATUS Status;
41
42 /* Perform the wait */
43 Status = KeWaitForSingleObject(&Block->Event, UserRequest, KernelMode, FALSE, NULL);
44
45 /* Update event status if wait was not successful */
46 if (!NT_SUCCESS(Status)) Block->Status = Status;
47
48 return Block->Status;
49 }
50
51
52 VOID
53 NTAPI
54 InternalWorker(IN PVOID Parameter)
55 {
56 PCTE_DELAYED_EVENT Event = (PCTE_DELAYED_EVENT)Parameter;
57 KIRQL OldIrql;
58
59 /* Acquire the lock */
60 KeAcquireSpinLock(&Event->Lock, &OldIrql);
61
62 /* Make sure it is queued */
63 ASSERT(Event->Queued);
64 Event->Queued = FALSE;
65
66 /* Release the lock */
67 KeReleaseSpinLock(&Event->Lock, OldIrql);
68
69 /* Call the real worker routine */
70 (*Event->WorkerRoutine)(Event, Event->Context);
71 }
72
73
74 /*
75 * @implemented
76 */
77 VOID
78 NTAPI
79 CTEInitEvent(PCTE_DELAYED_EVENT Event,
80 CTE_WORKER_ROUTINE Routine)
81 {
82 /* Init the structure, lock and a work item */
83 Event->Queued = FALSE;
84 KeInitializeSpinLock(&Event->Lock);
85 Event->WorkerRoutine = Routine;
86 ExInitializeWorkItem(&Event->WorkItem, InternalWorker, Event);
87 }
88
89 /*
90 * @unimplemented
91 */
92 NTSTATUS
93 NTAPI
94 CTELogEvent (
95 ULONG Unknown0,
96 ULONG Unknown1,
97 ULONG Unknown2,
98 ULONG Unknown3,
99 ULONG Unknown4,
100 ULONG Unknown5,
101 ULONG Unknown6
102 )
103 {
104 /* Probably call
105 * IoAllocateErrorLogEntry and
106 * IoWriteErrorLogEntry
107 */
108 return STATUS_NOT_IMPLEMENTED;
109 }
110
111
112 /*
113 * @implemented
114 */
115 BOOLEAN
116 NTAPI
117 CTEScheduleEvent(PCTE_DELAYED_EVENT Event,
118 PVOID Context)
119 {
120 KIRQL OldIrql;
121
122 /* Acquire the lock */
123 KeAcquireSpinLock(&Event->Lock, &OldIrql);
124
125 /* Make sure it is queued */
126 if (!Event->Queued)
127 {
128 /* Mark it as queued and set optional context pointer */
129 Event->Queued = TRUE;
130 Event->Context = Context;
131
132 /* Actually queue it */
133 ExQueueWorkItem(&Event->WorkItem, CriticalWorkQueue);
134 }
135
136 /* Release the lock */
137 KeReleaseSpinLock(&Event->Lock, OldIrql);
138
139 return TRUE;
140 }
141
142
143 /*
144 * @implemented
145 */
146 LONG
147 NTAPI
148 CTESignal(PCTEBLOCK_EVENT Block, NTSTATUS Status)
149 {
150 /* Set status right away */
151 Block->Status = Status;
152
153 /* Set the event */
154 return KeSetEvent(&Block->Event, IO_NO_INCREMENT, FALSE);
155 }
156
157 /* EOF */