2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS User I/O driver
5 * PURPOSE: Protocol stuff
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
14 PNDIS_MEDIUM SupportedMedia
= {NdisMedium802_3
};
18 NduOpenAdapterComplete(NDIS_HANDLE ProtocolBindingContext
,
20 NDIS_STATUS OpenStatus
)
22 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
24 DPRINT("Asynchronous adapter open completed\n");
26 /* Store the final status and signal the event */
27 AdapterContext
->AsyncStatus
= Status
;
28 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
33 NduCloseAdapterComplete(NDIS_HANDLE ProtocolBindingContext
,
36 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
38 DPRINT("Asynchronous adapter close completed\n");
40 /* Store the final status and signal the event */
41 AdapterContext
->AsyncStatus
= Status
;
42 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
47 NduSendComplete(NDIS_HANDLE ProtocolBindingContext
,
51 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
53 DPRINT("Asynchronous adapter send completed\n");
55 /* Store the final status and signal the event */
56 AdapterContext
->AsyncStatus
= Status
;
57 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
62 NduTransferDataComplete(NDIS_HANDLE ProtocolBindingContext
,
65 UINT BytesTransferred
)
67 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
69 DPRINT("Asynchronous adapter transfer completed\n");
71 /* Store the final status and signal the event */
72 AdapterContext
->AsyncStatus
= Status
;
73 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
78 NduResetComplete(NDIS_HANDLE ProtocolBindingContext
,
81 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
83 DPRINT("Asynchronous adapter reset completed\n");
85 /* Store the final status and signal the event */
86 AdapterContext
->AsyncStatus
= Status
;
87 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
92 NduRequestComplete(NDIS_HANDLE ProtocolBindingContext
,
93 PNDIS_REQUEST NdisRequest
,
96 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
98 DPRINT("Asynchronous adapter request completed\n");
100 /* Store the final status and signal the event */
101 AdapterContext
->AsyncStatus
= Status
;
102 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
107 NduReceive(NDIS_HANDLE ProtocolBindingContext
,
108 NDIS_HANDLE MacReceiveContext
,
110 UINT HeaderBufferSize
,
111 PVOID LookAheadBuffer
,
112 UINT LookaheadBufferSize
,
115 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
116 PNDISUIO_PACKET_ENTRY PacketEntry
;
120 UINT BytesTransferred
;
122 DPRINT("Received a %d byte packet on %wZ\n", PacketSize
+ HeaderBufferSize
, &AdapterContext
->DeviceName
);
124 /* Discard if nobody is waiting for it */
125 if (AdapterContext
->OpenCount
== 0)
126 return NDIS_STATUS_NOT_ACCEPTED
;
128 /* Allocate a buffer to hold the packet data and header */
129 PacketBuffer
= ExAllocatePool(NonPagedPool
, PacketSize
);
131 return NDIS_STATUS_NOT_ACCEPTED
;
133 /* Allocate the packet descriptor and buffer */
134 Packet
= CreatePacketFromPoolBuffer(AdapterContext
,
135 (PUCHAR
)PacketBuffer
+ HeaderBufferSize
,
139 ExFreePool(PacketBuffer
);
140 return NDIS_STATUS_NOT_ACCEPTED
;
143 /* Transfer the packet data into our data buffer */
144 NdisTransferData(&Status
,
145 AdapterContext
->BindingHandle
,
151 if (Status
== NDIS_STATUS_PENDING
)
153 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
158 Status
= AdapterContext
->AsyncStatus
;
160 if (Status
!= NDIS_STATUS_SUCCESS
)
162 DPRINT1("Failed to transfer data with status 0x%x\n", Status
);
163 CleanupAndFreePacket(Packet
, TRUE
);
164 return NDIS_STATUS_NOT_ACCEPTED
;
167 /* Copy the header data */
168 RtlCopyMemory(PacketBuffer
, HeaderBuffer
, HeaderBufferSize
);
170 /* Free the packet descriptor and buffers
171 but not the pool because we still need it */
172 CleanupAndFreePacket(Packet
, FALSE
);
174 /* Allocate a packet entry from paged pool */
175 PacketEntry
= ExAllocatePool(PagedPool
, sizeof(NDISUIO_PACKET_ENTRY
) + BytesTransferred
+ HeaderBufferSize
- 1);
178 ExFreePool(PacketBuffer
);
179 return NDIS_STATUS_RESOURCES
;
182 /* Initialize the packet entry and copy in packet data */
183 PacketEntry
->PacketLength
= BytesTransferred
+ HeaderBufferSize
;
184 RtlCopyMemory(&PacketEntry
->PacketData
[0], PacketBuffer
, PacketEntry
->PacketLength
);
186 /* Free the old non-paged buffer */
187 ExFreePool(PacketBuffer
);
189 /* Insert the packet on the adapter's packet list */
190 ExInterlockedInsertTailList(&AdapterContext
->PacketList
,
191 &PacketEntry
->ListEntry
,
192 &AdapterContext
->Spinlock
);
194 /* Signal the read event */
195 KeSetEvent(&AdapterContext
->PacketReadEvent
,
196 IO_NETWORK_INCREMENT
,
199 return NDIS_STATUS_SUCCESS
;
204 NduReceiveComplete(NDIS_HANDLE ProtocolBindingContext
)
211 NduStatus(NDIS_HANDLE ProtocolBindingContext
,
212 NDIS_STATUS GeneralStatus
,
214 UINT StatusBufferSize
)
216 /* FIXME: Implement status tracking */
221 NduStatusComplete(NDIS_HANDLE ProtocolBindingContext
)
223 /* FIXME: Implement status tracking */
228 UnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext
)
231 PLIST_ENTRY CurrentEntry
;
232 PNDISUIO_OPEN_ENTRY OpenEntry
;
233 PNDISUIO_PACKET_ENTRY PacketEntry
;
236 DPRINT("Unbinding adapter %wZ\n", &AdapterContext
->DeviceName
);
238 /* FIXME: We don't do anything with outstanding reads */
240 /* Remove the adapter context from the global list */
241 KeAcquireSpinLock(&GlobalAdapterListLock
, &OldIrql
);
242 RemoveEntryList(&AdapterContext
->ListEntry
);
243 KeReleaseSpinLock(&GlobalAdapterListLock
, OldIrql
);
245 /* Free the device name string */
246 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
248 /* Invalidate all handles to this adapter */
249 CurrentEntry
= AdapterContext
->OpenEntryList
.Flink
;
250 while (CurrentEntry
!= &AdapterContext
->OpenEntryList
)
252 OpenEntry
= CONTAINING_RECORD(CurrentEntry
, NDISUIO_OPEN_ENTRY
, ListEntry
);
254 /* Make sure the entry is sane */
255 ASSERT(OpenEntry
->FileObject
);
257 /* Remove the adapter context pointer */
258 ASSERT(AdapterContext
== OpenEntry
->FileObject
->FsContext
);
259 OpenEntry
->FileObject
->FsContext
= NULL
;
260 AdapterContext
->OpenCount
--;
262 /* Remove the open entry pointer */
263 ASSERT(OpenEntry
== OpenEntry
->FileObject
->FsContext2
);
264 OpenEntry
->FileObject
->FsContext2
= NULL
;
266 /* Move to the next entry */
267 CurrentEntry
= CurrentEntry
->Flink
;
269 /* Free the open entry */
270 ExFreePool(OpenEntry
);
273 /* If this fails, we have a refcount mismatch somewhere */
274 ASSERT(AdapterContext
->OpenCount
== 0);
276 /* Free all pending packet entries */
277 CurrentEntry
= AdapterContext
->PacketList
.Flink
;
278 while (CurrentEntry
!= &AdapterContext
->PacketList
)
280 PacketEntry
= CONTAINING_RECORD(CurrentEntry
, NDISUIO_PACKET_ENTRY
, ListEntry
);
282 /* Move to the next entry */
283 CurrentEntry
= CurrentEntry
->Flink
;
285 /* Free the packet entry */
286 ExFreePool(PacketEntry
);
289 /* Send the close request */
290 NdisCloseAdapter(&Status
,
291 AdapterContext
->BindingHandle
);
293 /* Wait for a pending close */
294 if (Status
== NDIS_STATUS_PENDING
)
296 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
301 Status
= AdapterContext
->AsyncStatus
;
304 /* Free the context */
305 ExFreePool(AdapterContext
);
312 BindAdapterByName(PNDIS_STRING DeviceName
)
314 NDIS_STATUS OpenErrorStatus
;
315 PNDISUIO_ADAPTER_CONTEXT AdapterContext
;
319 DPRINT("Binding adapter %wZ\n", &AdapterContext
->DeviceName
);
321 /* Allocate the adapter context */
322 AdapterContext
= ExAllocatePool(NonPagedPool
, sizeof(*AdapterContext
));
325 return NDIS_STATUS_RESOURCES
;
328 /* Set up the adapter context */
329 RtlZeroMemory(AdapterContext
, sizeof(*AdapterContext
));
330 KeInitializeEvent(&AdapterContext
->AsyncEvent
, SynchronizationEvent
, FALSE
);
331 KeInitializeEvent(&AdapterContext
->PacketReadEvent
, SynchronizationEvent
, FALSE
);
332 KeInitializeSpinLock(&AdapterContext
->Spinlock
);
333 InitializeListHead(&AdapterContext
->PacketList
);
334 InitializeListHead(&AdapterContext
->OpenEntryList
);
335 AdapterContext
->OpenCount
= 0;
337 AdapterContext
->DeviceName
.Length
=
338 AdapterContext
->DeviceName
.MaximumLength
= DeviceName
->Length
;
339 AdapterContext
->DeviceName
.Buffer
= ExAllocatePool(NonPagedPool
, DeviceName
->Length
);
340 if (!AdapterContext
->DeviceName
.Buffer
)
342 ExFreePool(AdapterContext
);
343 return NDIS_STATUS_RESOURCES
;
346 /* Copy the device name into the adapter context */
347 RtlCopyMemory(AdapterContext
->DeviceName
.Buffer
, DeviceName
->Buffer
, DeviceName
->Length
);
349 /* Create the buffer pool */
350 NdisAllocateBufferPool(&Status
,
351 &AdapterContext
->BufferPoolHandle
,
353 if (Status
!= NDIS_STATUS_SUCCESS
)
355 DPRINT1("Failed to allocate buffer pool with status 0x%x\n", Status
);
356 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
357 ExFreePool(AdapterContext
);
361 /* Create the packet pool */
362 NdisAllocatePacketPool(&Status
,
363 &AdapterContext
->PacketPoolHandle
,
365 PROTOCOL_RESERVED_SIZE_IN_PACKET
);
366 if (Status
!= NDIS_STATUS_SUCCESS
)
368 DPRINT1("Failed to allocate packet pool with status 0x%x\n", Status
);
369 NdisFreeBufferPool(AdapterContext
->BufferPoolHandle
);
370 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
371 ExFreePool(AdapterContext
);
375 /* Send the open request */
376 NdisOpenAdapter(&Status
,
378 &AdapterContext
->BindingHandle
,
382 GlobalProtocolHandle
,
388 /* Wait for a pending open */
389 if (Status
== NDIS_STATUS_PENDING
)
391 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
396 Status
= AdapterContext
->AsyncStatus
;
399 /* Check the final status */
400 if (Status
!= NDIS_STATUS_SUCCESS
)
402 DPRINT1("Failed to open adapter for bind with status 0x%x\n", Status
);
403 NdisFreePacketPool(AdapterContext
->PacketPoolHandle
);
404 NdisFreeBufferPool(AdapterContext
->BufferPoolHandle
);
405 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
406 ExFreePool(AdapterContext
);
410 /* Add the adapter context to the global list */
411 ExInterlockedInsertTailList(&GlobalAdapterList
,
412 &AdapterContext
->ListEntry
,
413 &GlobalAdapterListLock
);
415 return STATUS_SUCCESS
;
420 NduBindAdapter(PNDIS_STATUS Status
,
421 NDIS_HANDLE BindContext
,
422 PNDIS_STRING DeviceName
,
423 PVOID SystemSpecific1
,
424 PVOID SystemSpecific2
)
426 /* Use our helper function to create a context for this adapter */
427 *Status
= BindAdapterByName(DeviceName
);
432 NduUnbindAdapter(PNDIS_STATUS Status
,
433 NDIS_HANDLE ProtocolBindingContext
,
434 NDIS_HANDLE UnbindContext
)
436 /* This is forced unbind. UnbindAdapterByContext() will take care of
437 * invalidating file handles pointer to this adapter for us */
438 *Status
= UnbindAdapterByContext(ProtocolBindingContext
);