f41017b103528594d79c640eb8b8df7f3fb2ca21
[reactos.git] / reactos / drivers / network / ndis / ndis / protocol.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/protocol.c
5 * PURPOSE: Routines used by NDIS protocol drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 09-13-2003 Vizzini Updates for SendPackets support
11 */
12
13 #include "ndissys.h"
14 #include <buffer.h>
15
16 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
17 #define LINKAGE_KEY L"\\Linkage"
18 #define PARAMETERS_KEY L"\\Parameters\\"
19
20 LIST_ENTRY ProtocolListHead;
21 KSPIN_LOCK ProtocolListLock;
22
23 #define WORKER_TEST 0
24
25 typedef struct _DMA_CONTEXT {
26 PLOGICAL_ADAPTER Adapter;
27 PNDIS_PACKET Packet;
28 } DMA_CONTEXT, *PDMA_CONTEXT;
29
30 PNET_PNP_EVENT
31 ProSetupPnPEvent(
32 NET_PNP_EVENT_CODE EventCode,
33 PVOID EventBuffer,
34 ULONG EventBufferLength)
35 {
36 PNET_PNP_EVENT PnPEvent;
37
38 PnPEvent = ExAllocatePool(PagedPool, sizeof(NET_PNP_EVENT));
39 if (!PnPEvent) {
40 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
41 return NULL;
42 }
43
44 RtlZeroMemory(PnPEvent, sizeof(NET_PNP_EVENT));
45
46 PnPEvent->NetEvent = EventCode;
47
48 if (EventBuffer != NULL)
49 {
50 PnPEvent->Buffer = ExAllocatePool(PagedPool, EventBufferLength);
51 if (!PnPEvent->Buffer)
52 {
53 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
54 ExFreePool(PnPEvent);
55 return NULL;
56 }
57
58 PnPEvent->BufferLength = EventBufferLength;
59
60 RtlCopyMemory(PnPEvent->Buffer, EventBuffer, PnPEvent->BufferLength);
61 }
62
63 return PnPEvent;
64 }
65
66 NDIS_STATUS
67 ProSendAndFreePnPEvent(
68 PLOGICAL_ADAPTER Adapter,
69 PNET_PNP_EVENT PnPEvent,
70 PIRP Irp)
71 {
72 PLIST_ENTRY CurrentEntry;
73 NDIS_STATUS Status;
74 PADAPTER_BINDING AdapterBinding;
75
76 CurrentEntry = Adapter->ProtocolListHead.Flink;
77
78 while (CurrentEntry != &Adapter->ProtocolListHead)
79 {
80 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
81
82 Status = (*AdapterBinding->ProtocolBinding->Chars.PnPEventHandler)(
83 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
84 PnPEvent);
85
86 if (Status == NDIS_STATUS_PENDING)
87 {
88 IoMarkIrpPending(Irp);
89 /* Yes, I know this is stupid */
90 PnPEvent->NdisReserved[0] = (ULONG_PTR)Irp;
91 PnPEvent->NdisReserved[1] = (ULONG_PTR)CurrentEntry->Flink;
92 return NDIS_STATUS_PENDING;
93 }
94 else if (Status != NDIS_STATUS_SUCCESS)
95 {
96 if (PnPEvent->Buffer) ExFreePool(PnPEvent->Buffer);
97 ExFreePool(PnPEvent);
98 return Status;
99 }
100
101 CurrentEntry = CurrentEntry->Flink;
102 }
103
104 if (PnPEvent->Buffer) ExFreePool(PnPEvent->Buffer);
105 ExFreePool(PnPEvent);
106
107 return NDIS_STATUS_SUCCESS;
108 }
109
110 NTSTATUS
111 NTAPI
112 NdisIPwrSetPower(
113 IN PDEVICE_OBJECT DeviceObject,
114 PIRP Irp)
115 {
116 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
117 PNET_PNP_EVENT PnPEvent;
118 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
119
120 ASSERT(Stack->Parameters.Power.Type == DevicePowerState);
121
122 PnPEvent = ProSetupPnPEvent(NetEventSetPower, &Stack->Parameters.Power.State, sizeof(NDIS_DEVICE_POWER_STATE));
123 if (!PnPEvent) {
124 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
125 return NDIS_STATUS_RESOURCES;
126 }
127
128 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
129 }
130
131 NTSTATUS
132 NTAPI
133 NdisIPwrQueryPower(
134 IN PDEVICE_OBJECT DeviceObject,
135 PIRP Irp)
136 {
137 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
138 PNET_PNP_EVENT PnPEvent;
139 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
140
141 ASSERT(Stack->Parameters.Power.Type == DevicePowerState);
142
143 PnPEvent = ProSetupPnPEvent(NetEventQueryPower, &Stack->Parameters.Power.State, sizeof(NDIS_DEVICE_POWER_STATE));
144 if (!PnPEvent) {
145 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
146 return NDIS_STATUS_RESOURCES;
147 }
148
149 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
150 }
151
152
153 NTSTATUS
154 NTAPI
155 NdisIPnPQueryStopDevice(
156 IN PDEVICE_OBJECT DeviceObject,
157 PIRP Irp)
158 {
159 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
160 PNET_PNP_EVENT PnPEvent;
161
162 PnPEvent = ProSetupPnPEvent(NetEventQueryRemoveDevice, NULL, 0);
163 if (!PnPEvent) {
164 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
165 return NDIS_STATUS_RESOURCES;
166 }
167
168 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
169 }
170
171 NTSTATUS
172 NTAPI
173 NdisIPnPCancelStopDevice(
174 IN PDEVICE_OBJECT DeviceObject,
175 PIRP Irp)
176 {
177 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
178 PNET_PNP_EVENT PnPEvent;
179
180 PnPEvent = ProSetupPnPEvent(NetEventCancelRemoveDevice, NULL, 0);
181 if (!PnPEvent) {
182 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
183 return NDIS_STATUS_RESOURCES;
184 }
185
186 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
187 }
188
189 \f
190 /*
191 * @implemented
192 */
193 VOID
194 EXPORT
195 NdisCompleteBindAdapter(
196 IN NDIS_HANDLE BindAdapterContext,
197 IN NDIS_STATUS Status,
198 IN NDIS_STATUS OpenStatus)
199 /*
200 * FUNCTION: Indicates a packet to bound protocols
201 * ARGUMENTS:
202 * Adapter = Pointer to logical adapter
203 * Packet = Pointer to packet to indicate
204 * RETURNS:
205 * Status of operation
206 * NOTES:
207 * - FIXME: partially-implemented
208 */
209 {
210 PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)BindAdapterContext;
211
212 if (!NT_SUCCESS(Status)) {
213 NDIS_DbgPrint(MIN_TRACE, ("Binding failed (%x)\n", Status));
214 return;
215 }
216
217 /* Put protocol binding struct on global list */
218 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
219 }
220
221 /*
222 * @implemented
223 */
224 VOID
225 EXPORT
226 NdisCompleteUnbindAdapter(
227 IN NDIS_HANDLE UnbindAdapterContext,
228 IN NDIS_STATUS Status)
229 {
230 /* We probably need to do more here but for now we just do
231 * the opposite of what NdisCompleteBindAdapter does
232 */
233
234 PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)UnbindAdapterContext;
235
236 if (!NT_SUCCESS(Status)) {
237 NDIS_DbgPrint(MIN_TRACE, ("Unbinding failed (%x)\n", Status));
238 return;
239 }
240
241 ExInterlockedRemoveEntryList(&Protocol->ListEntry, &ProtocolListLock);
242 }
243
244 \f
245 NDIS_STATUS
246 ProIndicatePacket(
247 PLOGICAL_ADAPTER Adapter,
248 PNDIS_PACKET Packet)
249 /*
250 * FUNCTION: Indicates a packet to bound protocols
251 * ARGUMENTS:
252 * Adapter = Pointer to logical adapter
253 * Packet = Pointer to packet to indicate
254 * RETURNS:
255 * STATUS_SUCCESS in all cases
256 * NOTES:
257 * - XXX ATM, this only handles loopback packets - is that its designed function?
258 */
259 {
260 UINT BufferedLength;
261 UINT PacketLength;
262 KIRQL OldIrql;
263 PUCHAR LookaheadBuffer;
264
265 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
266
267 #if DBG
268 MiniDisplayPacket(Packet);
269 #endif
270
271 LookaheadBuffer = ExAllocatePool(NonPagedPool, Adapter->NdisMiniportBlock.CurrentLookahead + Adapter->MediumHeaderSize);
272 if (!LookaheadBuffer) {
273 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
274 return NDIS_STATUS_RESOURCES;
275 }
276
277 NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);
278
279 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
280 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
281 {
282 BufferedLength = CopyPacketToBuffer(LookaheadBuffer, Packet, 0, Adapter->NdisMiniportBlock.CurrentLookahead +
283 Adapter->MediumHeaderSize);
284 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = Packet;
285 }
286 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
287
288 if (BufferedLength > Adapter->MediumHeaderSize)
289 {
290 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
291 MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize,
292 &LookaheadBuffer[Adapter->MediumHeaderSize], BufferedLength - Adapter->MediumHeaderSize,
293 PacketLength - Adapter->MediumHeaderSize);
294 }
295 else
296 {
297 MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize, NULL, 0, 0);
298 }
299
300 ExFreePool(LookaheadBuffer);
301
302 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
303 {
304 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = NULL;
305 }
306 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
307
308 return NDIS_STATUS_SUCCESS;
309 }
310
311 \f
312 NDIS_STATUS NTAPI
313 ProRequest(
314 IN NDIS_HANDLE MacBindingHandle,
315 IN PNDIS_REQUEST NdisRequest)
316 /*
317 * FUNCTION: Forwards a request to an NDIS miniport
318 * ARGUMENTS:
319 * MacBindingHandle = Adapter binding handle
320 * NdisRequest = Pointer to request to perform
321 * RETURNS:
322 * Status of operation
323 */
324 {
325 PADAPTER_BINDING AdapterBinding;
326 PLOGICAL_ADAPTER Adapter;
327 PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
328
329 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
330
331 ASSERT(MacBindingHandle);
332 AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
333
334 ASSERT(AdapterBinding->Adapter);
335 Adapter = AdapterBinding->Adapter;
336
337 MacBlock->Binding = &AdapterBinding->NdisOpenBlock;
338
339 #if WORKER_TEST
340 MiniQueueWorkItem(Adapter, NdisWorkItemRequest, NdisRequest, FALSE);
341 return NDIS_STATUS_PENDING;
342 #else
343 if (MiniIsBusy(Adapter, NdisWorkItemRequest)) {
344 MiniQueueWorkItem(Adapter, NdisWorkItemRequest, NdisRequest, FALSE);
345 return NDIS_STATUS_PENDING;
346 }
347
348 return MiniDoRequest(Adapter, NdisRequest);
349 #endif
350 }
351
352
353 NDIS_STATUS NTAPI
354 ProReset(
355 IN NDIS_HANDLE MacBindingHandle)
356 {
357 PADAPTER_BINDING AdapterBinding = MacBindingHandle;
358
359 /* FIXME: Wait for all packets to be sent */
360
361 return MiniReset(AdapterBinding->Adapter);
362 }
363
364 VOID NTAPI
365 ScatterGatherSendPacket(
366 IN PDEVICE_OBJECT DeviceObject,
367 IN PIRP Irp,
368 IN PSCATTER_GATHER_LIST ScatterGather,
369 IN PVOID Context)
370 {
371 PDMA_CONTEXT DmaContext = Context;
372 PLOGICAL_ADAPTER Adapter = DmaContext->Adapter;
373 PNDIS_PACKET Packet = DmaContext->Packet;
374 NDIS_STATUS Status;
375
376 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
377
378 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
379 ScatterGatherListPacketInfo) = ScatterGather;
380
381 Status = proSendPacketToMiniport(Adapter, Packet);
382
383 if (Status != NDIS_STATUS_PENDING) {
384 NDIS_DbgPrint(MAX_TRACE, ("Completing packet.\n"));
385 MiniSendComplete(Adapter,
386 Packet,
387 Status);
388 }
389
390 ExFreePool(DmaContext);
391 }
392
393 NDIS_STATUS
394 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet)
395 {
396 #if WORKER_TEST
397 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
398 return NDIS_STATUS_PENDING;
399 #else
400 KIRQL RaiseOldIrql;
401 NDIS_STATUS NdisStatus;
402
403 if(MiniIsBusy(Adapter, NdisWorkItemSend)) {
404 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
405 return NDIS_STATUS_PENDING;
406 }
407
408 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
409 {
410 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
411 {
412 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
413 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
414 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
415 NdisStatus = NDIS_STATUS_PENDING;
416 } else {
417 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
418 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
419 {
420 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
421 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
422 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
423 }
424 KeLowerIrql(RaiseOldIrql);
425
426 NdisStatus = NDIS_GET_PACKET_STATUS(Packet);
427 if (NdisStatus == NDIS_STATUS_RESOURCES) {
428 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
429 NdisStatus = NDIS_STATUS_PENDING;
430 }
431 }
432
433 return NdisStatus;
434 } else {
435 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
436 {
437 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
438 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
439 Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags);
440 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
441 } else {
442 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
443 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
444 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
445 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
446 Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags);
447 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
448 KeLowerIrql(RaiseOldIrql);
449
450 if (NdisStatus == NDIS_STATUS_RESOURCES) {
451 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
452 NdisStatus = NDIS_STATUS_PENDING;
453 }
454 }
455
456 return NdisStatus;
457 }
458 #endif
459 }
460
461 \f
462 NDIS_STATUS NTAPI
463 ProSend(
464 IN NDIS_HANDLE MacBindingHandle,
465 IN PNDIS_PACKET Packet)
466 /*
467 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
468 * ARGUMENTS:
469 * MacBindingHandle = Adapter binding handle
470 * Packet = Pointer to NDIS packet descriptor
471 * RETURNS:
472 * NDIS_STATUS_SUCCESS if the packet was successfully sent
473 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
474 */
475 {
476 PADAPTER_BINDING AdapterBinding;
477 PLOGICAL_ADAPTER Adapter;
478 PNDIS_BUFFER NdisBuffer;
479 PDMA_CONTEXT Context;
480 NDIS_STATUS NdisStatus;
481 UINT PacketLength;
482 KIRQL OldIrql;
483
484 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
485
486 ASSERT(MacBindingHandle);
487 AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
488
489 ASSERT(AdapterBinding);
490 Adapter = AdapterBinding->Adapter;
491
492 ASSERT(Adapter);
493
494 /* if the following is not true, KeRaiseIrql() below will break */
495 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
496
497 /* XXX what is this crazy black magic? */
498 Packet->Reserved[1] = (ULONG_PTR)MacBindingHandle;
499
500 /*
501 * Test the packet to see if it is a MAC loopback.
502 *
503 * We may have to loop this packet if miniport cannot.
504 * If dest MAC address of packet == MAC address of adapter,
505 * this is a loopback frame.
506 */
507
508 if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
509 MiniAdapterHasAddress(Adapter, Packet))
510 {
511 #if WORKER_TEST
512 MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, Packet, FALSE);
513 return NDIS_STATUS_PENDING;
514 #else
515 return ProIndicatePacket(Adapter, Packet);
516 #endif
517 } else {
518 if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
519 {
520 NDIS_DbgPrint(MIN_TRACE, ("Using Scatter/Gather DMA\n"));
521
522 NdisQueryPacket(Packet,
523 NULL,
524 NULL,
525 &NdisBuffer,
526 &PacketLength);
527
528 Context = ExAllocatePool(NonPagedPool, sizeof(DMA_CONTEXT));
529 if (!Context) {
530 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
531 return NDIS_STATUS_RESOURCES;
532 }
533
534 Context->Adapter = Adapter;
535 Context->Packet = Packet;
536
537 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
538
539 KeFlushIoBuffers(NdisBuffer, FALSE, TRUE);
540
541 NdisStatus = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->GetScatterGatherList(
542 Adapter->NdisMiniportBlock.SystemAdapterObject,
543 Adapter->NdisMiniportBlock.PhysicalDeviceObject,
544 NdisBuffer,
545 MmGetMdlVirtualAddress(NdisBuffer),
546 PacketLength,
547 ScatterGatherSendPacket,
548 Context,
549 TRUE);
550
551 KeLowerIrql(OldIrql);
552
553 if (!NT_SUCCESS(NdisStatus)) {
554 NDIS_DbgPrint(MIN_TRACE, ("GetScatterGatherList failed! (%x)\n", NdisStatus));
555 return NdisStatus;
556 }
557
558 return NDIS_STATUS_PENDING;
559 }
560
561
562 return proSendPacketToMiniport(Adapter, Packet);
563 }
564 }
565
566 \f
567 VOID NTAPI
568 ProSendPackets(
569 IN NDIS_HANDLE NdisBindingHandle,
570 IN PPNDIS_PACKET PacketArray,
571 IN UINT NumberOfPackets)
572 {
573 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
574 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
575 KIRQL RaiseOldIrql;
576 NDIS_STATUS NdisStatus;
577 UINT i;
578
579 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
580 {
581 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
582 {
583 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
584 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
585 }
586 else
587 {
588 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
589 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
590 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
591 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
592 KeLowerIrql(RaiseOldIrql);
593 for (i = 0; i < NumberOfPackets; i++)
594 {
595 NdisStatus = NDIS_GET_PACKET_STATUS(PacketArray[i]);
596 if (NdisStatus != NDIS_STATUS_PENDING)
597 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
598 }
599 }
600 }
601 else
602 {
603 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
604 {
605 for (i = 0; i < NumberOfPackets; i++)
606 {
607 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
608 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags);
609 if (NdisStatus != NDIS_STATUS_PENDING)
610 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
611 }
612 }
613 else
614 {
615 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
616 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
617 for (i = 0; i < NumberOfPackets; i++)
618 {
619 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
620 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags);
621 if (NdisStatus != NDIS_STATUS_PENDING)
622 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
623 }
624 KeLowerIrql(RaiseOldIrql);
625 }
626 }
627 }
628
629 \f
630 NDIS_STATUS NTAPI
631 ProTransferData(
632 IN NDIS_HANDLE MacBindingHandle,
633 IN NDIS_HANDLE MacReceiveContext,
634 IN UINT ByteOffset,
635 IN UINT BytesToTransfer,
636 IN OUT PNDIS_PACKET Packet,
637 OUT PUINT BytesTransferred)
638 /*
639 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
640 * ARGUMENTS:
641 * MacBindingHandle = Adapter binding handle
642 * MacReceiveContext = MAC receive context
643 * ByteOffset = Offset in packet to place data
644 * BytesToTransfer = Number of bytes to copy into packet
645 * Packet = Pointer to NDIS packet descriptor
646 * BytesTransferred = Address of buffer to place number of bytes copied
647 */
648 {
649 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
650 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
651 NDIS_STATUS Status;
652 KIRQL OldIrql;
653
654 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
655
656 /* FIXME: Interrupts must be disabled for adapter */
657 /* XXX sd - why is that true? */
658
659 if (Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()]) {
660 NDIS_DbgPrint(MAX_TRACE, ("LoopPacket\n"));
661 /* NDIS is responsible for looping this packet */
662 NdisCopyFromPacketToPacket(Packet,
663 ByteOffset + Adapter->MediumHeaderSize,
664 BytesToTransfer + Adapter->MediumHeaderSize,
665 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()],
666 0,
667 BytesTransferred);
668 return NDIS_STATUS_SUCCESS;
669 }
670
671 ASSERT(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler);
672
673 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
674
675 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler)(
676 Packet,
677 BytesTransferred,
678 Adapter->NdisMiniportBlock.MiniportAdapterContext,
679 MacReceiveContext,
680 ByteOffset,
681 BytesToTransfer);
682
683 KeLowerIrql(OldIrql);
684
685 return Status;
686 }
687
688
689
690 /*
691 * @implemented
692 */
693 VOID
694 EXPORT
695 NdisCloseAdapter(
696 OUT PNDIS_STATUS Status,
697 IN NDIS_HANDLE NdisBindingHandle)
698 /*
699 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
700 * ARGUMENTS:
701 * Status = Address of buffer for status information
702 * NdisBindingHandle = Handle returned by NdisOpenAdapter
703 */
704 {
705 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(NdisBindingHandle);
706
707 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
708
709 /* Remove from protocol's bound adapters list */
710 ExInterlockedRemoveEntryList(&AdapterBinding->ProtocolListEntry, &AdapterBinding->ProtocolBinding->Lock);
711
712 /* Remove protocol from adapter's bound protocols list */
713 ExInterlockedRemoveEntryList(&AdapterBinding->AdapterListEntry, &AdapterBinding->Adapter->NdisMiniportBlock.Lock);
714
715 ExFreePool(AdapterBinding);
716
717 *Status = NDIS_STATUS_SUCCESS;
718 }
719
720
721 /*
722 * @implemented
723 */
724 VOID
725 EXPORT
726 NdisDeregisterProtocol(
727 OUT PNDIS_STATUS Status,
728 IN NDIS_HANDLE NdisProtocolHandle)
729 /*
730 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
731 * ARGUMENTS:
732 * Status = Address of buffer for status information
733 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
734 */
735 {
736 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
737
738 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
739
740 /* FIXME: Make sure no adapter bindings exist */
741
742 /* Remove protocol from global list */
743 ExInterlockedRemoveEntryList(&Protocol->ListEntry, &ProtocolListLock);
744
745 ExFreePool(Protocol);
746
747 *Status = NDIS_STATUS_SUCCESS;
748 }
749
750
751 /*
752 * @implemented
753 */
754 VOID
755 EXPORT
756 NdisOpenAdapter(
757 OUT PNDIS_STATUS Status,
758 OUT PNDIS_STATUS OpenErrorStatus,
759 OUT PNDIS_HANDLE NdisBindingHandle,
760 OUT PUINT SelectedMediumIndex,
761 IN PNDIS_MEDIUM MediumArray,
762 IN UINT MediumArraySize,
763 IN NDIS_HANDLE NdisProtocolHandle,
764 IN NDIS_HANDLE ProtocolBindingContext,
765 IN PNDIS_STRING AdapterName,
766 IN UINT OpenOptions,
767 IN PSTRING AddressingInformation OPTIONAL)
768 /*
769 * FUNCTION: Opens an adapter for communication
770 * ARGUMENTS:
771 * Status = Address of buffer for status information
772 * OpenErrorStatus = Address of buffer for secondary error code
773 * NdisBindingHandle = Address of buffer for adapter binding handle
774 * SelectedMediumIndex = Address of buffer for selected medium
775 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
776 * MediumArraySize = Number of elements in MediumArray
777 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
778 * ProtocolBindingContext = Pointer to caller suplied context area
779 * AdapterName = Pointer to buffer with name of adapter
780 * OpenOptions = Bitmask with flags passed to next-lower driver
781 * AddressingInformation = Optional pointer to buffer with NIC specific information
782 */
783 {
784 UINT i;
785 BOOLEAN Found;
786 PLOGICAL_ADAPTER Adapter;
787 PADAPTER_BINDING AdapterBinding;
788 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
789
790 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
791
792 if(!NdisProtocolHandle)
793 {
794 NDIS_DbgPrint(MIN_TRACE, ("NdisProtocolHandle is NULL\n"));
795 *OpenErrorStatus = *Status = NDIS_STATUS_FAILURE;
796 return;
797 }
798
799 Adapter = MiniLocateDevice(AdapterName);
800 if (!Adapter)
801 {
802 NDIS_DbgPrint(MIN_TRACE, ("Adapter not found.\n"));
803 *Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
804 return;
805 }
806
807 /* Find the media type in the list provided by the protocol driver */
808 Found = FALSE;
809 for (i = 0; i < MediumArraySize; i++)
810 {
811 if (Adapter->NdisMiniportBlock.MediaType == MediumArray[i])
812 {
813 *SelectedMediumIndex = i;
814 Found = TRUE;
815 break;
816 }
817 }
818
819 if (!Found)
820 {
821 NDIS_DbgPrint(MIN_TRACE, ("Medium is not supported.\n"));
822 *Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
823 return;
824 }
825
826 /* Now that we have confirmed that the adapter can be opened, create a binding */
827
828 AdapterBinding = ExAllocatePool(NonPagedPool, sizeof(ADAPTER_BINDING));
829 if (!AdapterBinding)
830 {
831 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
832 *Status = NDIS_STATUS_RESOURCES;
833 return;
834 }
835
836 RtlZeroMemory(AdapterBinding, sizeof(ADAPTER_BINDING));
837
838 AdapterBinding->ProtocolBinding = Protocol;
839 AdapterBinding->Adapter = Adapter;
840 AdapterBinding->NdisOpenBlock.ProtocolBindingContext = ProtocolBindingContext;
841
842 /* Set fields required by some NDIS macros */
843 AdapterBinding->NdisOpenBlock.BindingHandle = (NDIS_HANDLE)AdapterBinding;
844
845 /* Set handlers (some NDIS macros require these) */
846
847 AdapterBinding->NdisOpenBlock.RequestHandler = ProRequest;
848 AdapterBinding->NdisOpenBlock.ResetHandler = ProReset;
849 AdapterBinding->NdisOpenBlock.SendHandler = ProSend;
850 AdapterBinding->NdisOpenBlock.SendPacketsHandler = ProSendPackets;
851 AdapterBinding->NdisOpenBlock.TransferDataHandler = ProTransferData;
852
853 AdapterBinding->NdisOpenBlock.RequestCompleteHandler =
854 Protocol->Chars.RequestCompleteHandler;
855
856 /* Put on protocol's bound adapters list */
857 ExInterlockedInsertTailList(&Protocol->AdapterListHead, &AdapterBinding->ProtocolListEntry, &Protocol->Lock);
858
859 /* Put protocol on adapter's bound protocols list */
860 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
861 ExInterlockedInsertTailList(&Adapter->ProtocolListHead, &AdapterBinding->AdapterListEntry, &Adapter->NdisMiniportBlock.Lock);
862
863 *NdisBindingHandle = (NDIS_HANDLE)AdapterBinding;
864
865 *Status = NDIS_STATUS_SUCCESS;
866 }
867
868 PADAPTER_BINDING
869 NTAPI
870 LocateAdapterBindingByName(IN PPROTOCOL_BINDING ProtocolBinding, IN PNDIS_STRING AdapterName)
871 {
872 PLIST_ENTRY CurrentEntry;
873 PADAPTER_BINDING AdapterBinding;
874 KIRQL OldIrql;
875
876 KeAcquireSpinLock(&ProtocolBinding->Lock, &OldIrql);
877
878 CurrentEntry = ProtocolBinding->AdapterListHead.Flink;
879
880 while (CurrentEntry != &ProtocolBinding->AdapterListHead)
881 {
882 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, ProtocolListEntry);
883
884 if (RtlCompareUnicodeString(AdapterName, &AdapterBinding->Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
885 {
886 KeReleaseSpinLock(&ProtocolBinding->Lock, OldIrql);
887 return AdapterBinding;
888 }
889
890 CurrentEntry = CurrentEntry->Flink;
891 }
892
893 KeReleaseSpinLock(&ProtocolBinding->Lock, OldIrql);
894
895 return NULL;
896 }
897
898 VOID
899 NTAPI
900 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status, IN PPROTOCOL_BINDING Protocol)
901 {
902 /*
903 * bind the protocol to all of its miniports
904 *
905 * open registry path
906 * get list of devices from Bind key
907 * call BindAdapterHandler for each
908 */
909 OBJECT_ATTRIBUTES ObjectAttributes;
910 UNICODE_STRING RegistryPath;
911 WCHAR *RegistryPathStr;
912 NTSTATUS NtStatus;
913 WCHAR *DataPtr;
914 HANDLE DriverKeyHandle = NULL;
915 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL;
916 PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics = &Protocol->Chars;
917
918 RegistryPathStr = ExAllocatePoolWithTag(PagedPool, sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY), NDIS_TAG + __LINE__);
919 if(!RegistryPathStr)
920 {
921 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
922 *Status = NDIS_STATUS_RESOURCES;
923 return;
924 }
925
926 wcscpy(RegistryPathStr, SERVICES_KEY);
927 wcsncat(RegistryPathStr, ((WCHAR *)ProtocolCharacteristics->Name.Buffer), ProtocolCharacteristics->Name.Length / sizeof(WCHAR));
928 RegistryPathStr[wcslen(SERVICES_KEY)+ProtocolCharacteristics->Name.Length/sizeof(WCHAR)] = 0;
929 wcscat(RegistryPathStr, LINKAGE_KEY);
930
931 RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
932 NDIS_DbgPrint(MAX_TRACE, ("Opening configuration key: %wZ\n", &RegistryPath));
933
934 InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
935 NtStatus = ZwOpenKey(&DriverKeyHandle, KEY_READ, &ObjectAttributes);
936
937 ExFreePool(RegistryPathStr);
938
939 if(!NT_SUCCESS(NtStatus))
940 {
941 NDIS_DbgPrint(MIN_TRACE, ("Unable to open protocol configuration\n"));
942 *Status = NDIS_STATUS_FAILURE;
943 return;
944 }
945
946 NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n"));
947
948 {
949 UNICODE_STRING ValueName;
950 ULONG ResultLength;
951
952 RtlInitUnicodeString(&ValueName, L"Bind");
953
954 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength);
955 if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL && NtStatus != STATUS_SUCCESS)
956 {
957 NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value for size\n"));
958 ZwClose(DriverKeyHandle);
959 *Status = NDIS_STATUS_FAILURE;
960 return;
961 }
962
963 KeyInformation = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, NDIS_TAG + __LINE__);
964 if(!KeyInformation)
965 {
966 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
967 ZwClose(DriverKeyHandle);
968 *Status = NDIS_STATUS_FAILURE;
969 return;
970 }
971
972 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation,
973 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength);
974
975 ZwClose(DriverKeyHandle);
976
977 if(!NT_SUCCESS(NtStatus))
978 {
979 NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n"));
980 ExFreePool(KeyInformation);
981 *Status = NDIS_STATUS_FAILURE;
982 return;
983 }
984 }
985
986 /* Assume success for now */
987 *Status = NDIS_STATUS_SUCCESS;
988
989 for (DataPtr = (WCHAR *)KeyInformation->Data;
990 *DataPtr != 0;
991 DataPtr += wcslen(DataPtr) + 1)
992 {
993 /* BindContext is for tracking pending binding operations */
994 VOID *BindContext = 0;
995 NDIS_STRING DeviceName;
996 NDIS_STRING RegistryPath;
997 WCHAR *RegistryPathStr = NULL;
998 ULONG PathLength = 0;
999
1000 RtlInitUnicodeString(&DeviceName, DataPtr); /* we know this is 0-term */
1001
1002 /* Make sure the adapter has started */
1003 if (!MiniLocateDevice(&DeviceName))
1004 {
1005 /* It wasn't in the global miniport list, so skip the bind entry */
1006 continue;
1007 }
1008
1009 /* Make sure this device isn't already bound to this protocol */
1010 if (LocateAdapterBindingByName(Protocol, &DeviceName))
1011 {
1012 /* It was already in this protocol's bound adapter list, so skip the bind entry */
1013 continue;
1014 }
1015
1016 /*
1017 * RegistryPath should be:
1018 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
1019 *
1020 * This is constructed as follows:
1021 * SERVICES_KEY + extracted device name + Protocol name from characteristics
1022 */
1023
1024 PathLength = sizeof(SERVICES_KEY) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
1025 wcslen( DataPtr + 8 ) * sizeof(WCHAR) + /* Adapter1 (extracted from \Device\Adapter1) */
1026 sizeof(PARAMETERS_KEY) + /* \Parameters\ */
1027 ProtocolCharacteristics->Name.Length + sizeof(WCHAR); /* Tcpip */
1028
1029 RegistryPathStr = ExAllocatePool(PagedPool, PathLength);
1030 if(!RegistryPathStr)
1031 {
1032 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n"));
1033 ExFreePool(KeyInformation);
1034 *Status = NDIS_STATUS_RESOURCES;
1035 return;
1036 }
1037
1038 wcscpy(RegistryPathStr, SERVICES_KEY);
1039 wcscat(RegistryPathStr, DataPtr + 8 );
1040 wcscat(RegistryPathStr, PARAMETERS_KEY);
1041 wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) );
1042
1043 RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0;
1044
1045 RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
1046
1047 NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
1048 &DeviceName, &RegistryPath));
1049
1050 {
1051 BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler;
1052 if(BindHandler)
1053 {
1054 BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0);
1055 NDIS_DbgPrint(MIN_TRACE, ("%wZ's BindAdapter handler returned 0x%x for %wZ\n", &ProtocolCharacteristics->Name, *Status, &DeviceName));
1056 }
1057 else
1058 NDIS_DbgPrint(MIN_TRACE, ("No protocol bind handler specified\n"));
1059 }
1060 }
1061
1062 ExFreePool(KeyInformation);
1063 }
1064
1065 /*
1066 * @implemented
1067 */
1068 VOID
1069 EXPORT
1070 NdisRegisterProtocol(
1071 OUT PNDIS_STATUS Status,
1072 OUT PNDIS_HANDLE NdisProtocolHandle,
1073 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
1074 IN UINT CharacteristicsLength)
1075 /*
1076 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
1077 * ARGUMENTS:
1078 * Status = Address of buffer for status information
1079 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
1080 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
1081 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
1082 * NOTES:
1083 * - you *must* set NdisProtocolHandle before doing anything that could wind up
1084 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
1085 * - the above implies that the initialization of the protocol block must be complete
1086 * by then
1087 * TODO:
1088 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
1089 * - make this thing able to handle >1 protocol
1090 */
1091 {
1092 PPROTOCOL_BINDING Protocol;
1093 NTSTATUS NtStatus;
1094 UINT MinSize;
1095 PNET_PNP_EVENT PnPEvent;
1096
1097 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1098
1099 *NdisProtocolHandle = NULL;
1100
1101 /* first validate the PROTOCOL_CHARACTERISTICS */
1102 switch (ProtocolCharacteristics->MajorNdisVersion)
1103 {
1104 case 0x03:
1105 /* we don't really want to support ndis3 drivers - so we complain for now */
1106 NDIS_DbgPrint(MID_TRACE, ("NDIS 3 protocol attempting to register\n"));
1107 MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS);
1108 break;
1109
1110 case 0x04:
1111 MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS);
1112 break;
1113
1114 case 0x05:
1115 MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS);
1116 break;
1117
1118 default:
1119 *Status = NDIS_STATUS_BAD_VERSION;
1120 NDIS_DbgPrint(MIN_TRACE, ("Incorrect characteristics size\n"));
1121 return;
1122 }
1123
1124 if (CharacteristicsLength < MinSize)
1125 {
1126 NDIS_DbgPrint(MIN_TRACE, ("Bad protocol characteristics.\n"));
1127 *Status = NDIS_STATUS_BAD_CHARACTERISTICS;
1128 return;
1129 }
1130
1131 /* set up the protocol block */
1132 Protocol = ExAllocatePool(NonPagedPool, sizeof(PROTOCOL_BINDING));
1133 if (!Protocol)
1134 {
1135 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1136 *Status = NDIS_STATUS_RESOURCES;
1137 return;
1138 }
1139
1140 RtlZeroMemory(Protocol, sizeof(PROTOCOL_BINDING));
1141 RtlCopyMemory(&Protocol->Chars, ProtocolCharacteristics, MinSize);
1142
1143 NtStatus = RtlUpcaseUnicodeString(&Protocol->Chars.Name, &ProtocolCharacteristics->Name, TRUE);
1144 if (!NT_SUCCESS(NtStatus))
1145 {
1146 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1147 ExFreePool(Protocol);
1148 *Status = NDIS_STATUS_RESOURCES;
1149 return;
1150 }
1151
1152 KeInitializeSpinLock(&Protocol->Lock);
1153
1154 InitializeListHead(&Protocol->AdapterListHead);
1155
1156 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's
1157 * BindAdapter handler might need it */
1158
1159 *NdisProtocolHandle = Protocol;
1160
1161 ndisBindMiniportsToProtocol(Status, Protocol);
1162
1163 /* Should we only send this if ndisBindMiniportsToProtocol succeeds? */
1164 PnPEvent = ProSetupPnPEvent(NetEventBindsComplete, NULL, 0);
1165 if (PnPEvent)
1166 {
1167 if (Protocol->Chars.PnPEventHandler)
1168 {
1169 /* We call this with a NULL binding context because it affects all bindings */
1170 NtStatus = (*Protocol->Chars.PnPEventHandler)(NULL,
1171 PnPEvent);
1172
1173 /* FIXME: We don't support this yet */
1174 ASSERT(NtStatus != NDIS_STATUS_PENDING);
1175 }
1176
1177 ExFreePool(PnPEvent);
1178 }
1179
1180 if (*Status == NDIS_STATUS_SUCCESS) {
1181 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
1182 } else {
1183 NDIS_DbgPrint(MIN_TRACE, ("Binding failed (%x)\n", *Status));
1184 ExFreePool(Protocol);
1185 *NdisProtocolHandle = NULL;
1186 }
1187 }
1188
1189 \f
1190 /*
1191 * @implemented
1192 */
1193 VOID
1194 EXPORT
1195 NdisRequest(
1196 OUT PNDIS_STATUS Status,
1197 IN NDIS_HANDLE NdisBindingHandle,
1198 IN PNDIS_REQUEST NdisRequest)
1199 /*
1200 * FUNCTION: Forwards a request to an NDIS driver
1201 * ARGUMENTS:
1202 * Status = Address of buffer for status information
1203 * NdisBindingHandle = Adapter binding handle
1204 * NdisRequest = Pointer to request to perform
1205 */
1206 {
1207 *Status = ProRequest(NdisBindingHandle, NdisRequest);
1208 }
1209
1210 \f
1211 /*
1212 * @implemented
1213 */
1214 VOID
1215 EXPORT
1216 NdisReset(
1217 OUT PNDIS_STATUS Status,
1218 IN NDIS_HANDLE NdisBindingHandle)
1219 {
1220 *Status = ProReset(NdisBindingHandle);
1221 }
1222
1223 \f
1224 /*
1225 * @implemented
1226 */
1227 #undef NdisSend
1228 VOID
1229 EXPORT
1230 NdisSend(
1231 OUT PNDIS_STATUS Status,
1232 IN NDIS_HANDLE NdisBindingHandle,
1233 IN PNDIS_PACKET Packet)
1234 /*
1235 * FUNCTION: Forwards a request to send a packet
1236 * ARGUMENTS:
1237 * Status = Address of buffer for status information
1238 * NdisBindingHandle = Adapter binding handle
1239 * Packet = Pointer to NDIS packet descriptor
1240 */
1241 {
1242 *Status = ProSend(NdisBindingHandle, Packet);
1243 }
1244
1245 \f
1246 /*
1247 * @implemented
1248 */
1249 #undef NdisSendPackets
1250 VOID
1251 EXPORT
1252 NdisSendPackets(
1253 IN NDIS_HANDLE NdisBindingHandle,
1254 IN PPNDIS_PACKET PacketArray,
1255 IN UINT NumberOfPackets)
1256 {
1257 ProSendPackets(NdisBindingHandle, PacketArray, NumberOfPackets);
1258 }
1259
1260 \f
1261 /*
1262 * @implemented
1263 */
1264 #undef NdisTransferData
1265 VOID
1266 EXPORT
1267 NdisTransferData(
1268 OUT PNDIS_STATUS Status,
1269 IN NDIS_HANDLE NdisBindingHandle,
1270 IN NDIS_HANDLE MacReceiveContext,
1271 IN UINT ByteOffset,
1272 IN UINT BytesToTransfer,
1273 IN OUT PNDIS_PACKET Packet,
1274 OUT PUINT BytesTransferred)
1275 /*
1276 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
1277 * ARGUMENTS:
1278 * Status = Address of buffer for status information
1279 * NdisBindingHandle = Adapter binding handle
1280 * MacReceiveContext = MAC receive context
1281 * ByteOffset = Offset in packet to place data
1282 * BytesToTransfer = Number of bytes to copy into packet
1283 * Packet = Pointer to NDIS packet descriptor
1284 * BytesTransferred = Address of buffer to place number of bytes copied
1285 */
1286 {
1287 *Status = ProTransferData(NdisBindingHandle,
1288 MacReceiveContext,
1289 ByteOffset,
1290 BytesToTransfer,
1291 Packet,
1292 BytesTransferred);
1293 }
1294
1295 /*
1296 * @implemented
1297 */
1298 VOID
1299 NTAPI
1300 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle)
1301 {
1302 NDIS_STATUS NdisStatus;
1303
1304 ndisBindMiniportsToProtocol(&NdisStatus, NdisProtocolHandle);
1305 }
1306
1307
1308 /*
1309 * @implemented
1310 */
1311 VOID
1312 EXPORT
1313 NdisGetDriverHandle(
1314 IN PNDIS_HANDLE NdisBindingHandle,
1315 OUT PNDIS_HANDLE NdisDriverHandle)
1316 /*
1317 * FUNCTION:
1318 * ARGUMENTS:
1319 * NOTES:
1320 * NDIS 5.0
1321 */
1322 {
1323 PADAPTER_BINDING Binding = (PADAPTER_BINDING)NdisBindingHandle;
1324
1325 if (!Binding)
1326 {
1327 NDIS_DbgPrint(MIN_TRACE, ("Bad binding handle\n"));
1328 *NdisDriverHandle = NULL;
1329 return;
1330 }
1331
1332 *NdisDriverHandle = Binding->Adapter->NdisMiniportBlock.DriverHandle;
1333 }
1334
1335 /* EOF */