xref: /reactos/drivers/network/tdi/cte/events.c (revision c2d0d784)
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 */
158