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