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)
16 NduOpenAdapterComplete(NDIS_HANDLE ProtocolBindingContext
,
18 NDIS_STATUS OpenStatus
)
20 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
22 DPRINT("Asynchronous adapter open completed\n");
24 /* Store the final status and signal the event */
25 AdapterContext
->AsyncStatus
= Status
;
26 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
31 NduCloseAdapterComplete(NDIS_HANDLE ProtocolBindingContext
,
34 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
36 DPRINT("Asynchronous adapter close completed\n");
38 /* Store the final status and signal the event */
39 AdapterContext
->AsyncStatus
= Status
;
40 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
45 NduSendComplete(NDIS_HANDLE ProtocolBindingContext
,
49 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
51 DPRINT("Asynchronous adapter send completed\n");
53 /* Store the final status and signal the event */
54 AdapterContext
->AsyncStatus
= Status
;
55 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
60 NduTransferDataComplete(NDIS_HANDLE ProtocolBindingContext
,
63 UINT BytesTransferred
)
65 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
67 DPRINT("Asynchronous adapter transfer completed\n");
69 /* Store the final status and signal the event */
70 AdapterContext
->AsyncStatus
= Status
;
71 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
76 NduResetComplete(NDIS_HANDLE ProtocolBindingContext
,
79 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
81 DPRINT("Asynchronous adapter reset completed\n");
83 /* Store the final status and signal the event */
84 AdapterContext
->AsyncStatus
= Status
;
85 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
90 NduRequestComplete(NDIS_HANDLE ProtocolBindingContext
,
91 PNDIS_REQUEST NdisRequest
,
94 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
96 DPRINT("Asynchronous adapter request completed\n");
98 /* Store the final status and signal the event */
99 AdapterContext
->AsyncStatus
= Status
;
100 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
105 NduReceive(NDIS_HANDLE ProtocolBindingContext
,
106 NDIS_HANDLE MacReceiveContext
,
108 UINT HeaderBufferSize
,
109 PVOID LookAheadBuffer
,
110 UINT LookaheadBufferSize
,
113 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
114 PNDISUIO_PACKET_ENTRY PacketEntry
;
118 UINT BytesTransferred
;
120 DPRINT("Received a %d byte packet\n", PacketSize
);
122 /* Discard if nobody is waiting for it */
123 if (AdapterContext
->OpenCount
== 0)
124 return NDIS_STATUS_NOT_ACCEPTED
;
126 /* Allocate a buffer to hold the packet data and header */
127 PacketBuffer
= ExAllocatePool(NonPagedPool
, PacketSize
+ HeaderBufferSize
);
129 return NDIS_STATUS_NOT_ACCEPTED
;
131 /* Allocate the packet descriptor and buffer */
132 Packet
= CreatePacketFromPoolBuffer(AdapterContext
,
133 (PUCHAR
)PacketBuffer
+ HeaderBufferSize
,
137 ExFreePool(PacketBuffer
);
138 return NDIS_STATUS_NOT_ACCEPTED
;
141 /* Transfer the packet data into our data buffer */
142 if (LookaheadBufferSize
== PacketSize
)
144 NdisCopyLookaheadData((PVOID
)((PUCHAR
)PacketBuffer
+ HeaderBufferSize
),
147 AdapterContext
->MacOptions
);
148 BytesTransferred
= PacketSize
;
152 NdisTransferData(&Status
,
153 AdapterContext
->BindingHandle
,
159 if (Status
== NDIS_STATUS_PENDING
)
161 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
166 Status
= AdapterContext
->AsyncStatus
;
168 if (Status
!= NDIS_STATUS_SUCCESS
)
170 DPRINT1("Failed to transfer data with status 0x%x\n", Status
);
171 CleanupAndFreePacket(Packet
, TRUE
);
172 return NDIS_STATUS_NOT_ACCEPTED
;
176 /* Copy the header data */
177 RtlCopyMemory(PacketBuffer
, HeaderBuffer
, HeaderBufferSize
);
179 /* Free the packet descriptor and buffers
180 but not the pool because we still need it */
181 CleanupAndFreePacket(Packet
, FALSE
);
183 /* Allocate a packet entry from pool */
184 PacketEntry
= ExAllocatePool(NonPagedPool
, sizeof(NDISUIO_PACKET_ENTRY
) + BytesTransferred
+ HeaderBufferSize
- 1);
187 ExFreePool(PacketBuffer
);
188 return NDIS_STATUS_RESOURCES
;
191 /* Initialize the packet entry and copy in packet data */
192 PacketEntry
->PacketLength
= BytesTransferred
+ HeaderBufferSize
;
193 RtlCopyMemory(PacketEntry
->PacketData
, PacketBuffer
, PacketEntry
->PacketLength
);
195 /* Free the old buffer */
196 ExFreePool(PacketBuffer
);
198 /* Insert the packet on the adapter's packet list */
199 ExInterlockedInsertTailList(&AdapterContext
->PacketList
,
200 &PacketEntry
->ListEntry
,
201 &AdapterContext
->Spinlock
);
203 /* Signal the read event */
204 KeSetEvent(&AdapterContext
->PacketReadEvent
,
205 IO_NETWORK_INCREMENT
,
208 return NDIS_STATUS_SUCCESS
;
213 NduReceiveComplete(NDIS_HANDLE ProtocolBindingContext
)
220 NduStatus(NDIS_HANDLE ProtocolBindingContext
,
221 NDIS_STATUS GeneralStatus
,
223 UINT StatusBufferSize
)
225 /* FIXME: Implement status tracking */
230 NduStatusComplete(NDIS_HANDLE ProtocolBindingContext
)
232 /* FIXME: Implement status tracking */
237 UnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext
)
240 PLIST_ENTRY CurrentEntry
;
241 PNDISUIO_OPEN_ENTRY OpenEntry
;
242 PNDISUIO_PACKET_ENTRY PacketEntry
;
245 DPRINT("Unbinding adapter %wZ\n", &AdapterContext
->DeviceName
);
247 /* FIXME: We don't do anything with outstanding reads */
249 /* Remove the adapter context from the global list */
250 KeAcquireSpinLock(&GlobalAdapterListLock
, &OldIrql
);
251 RemoveEntryList(&AdapterContext
->ListEntry
);
252 KeReleaseSpinLock(&GlobalAdapterListLock
, OldIrql
);
254 /* Free the device name string */
255 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
257 /* Invalidate all handles to this adapter */
258 CurrentEntry
= AdapterContext
->OpenEntryList
.Flink
;
259 while (CurrentEntry
!= &AdapterContext
->OpenEntryList
)
261 OpenEntry
= CONTAINING_RECORD(CurrentEntry
, NDISUIO_OPEN_ENTRY
, ListEntry
);
263 /* Make sure the entry is sane */
264 ASSERT(OpenEntry
->FileObject
);
266 /* Remove the adapter context pointer */
267 ASSERT(AdapterContext
== OpenEntry
->FileObject
->FsContext
);
268 OpenEntry
->FileObject
->FsContext
= NULL
;
269 AdapterContext
->OpenCount
--;
271 /* Remove the open entry pointer */
272 ASSERT(OpenEntry
== OpenEntry
->FileObject
->FsContext2
);
273 OpenEntry
->FileObject
->FsContext2
= NULL
;
275 /* Move to the next entry */
276 CurrentEntry
= CurrentEntry
->Flink
;
278 /* Free the open entry */
279 ExFreePool(OpenEntry
);
282 /* If this fails, we have a refcount mismatch somewhere */
283 ASSERT(AdapterContext
->OpenCount
== 0);
285 /* Free all pending packet entries */
286 CurrentEntry
= AdapterContext
->PacketList
.Flink
;
287 while (CurrentEntry
!= &AdapterContext
->PacketList
)
289 PacketEntry
= CONTAINING_RECORD(CurrentEntry
, NDISUIO_PACKET_ENTRY
, ListEntry
);
291 /* Move to the next entry */
292 CurrentEntry
= CurrentEntry
->Flink
;
294 /* Free the packet entry */
295 ExFreePool(PacketEntry
);
298 /* Send the close request */
299 NdisCloseAdapter(&Status
,
300 AdapterContext
->BindingHandle
);
302 /* Wait for a pending close */
303 if (Status
== NDIS_STATUS_PENDING
)
305 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
310 Status
= AdapterContext
->AsyncStatus
;
313 /* Free the context */
314 ExFreePool(AdapterContext
);
321 BindAdapterByName(PNDIS_STRING DeviceName
)
323 NDIS_STATUS OpenErrorStatus
;
324 PNDISUIO_ADAPTER_CONTEXT AdapterContext
;
325 NDIS_MEDIUM SupportedMedia
[1] = {NdisMedium802_3
};
328 NDIS_REQUEST Request
;
330 /* Allocate the adapter context */
331 AdapterContext
= ExAllocatePool(NonPagedPool
, sizeof(*AdapterContext
));
334 return NDIS_STATUS_RESOURCES
;
337 /* Set up the adapter context */
338 RtlZeroMemory(AdapterContext
, sizeof(*AdapterContext
));
339 KeInitializeEvent(&AdapterContext
->AsyncEvent
, SynchronizationEvent
, FALSE
);
340 KeInitializeEvent(&AdapterContext
->PacketReadEvent
, SynchronizationEvent
, FALSE
);
341 KeInitializeSpinLock(&AdapterContext
->Spinlock
);
342 InitializeListHead(&AdapterContext
->PacketList
);
343 InitializeListHead(&AdapterContext
->OpenEntryList
);
344 AdapterContext
->OpenCount
= 0;
346 AdapterContext
->DeviceName
.Length
=
347 AdapterContext
->DeviceName
.MaximumLength
= DeviceName
->Length
;
348 AdapterContext
->DeviceName
.Buffer
= ExAllocatePool(NonPagedPool
, DeviceName
->Length
);
349 if (!AdapterContext
->DeviceName
.Buffer
)
351 ExFreePool(AdapterContext
);
352 return NDIS_STATUS_RESOURCES
;
355 /* Copy the device name into the adapter context */
356 RtlCopyMemory(AdapterContext
->DeviceName
.Buffer
, DeviceName
->Buffer
, DeviceName
->Length
);
358 DPRINT("Binding adapter %wZ\n", &AdapterContext
->DeviceName
);
360 /* Create the buffer pool */
361 NdisAllocateBufferPool(&Status
,
362 &AdapterContext
->BufferPoolHandle
,
364 if (Status
!= NDIS_STATUS_SUCCESS
)
366 DPRINT1("Failed to allocate buffer pool with status 0x%x\n", Status
);
367 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
368 ExFreePool(AdapterContext
);
372 /* Create the packet pool */
373 NdisAllocatePacketPool(&Status
,
374 &AdapterContext
->PacketPoolHandle
,
376 PROTOCOL_RESERVED_SIZE_IN_PACKET
);
377 if (Status
!= NDIS_STATUS_SUCCESS
)
379 DPRINT1("Failed to allocate packet pool with status 0x%x\n", Status
);
380 NdisFreeBufferPool(AdapterContext
->BufferPoolHandle
);
381 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
382 ExFreePool(AdapterContext
);
386 /* Send the open request */
387 NdisOpenAdapter(&Status
,
389 &AdapterContext
->BindingHandle
,
393 GlobalProtocolHandle
,
399 /* Wait for a pending open */
400 if (Status
== NDIS_STATUS_PENDING
)
402 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
407 Status
= AdapterContext
->AsyncStatus
;
410 /* Check the final status */
411 if (Status
!= NDIS_STATUS_SUCCESS
)
413 DPRINT1("Failed to open adapter for bind with status 0x%x\n", Status
);
414 NdisFreePacketPool(AdapterContext
->PacketPoolHandle
);
415 NdisFreeBufferPool(AdapterContext
->BufferPoolHandle
);
416 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
417 ExFreePool(AdapterContext
);
421 /* Get the MAC options */
422 Request
.RequestType
= NdisRequestQueryInformation
;
423 Request
.DATA
.QUERY_INFORMATION
.Oid
= OID_GEN_MAC_OPTIONS
;
424 Request
.DATA
.QUERY_INFORMATION
.InformationBuffer
= &AdapterContext
->MacOptions
;
425 Request
.DATA
.QUERY_INFORMATION
.InformationBufferLength
= sizeof(ULONG
);
427 AdapterContext
->BindingHandle
,
430 /* Wait for a pending request */
431 if (Status
== NDIS_STATUS_PENDING
)
433 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
438 Status
= AdapterContext
->AsyncStatus
;
441 /* Check the final status */
442 if (Status
!= NDIS_STATUS_SUCCESS
)
444 NDIS_STATUS CloseStatus
;
446 DPRINT1("Failed to get MAC options with status 0x%x\n", Status
);
448 NdisCloseAdapter(&CloseStatus
,
449 AdapterContext
->BindingHandle
);
450 if (CloseStatus
== NDIS_STATUS_PENDING
)
452 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
459 NdisFreePacketPool(AdapterContext
->PacketPoolHandle
);
460 NdisFreeBufferPool(AdapterContext
->BufferPoolHandle
);
461 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
462 ExFreePool(AdapterContext
);
466 /* Add the adapter context to the global list */
467 ExInterlockedInsertTailList(&GlobalAdapterList
,
468 &AdapterContext
->ListEntry
,
469 &GlobalAdapterListLock
);
471 return STATUS_SUCCESS
;
476 NduBindAdapter(PNDIS_STATUS Status
,
477 NDIS_HANDLE BindContext
,
478 PNDIS_STRING DeviceName
,
479 PVOID SystemSpecific1
,
480 PVOID SystemSpecific2
)
482 /* Use our helper function to create a context for this adapter */
483 *Status
= BindAdapterByName(DeviceName
);
488 NduUnbindAdapter(PNDIS_STATUS Status
,
489 NDIS_HANDLE ProtocolBindingContext
,
490 NDIS_HANDLE UnbindContext
)
492 /* This is forced unbind. UnbindAdapterByContext() will take care of
493 * invalidating file handles pointer to this adapter for us */
494 *Status
= UnbindAdapterByContext(ProtocolBindingContext
);