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 NduNetPnPEvent(NDIS_HANDLE ProtocolBindingContext
,
46 PNET_PNP_EVENT NetPnPEvent
)
48 PNDIS_DEVICE_POWER_STATE PowerState
;
50 DPRINT("NetPnPEvent\n");
52 switch (NetPnPEvent
->NetEvent
)
54 case NetEventQueryRemoveDevice
:
56 DPRINT1("NetPnPEvent: QueryRemoveDevice\n");
57 return NDIS_STATUS_SUCCESS
;
59 case NetEventSetPower
:
60 ASSERT(NetPnPEvent
->BufferLength
>= sizeof(*PowerState
));
62 PowerState
= NetPnPEvent
->Buffer
;
65 case NdisDeviceStateD0
:
66 DPRINT1("NetPnPEvent: SetPower D0\n");
67 return NDIS_STATUS_SUCCESS
;
70 DPRINT1("NetPnPEvent: SetPower state %d not supported\n", *PowerState
);
71 return NDIS_STATUS_FAILURE
;
74 case NetEventQueryPower
:
75 DPRINT1("NetPnPEvent: QueryPower\n");
76 return NDIS_STATUS_SUCCESS
;
78 case NetEventCancelRemoveDevice
:
79 DPRINT1("NetPnPEvent: CancelRemoveDevice\n");
80 return NDIS_STATUS_SUCCESS
;
82 case NetEventReconfigure
:
83 DPRINT1("NetPnPEvent: Reconfigure\n");
84 return NDIS_STATUS_SUCCESS
;
86 case NetEventBindList
:
87 DPRINT1("NetPnPEvent: BindList\n");
88 return NDIS_STATUS_SUCCESS
;
90 case NetEventBindsComplete
:
91 DPRINT("NetPnPEvent: BindsComplete\n");
92 return NDIS_STATUS_SUCCESS
;
94 case NetEventPnPCapabilities
:
95 DPRINT1("NetPnPEvent: PnPCapabilities\n");
96 return NDIS_STATUS_SUCCESS
;
99 DPRINT1("NetPnPEvent unimplemented for net event 0x%x\n", NetPnPEvent
->NetEvent
);
100 return NDIS_STATUS_FAILURE
;
106 NduSendComplete(NDIS_HANDLE ProtocolBindingContext
,
110 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
112 DPRINT("Asynchronous adapter send completed\n");
114 /* Store the final status and signal the event */
115 AdapterContext
->AsyncStatus
= Status
;
116 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
121 NduTransferDataComplete(NDIS_HANDLE ProtocolBindingContext
,
124 UINT BytesTransferred
)
126 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
128 DPRINT("Asynchronous adapter transfer completed\n");
130 /* Store the final status and signal the event */
131 AdapterContext
->AsyncStatus
= Status
;
132 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
137 NduResetComplete(NDIS_HANDLE ProtocolBindingContext
,
140 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
142 DPRINT("Asynchronous adapter reset completed\n");
144 /* Store the final status and signal the event */
145 AdapterContext
->AsyncStatus
= Status
;
146 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
151 NduRequestComplete(NDIS_HANDLE ProtocolBindingContext
,
152 PNDIS_REQUEST NdisRequest
,
155 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
157 DPRINT("Asynchronous adapter request completed\n");
159 /* Store the final status and signal the event */
160 AdapterContext
->AsyncStatus
= Status
;
161 KeSetEvent(&AdapterContext
->AsyncEvent
, IO_NO_INCREMENT
, FALSE
);
166 NduReceive(NDIS_HANDLE ProtocolBindingContext
,
167 NDIS_HANDLE MacReceiveContext
,
169 UINT HeaderBufferSize
,
170 PVOID LookAheadBuffer
,
171 UINT LookaheadBufferSize
,
174 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= ProtocolBindingContext
;
175 PNDISUIO_PACKET_ENTRY PacketEntry
;
179 UINT BytesTransferred
;
181 DPRINT("Received a %d byte packet\n", PacketSize
);
183 /* Discard if nobody is waiting for it */
184 if (AdapterContext
->OpenCount
== 0)
185 return NDIS_STATUS_NOT_ACCEPTED
;
187 /* Allocate a buffer to hold the packet data and header */
188 PacketBuffer
= ExAllocatePool(NonPagedPool
, PacketSize
+ HeaderBufferSize
);
190 return NDIS_STATUS_NOT_ACCEPTED
;
192 /* Allocate the packet descriptor and buffer */
193 Packet
= CreatePacketFromPoolBuffer(AdapterContext
,
194 (PUCHAR
)PacketBuffer
+ HeaderBufferSize
,
198 ExFreePool(PacketBuffer
);
199 return NDIS_STATUS_NOT_ACCEPTED
;
202 /* Transfer the packet data into our data buffer */
203 if (LookaheadBufferSize
== PacketSize
)
205 NdisCopyLookaheadData((PVOID
)((PUCHAR
)PacketBuffer
+ HeaderBufferSize
),
208 AdapterContext
->MacOptions
);
209 BytesTransferred
= PacketSize
;
213 NdisTransferData(&Status
,
214 AdapterContext
->BindingHandle
,
220 if (Status
== NDIS_STATUS_PENDING
)
222 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
227 Status
= AdapterContext
->AsyncStatus
;
229 if (Status
!= NDIS_STATUS_SUCCESS
)
231 DPRINT1("Failed to transfer data with status 0x%x\n", Status
);
232 CleanupAndFreePacket(Packet
, FALSE
);
233 ExFreePool(PacketBuffer
);
234 return NDIS_STATUS_NOT_ACCEPTED
;
238 /* Copy the header data */
239 RtlCopyMemory(PacketBuffer
, HeaderBuffer
, HeaderBufferSize
);
241 /* Free the packet descriptor and buffers
242 but not the pool because we still need it */
243 CleanupAndFreePacket(Packet
, FALSE
);
245 /* Allocate a packet entry from pool */
246 PacketEntry
= ExAllocatePool(NonPagedPool
, sizeof(NDISUIO_PACKET_ENTRY
) + BytesTransferred
+ HeaderBufferSize
- 1);
249 ExFreePool(PacketBuffer
);
250 return NDIS_STATUS_RESOURCES
;
253 /* Initialize the packet entry and copy in packet data */
254 PacketEntry
->PacketLength
= BytesTransferred
+ HeaderBufferSize
;
255 RtlCopyMemory(PacketEntry
->PacketData
, PacketBuffer
, PacketEntry
->PacketLength
);
257 /* Free the old buffer */
258 ExFreePool(PacketBuffer
);
260 /* Insert the packet on the adapter's packet list */
261 ExInterlockedInsertTailList(&AdapterContext
->PacketList
,
262 &PacketEntry
->ListEntry
,
263 &AdapterContext
->Spinlock
);
265 /* Signal the read event */
266 KeSetEvent(&AdapterContext
->PacketReadEvent
,
267 IO_NETWORK_INCREMENT
,
270 return NDIS_STATUS_SUCCESS
;
275 NduReceiveComplete(NDIS_HANDLE ProtocolBindingContext
)
282 NduStatus(NDIS_HANDLE ProtocolBindingContext
,
283 NDIS_STATUS GeneralStatus
,
285 UINT StatusBufferSize
)
287 /* FIXME: Implement status tracking */
292 NduStatusComplete(NDIS_HANDLE ProtocolBindingContext
)
294 /* FIXME: Implement status tracking */
299 UnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext
)
302 PLIST_ENTRY CurrentEntry
;
303 PNDISUIO_OPEN_ENTRY OpenEntry
;
304 PNDISUIO_PACKET_ENTRY PacketEntry
;
307 DPRINT("Unbinding adapter %wZ\n", &AdapterContext
->DeviceName
);
309 /* FIXME: We don't do anything with outstanding reads */
311 /* Remove the adapter context from the global list */
312 KeAcquireSpinLock(&GlobalAdapterListLock
, &OldIrql
);
313 RemoveEntryList(&AdapterContext
->ListEntry
);
314 KeReleaseSpinLock(&GlobalAdapterListLock
, OldIrql
);
316 /* Free the device name string */
317 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
319 /* Invalidate all handles to this adapter */
320 CurrentEntry
= AdapterContext
->OpenEntryList
.Flink
;
321 while (CurrentEntry
!= &AdapterContext
->OpenEntryList
)
323 OpenEntry
= CONTAINING_RECORD(CurrentEntry
, NDISUIO_OPEN_ENTRY
, ListEntry
);
325 /* Make sure the entry is sane */
326 ASSERT(OpenEntry
->FileObject
);
328 /* Remove the adapter context pointer */
329 ASSERT(AdapterContext
== OpenEntry
->FileObject
->FsContext
);
330 OpenEntry
->FileObject
->FsContext
= NULL
;
331 AdapterContext
->OpenCount
--;
333 /* Remove the open entry pointer */
334 ASSERT(OpenEntry
== OpenEntry
->FileObject
->FsContext2
);
335 OpenEntry
->FileObject
->FsContext2
= NULL
;
337 /* Move to the next entry */
338 CurrentEntry
= CurrentEntry
->Flink
;
340 /* Free the open entry */
341 ExFreePool(OpenEntry
);
344 /* If this fails, we have a refcount mismatch somewhere */
345 ASSERT(AdapterContext
->OpenCount
== 0);
347 /* Free all pending packet entries */
348 CurrentEntry
= AdapterContext
->PacketList
.Flink
;
349 while (CurrentEntry
!= &AdapterContext
->PacketList
)
351 PacketEntry
= CONTAINING_RECORD(CurrentEntry
, NDISUIO_PACKET_ENTRY
, ListEntry
);
353 /* Move to the next entry */
354 CurrentEntry
= CurrentEntry
->Flink
;
356 /* Free the packet entry */
357 ExFreePool(PacketEntry
);
360 /* Send the close request */
361 NdisCloseAdapter(&Status
,
362 AdapterContext
->BindingHandle
);
364 /* Wait for a pending close */
365 if (Status
== NDIS_STATUS_PENDING
)
367 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
372 Status
= AdapterContext
->AsyncStatus
;
375 /* Free the context */
376 ExFreePool(AdapterContext
);
383 BindAdapterByName(PNDIS_STRING DeviceName
)
385 NDIS_STATUS OpenErrorStatus
;
386 PNDISUIO_ADAPTER_CONTEXT AdapterContext
;
387 NDIS_MEDIUM SupportedMedia
[1] = {NdisMedium802_3
};
390 NDIS_REQUEST Request
;
392 /* Allocate the adapter context */
393 AdapterContext
= ExAllocatePool(NonPagedPool
, sizeof(*AdapterContext
));
396 return NDIS_STATUS_RESOURCES
;
399 /* Set up the adapter context */
400 RtlZeroMemory(AdapterContext
, sizeof(*AdapterContext
));
401 KeInitializeEvent(&AdapterContext
->AsyncEvent
, SynchronizationEvent
, FALSE
);
402 KeInitializeEvent(&AdapterContext
->PacketReadEvent
, SynchronizationEvent
, FALSE
);
403 KeInitializeSpinLock(&AdapterContext
->Spinlock
);
404 InitializeListHead(&AdapterContext
->PacketList
);
405 InitializeListHead(&AdapterContext
->OpenEntryList
);
406 AdapterContext
->OpenCount
= 0;
408 AdapterContext
->DeviceName
.Length
=
409 AdapterContext
->DeviceName
.MaximumLength
= DeviceName
->Length
;
410 AdapterContext
->DeviceName
.Buffer
= ExAllocatePool(NonPagedPool
, DeviceName
->Length
);
411 if (!AdapterContext
->DeviceName
.Buffer
)
413 ExFreePool(AdapterContext
);
414 return NDIS_STATUS_RESOURCES
;
417 /* Copy the device name into the adapter context */
418 RtlCopyMemory(AdapterContext
->DeviceName
.Buffer
, DeviceName
->Buffer
, DeviceName
->Length
);
420 DPRINT("Binding adapter %wZ\n", &AdapterContext
->DeviceName
);
422 /* Create the buffer pool */
423 NdisAllocateBufferPool(&Status
,
424 &AdapterContext
->BufferPoolHandle
,
426 if (Status
!= NDIS_STATUS_SUCCESS
)
428 DPRINT1("Failed to allocate buffer pool with status 0x%x\n", Status
);
429 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
430 ExFreePool(AdapterContext
);
434 /* Create the packet pool */
435 NdisAllocatePacketPool(&Status
,
436 &AdapterContext
->PacketPoolHandle
,
438 PROTOCOL_RESERVED_SIZE_IN_PACKET
);
439 if (Status
!= NDIS_STATUS_SUCCESS
)
441 DPRINT1("Failed to allocate packet pool with status 0x%x\n", Status
);
442 NdisFreeBufferPool(AdapterContext
->BufferPoolHandle
);
443 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
444 ExFreePool(AdapterContext
);
448 /* Send the open request */
449 NdisOpenAdapter(&Status
,
451 &AdapterContext
->BindingHandle
,
455 GlobalProtocolHandle
,
461 /* Wait for a pending open */
462 if (Status
== NDIS_STATUS_PENDING
)
464 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
469 Status
= AdapterContext
->AsyncStatus
;
472 /* Check the final status */
473 if (Status
!= NDIS_STATUS_SUCCESS
)
475 DPRINT1("Failed to open adapter for bind with status 0x%x\n", Status
);
476 NdisFreePacketPool(AdapterContext
->PacketPoolHandle
);
477 NdisFreeBufferPool(AdapterContext
->BufferPoolHandle
);
478 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
479 ExFreePool(AdapterContext
);
483 /* Get the MAC options */
484 Request
.RequestType
= NdisRequestQueryInformation
;
485 Request
.DATA
.QUERY_INFORMATION
.Oid
= OID_GEN_MAC_OPTIONS
;
486 Request
.DATA
.QUERY_INFORMATION
.InformationBuffer
= &AdapterContext
->MacOptions
;
487 Request
.DATA
.QUERY_INFORMATION
.InformationBufferLength
= sizeof(ULONG
);
489 AdapterContext
->BindingHandle
,
492 /* Wait for a pending request */
493 if (Status
== NDIS_STATUS_PENDING
)
495 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
500 Status
= AdapterContext
->AsyncStatus
;
503 /* Check the final status */
504 if (Status
!= NDIS_STATUS_SUCCESS
)
506 NDIS_STATUS CloseStatus
;
508 DPRINT1("Failed to get MAC options with status 0x%x\n", Status
);
510 NdisCloseAdapter(&CloseStatus
,
511 AdapterContext
->BindingHandle
);
512 if (CloseStatus
== NDIS_STATUS_PENDING
)
514 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
521 NdisFreePacketPool(AdapterContext
->PacketPoolHandle
);
522 NdisFreeBufferPool(AdapterContext
->BufferPoolHandle
);
523 RtlFreeUnicodeString(&AdapterContext
->DeviceName
);
524 ExFreePool(AdapterContext
);
528 /* Add the adapter context to the global list */
529 ExInterlockedInsertTailList(&GlobalAdapterList
,
530 &AdapterContext
->ListEntry
,
531 &GlobalAdapterListLock
);
533 return STATUS_SUCCESS
;
538 NduBindAdapter(PNDIS_STATUS Status
,
539 NDIS_HANDLE BindContext
,
540 PNDIS_STRING DeviceName
,
541 PVOID SystemSpecific1
,
542 PVOID SystemSpecific2
)
544 /* Use our helper function to create a context for this adapter */
545 *Status
= BindAdapterByName(DeviceName
);
550 NduUnbindAdapter(PNDIS_STATUS Status
,
551 NDIS_HANDLE ProtocolBindingContext
,
552 NDIS_HANDLE UnbindContext
)
554 /* This is forced unbind. UnbindAdapterByContext() will take care of
555 * invalidating file handles pointer to this adapter for us */
556 *Status
= UnbindAdapterByContext(ProtocolBindingContext
);