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 /* Allocate a buffer to hold the packet data and header */
123 PacketBuffer
= ExAllocatePool(NonPagedPool
, PacketSize
);
125 return NDIS_STATUS_NOT_ACCEPTED
;
127 /* Allocate the packet descriptor and buffer */
128 Packet
= CreatePacketFromPoolBuffer((PUCHAR
)PacketBuffer
+ HeaderBufferSize
,
132 ExFreePool(PacketBuffer
);
133 return NDIS_STATUS_NOT_ACCEPTED
;
136 /* Transfer the packet data into our data buffer */
137 NdisTransferData(&Status
,
138 AdapterContext
->BindingHandle
,
144 if (Status
== NDIS_STATUS_PENDING
)
146 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
151 Status
= AdapterContext
->AsyncStatus
;
153 if (Status
!= NDIS_STATUS_SUCCESS
)
155 DPRINT1("Failed to transfer data with status 0x%x\n", Status
);
156 CleanupAndFreePacket(Packet
, TRUE
);
157 return NDIS_STATUS_NOT_ACCEPTED
;
160 /* Copy the header data */
161 RtlCopyMemory(PacketBuffer
, HeaderBuffer
, HeaderBufferSize
);
163 /* Free the packet descriptor and buffers
164 but not the pool because we still need it */
165 CleanupAndFreePacket(Packet
, FALSE
);
167 /* Allocate a packet entry from paged pool */
168 PacketEntry
= ExAllocatePool(PagedPool
, sizeof(NDISUIO_PACKET_ENTRY
) + BytesTransferred
+ HeaderBufferSize
- 1);
171 ExFreePool(PacketBuffer
);
172 return NDIS_STATUS_RESOURCES
;
175 /* Initialize the packet entry and copy in packet data */
176 PacketEntry
->PacketLength
= BytesTransferred
+ HeaderBufferSize
;
177 RtlCopyMemory(&PacketEntry
->PacketData
[0], PacketBuffer
, PacketEntry
->PacketLength
);
179 /* Free the old non-paged buffer */
180 ExFreePool(PacketBuffer
);
182 /* Insert the packet on the adapter's packet list */
183 ExInterlockedInsertTailList(&AdapterContext
->PacketList
,
184 &PacketEntry
->ListEntry
,
185 &AdapterContext
->Spinlock
);
187 /* Signal the read event */
188 KeSetEvent(&AdapterContext
->PacketReadEvent
,
189 IO_NETWORK_INCREMENT
,
192 return NDIS_STATUS_SUCCESS
;
197 NduReceiveComplete(NDIS_HANDLE ProtocolBindingContext
)
204 NduStatus(NDIS_HANDLE ProtocolBindingContext
,
205 NDIS_STATUS GeneralStatus
,
207 UINT StatusBufferSize
)
209 /* FIXME: Implement status tracking */
214 NduStatusComplete(NDIS_HANDLE ProtocolBindingContext
)
216 /* FIXME: Implement status tracking */
221 UnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext
)
224 PLIST_ENTRY CurrentOpenEntry
;
225 PNDISUIO_OPEN_ENTRY OpenEntry
;
228 /* Remove the adapter context from the global list */
229 KeAcquireSpinLock(&GlobalAdapterListLock
, &OldIrql
);
230 RemoveEntryList(&AdapterContext
->ListEntry
);
231 KeReleaseSpinLock(&GlobalAdapterListLock
, OldIrql
);
233 /* Invalidate all handles to this adapter */
234 CurrentOpenEntry
= AdapterContext
->OpenEntryList
.Flink
;
235 while (CurrentOpenEntry
!= &AdapterContext
->OpenEntryList
)
237 OpenEntry
= CONTAINING_RECORD(CurrentOpenEntry
, NDISUIO_OPEN_ENTRY
, ListEntry
);
239 /* Make sure the entry is sane */
240 ASSERT(OpenEntry
->FileObject
);
242 /* Remove the adapter context pointer */
243 ASSERT(AdapterContext
== OpenEntry
->FileObject
->FsContext
);
244 OpenEntry
->FileObject
->FsContext
= NULL
;
245 AdapterContext
->OpenCount
--;
247 /* Remove the open entry pointer */
248 ASSERT(OpenEntry
== OpenEntry
->FileObject
->FsContext2
);
249 OpenEntry
->FileObject
->FsContext2
= NULL
;
251 /* Move to the next entry */
252 CurrentOpenEntry
= CurrentOpenEntry
->Flink
;
254 /* Free the open entry */
255 ExFreePool(OpenEntry
);
258 /* If this fails, we have a refcount mismatch somewhere */
259 ASSERT(AdapterContext
->OpenCount
== 0);
261 /* Send the close request */
262 NdisCloseAdapter(&Status
,
263 AdapterContext
->BindingHandle
);
265 /* Wait for a pending close */
266 if (Status
== NDIS_STATUS_PENDING
)
268 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
273 Status
= AdapterContext
->AsyncStatus
;
276 /* Free the context */
277 ExFreePool(AdapterContext
);
284 BindAdapterByName(PNDIS_STRING DeviceName
)
286 NDIS_STATUS OpenErrorStatus
;
287 PNDISUIO_ADAPTER_CONTEXT AdapterContext
;
291 /* Allocate the adapter context */
292 AdapterContext
= ExAllocatePool(NonPagedPool
, sizeof(*AdapterContext
));
295 return NDIS_STATUS_RESOURCES
;
298 /* Set up the adapter context */
299 RtlZeroMemory(AdapterContext
, sizeof(*AdapterContext
));
300 KeInitializeEvent(&AdapterContext
->AsyncEvent
, SynchronizationEvent
, FALSE
);
301 KeInitializeEvent(&AdapterContext
->PacketReadEvent
, SynchronizationEvent
, FALSE
);
302 KeInitializeSpinLock(&AdapterContext
->Spinlock
);
303 InitializeListHead(&AdapterContext
->PacketList
);
304 InitializeListHead(&AdapterContext
->OpenEntryList
);
305 AdapterContext
->OpenCount
= 0;
307 AdapterContext
->DeviceName
.Length
=
308 AdapterContext
->DeviceName
.MaximumLength
= DeviceName
->Length
;
309 AdapterContext
->DeviceName
.Buffer
= ExAllocatePool(NonPagedPool
, DeviceName
->Length
);
310 if (!AdapterContext
->DeviceName
.Buffer
)
312 ExFreePool(AdapterContext
);
313 return NDIS_STATUS_RESOURCES
;
316 RtlCopyMemory(AdapterContext
->DeviceName
.Buffer
, DeviceName
->Buffer
, DeviceName
->Length
);
318 /* Send the open request */
319 NdisOpenAdapter(&Status
,
321 &AdapterContext
->BindingHandle
,
324 sizeof(SupportedMedia
),
325 GlobalProtocolHandle
,
331 /* Wait for a pending open */
332 if (Status
== NDIS_STATUS_PENDING
)
334 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
339 Status
= AdapterContext
->AsyncStatus
;
342 /* Check the final status */
343 if (Status
!= NDIS_STATUS_SUCCESS
)
345 DPRINT1("Failed to open adapter for bind with status 0x%x\n", Status
);
346 ExFreePool(AdapterContext
);
350 /* Add the adapter context to the global list */
351 ExInterlockedInsertTailList(&GlobalAdapterList
,
352 &AdapterContext
->ListEntry
,
353 &GlobalAdapterListLock
);
355 return STATUS_SUCCESS
;
360 NduBindAdapter(PNDIS_STATUS Status
,
361 NDIS_HANDLE BindContext
,
362 PNDIS_STRING DeviceName
,
363 PVOID SystemSpecific1
,
364 PVOID SystemSpecific2
)
366 /* Use our helper function to create a context for this adapter */
367 *Status
= BindAdapterByName(DeviceName
);
372 NduUnbindAdapter(PNDIS_STATUS Status
,
373 NDIS_HANDLE ProtocolBindingContext
,
374 NDIS_HANDLE UnbindContext
)
376 /* This is forced unbind. UnbindAdapterByContext() will take care of
377 * invalidating file handles pointer to this adapter for us */
378 *Status
= UnbindAdapterByContext(ProtocolBindingContext
);