f95cf63e9182c4c9a3a480233894bba5c2823c14
[reactos.git] / drivers / network / ndisuio / protocol.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS User I/O driver
4 * FILE: protocol.c
5 * PURPOSE: Protocol stuff
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
7 */
8
9 #include "ndisuio.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 PNDIS_MEDIUM SupportedMedia = {NdisMedium802_3};
15
16 VOID
17 NTAPI
18 NduOpenAdapterComplete(NDIS_HANDLE ProtocolBindingContext,
19 NDIS_STATUS Status,
20 NDIS_STATUS OpenStatus)
21 {
22 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
23
24 DPRINT("Asynchronous adapter open completed\n");
25
26 /* Store the final status and signal the event */
27 AdapterContext->AsyncStatus = Status;
28 KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
29 }
30
31 VOID
32 NTAPI
33 NduCloseAdapterComplete(NDIS_HANDLE ProtocolBindingContext,
34 NDIS_STATUS Status)
35 {
36 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
37
38 DPRINT("Asynchronous adapter close completed\n");
39
40 /* Store the final status and signal the event */
41 AdapterContext->AsyncStatus = Status;
42 KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
43 }
44
45 VOID
46 NTAPI
47 NduSendComplete(NDIS_HANDLE ProtocolBindingContext,
48 PNDIS_PACKET Packet,
49 NDIS_STATUS Status)
50 {
51 /* FIXME: Implement send/receive */
52 }
53
54 VOID
55 NTAPI
56 NduTransferDataComplete(NDIS_HANDLE ProtocolBindingContext,
57 PNDIS_PACKET Packet,
58 NDIS_STATUS Status,
59 UINT BytesTransferred)
60 {
61 /* FIXME: Implement send/receive */
62 }
63
64 VOID
65 NTAPI
66 NduResetComplete(NDIS_HANDLE ProtocolBindingContext,
67 NDIS_STATUS Status)
68 {
69 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
70
71 DPRINT("Asynchronous adapter reset completed\n");
72
73 /* Store the final status and signal the event */
74 AdapterContext->AsyncStatus = Status;
75 KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
76 }
77
78 VOID
79 NTAPI
80 NduRequestComplete(NDIS_HANDLE ProtocolBindingContext,
81 PNDIS_REQUEST NdisRequest,
82 NDIS_STATUS Status)
83 {
84 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
85
86 DPRINT("Asynchronous adapter request completed\n");
87
88 /* Store the final status and signal the event */
89 AdapterContext->AsyncStatus = Status;
90 KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
91 }
92
93 NDIS_STATUS
94 NTAPI
95 NduReceive(NDIS_HANDLE ProtocolBindingContext,
96 NDIS_HANDLE MacReceiveContext,
97 PVOID HeaderBuffer,
98 UINT HeaderBufferSize,
99 PVOID LookAheadBuffer,
100 UINT LookaheadBufferSize,
101 UINT PacketSize)
102 {
103 /* FIXME: Implement send/receive */
104 return NDIS_STATUS_NOT_ACCEPTED;
105 }
106
107 VOID
108 NTAPI
109 NduReceiveComplete(NDIS_HANDLE ProtocolBindingContext)
110 {
111 /* No op */
112 }
113
114 VOID
115 NTAPI
116 NduStatus(NDIS_HANDLE ProtocolBindingContext,
117 NDIS_STATUS GeneralStatus,
118 PVOID StatusBuffer,
119 UINT StatusBufferSize)
120 {
121 /* FIXME: Implement status tracking */
122 }
123
124 VOID
125 NTAPI
126 NduStatusComplete(NDIS_HANDLE ProtocolBindingContext)
127 {
128 /* FIXME: Implement status tracking */
129 }
130
131 NDIS_STATUS
132 UnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext)
133 {
134 KIRQL OldIrql;
135 PLIST_ENTRY CurrentOpenEntry;
136 PNDISUIO_OPEN_ENTRY OpenEntry;
137
138 /* Remove the adapter context from the global list */
139 KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql);
140 RemoveEntryList(&AdapterContext->ListEntry);
141 KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
142
143 /* Invalidate all handles to this adapter */
144 CurrentOpenEntry = AdapterContext->OpenEntryList.Flink;
145 while (CurrentOpenEntry != &AdapterContext->OpenEntryList)
146 {
147 OpenEntry = CONTAINING_RECORD(CurrentOpenEntry, NDISUIO_OPEN_ENTRY, ListEntry);
148
149 /* Make sure the entry is sane */
150 ASSERT(OpenEntry->FileObject);
151
152 /* Remove the adapter context pointer */
153 ASSERT(AdapterContext == OpenEntry->FileObject->FsContext);
154 OpenEntry->FileObject->FsContext = NULL;
155 AdapterContext->OpenCount--;
156
157 /* Remove the open entry pointer */
158 ASSERT(OpenEntry == OpenEntry->FileObject->FsContext2);
159 OpenEntry->FileObject->FsContext2 = NULL;
160
161 /* Move to the next entry */
162 CurrentOpenEntry = CurrentOpenEntry->Flink;
163
164 /* Free the open entry */
165 ExFreePool(OpenEntry);
166 }
167
168 /* If this fails, we have a refcount mismatch somewhere */
169 ASSERT(AdapterContext->OpenCount == 0);
170
171 /* Send the close request */
172 NdisCloseAdapter(Status,
173 AdapterContext->BindingHandle);
174
175 /* Wait for a pending close */
176 if (*Status == NDIS_STATUS_PENDING)
177 {
178 KeWaitForSingleObject(&AdapterContext->AsyncEvent,
179 Executive,
180 KernelMode,
181 FALSE,
182 NULL);
183 *Status = AdapterContext->AsyncStatus;
184 }
185
186 /* Free the context */
187 ExFreePool(AdapterContext);
188 }
189
190
191 NDIS_STATUS
192 BindAdapterByName(PNDIS_STRING DeviceName, PNDISUIO_ADAPTER_CONTEXT *Context)
193 {
194 NDIS_STATUS OpenErrorStatus;
195 PNDISUIO_ADAPTER_CONTEXT AdapterContext;
196 UINT SelectedMedium;
197 NDIS_STATUS Status;
198
199 /* Allocate the adapter context */
200 AdapterContext = ExAllocatePool(NonPagedPool, sizeof(*AdapterContext));
201 if (!AdapterContext)
202 {
203 return NDIS_STATUS_RESOURCES;
204 }
205
206 /* Set up the adapter context */
207 RtlZeroMemory(AdapterContext, sizeof(*AdapterContext));
208 KeInitializeEvent(&AdapterContext->AsyncEvent, SynchronizationEvent, FALSE);
209 KeInitializeSpinLock(&AdapterContext->Spinlock);
210 InitializeListHead(&AdapterContext->PacketList);
211 InitializeListHead(&AdapterContext->OpenEntryList);
212 AdapterContext->OpenCount = 0;
213
214 /* Send the open request */
215 NdisOpenAdapter(&Status,
216 &OpenErrorStatus,
217 &AdapterContext->BindingHandle,
218 &SelectedMedium,
219 SupportedMedia,
220 sizeof(SupportedMedia),
221 GlobalProtocolHandle,
222 AdapterContext,
223 DeviceName,
224 0,
225 NULL);
226
227 /* Wait for a pending open */
228 if (Status == NDIS_STATUS_PENDING)
229 {
230 KeWaitForSingleObject(&AdapterContext->AsyncEvent,
231 Executive,
232 KernelMode,
233 FALSE,
234 NULL);
235 Status = AdapterContext->AsyncStatus;
236 }
237
238 /* Check the final status */
239 if (Status != NDIS_STATUS_SUCCESS)
240 {
241 DPRINT1("Failed to open adapter for bind with status 0x%x\n", *Status);
242 ExFreePool(AdapterContext);
243 return;
244 }
245
246 /* Add the adapter context to the global list */
247 ExInterlockedInsertTailList(&GlobalAdapterList,
248 &AdapterContext->ListEntry,
249 &GlobalAdapterListLock);
250
251 /* Return the context */
252 *Context = AdapterContext;
253 return STATUS_SUCCESS;
254 }
255
256 VOID
257 NTAPI
258 NduBindAdapter(PNDIS_STATUS Status,
259 NDIS_HANDLE BindContext,
260 PNDIS_STRING DeviceName,
261 PVOID SystemSpecific1,
262 PVOID SystemSpecific2)
263 {
264 /* Use our helper function to create a context for this adapter */
265 *Status = BindAdapterByName(DeviceName);
266 }
267
268 VOID
269 NTAPI
270 NduUnbindAdapter(PNDIS_STATUS Status,
271 NDIS_HANDLE ProtocolBindingContext,
272 NDIS_HANDLE UnbindContext)
273 {
274 /* This is forced unbind. UnbindAdapterByContext() will take care of
275 * invalidating file handles pointer to this adapter for us */
276 *Status = UnbindAdapterByContext(ProtocolBindingContext);
277 }
278