3301682b97bddfa7628a998c3e04061582d22563
[reactos.git] / drivers / network / ndis / ndis / miniport.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/miniport.c
5 * PURPOSE: Routines used by NDIS miniport drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 20 Aug 2003 vizzini - DMA support
11 * 3 Oct 2003 vizzini - SendPackets support
12 */
13
14 #include "ndissys.h"
15
16 #include <ndisguid.h>
17
18 /*
19 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
20 * for each new miniport starting up
21 */
22 #define BREAK_ON_MINIPORT_INIT 0
23
24 /*
25 * This has to be big enough to hold the results of querying the Route value
26 * from the Linkage key. Please re-code me to determine this dynamically.
27 */
28 #define ROUTE_DATA_SIZE 256
29
30 /* Number of media we know */
31 #define MEDIA_ARRAY_SIZE 15
32
33 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] =
34 {
35 NdisMedium802_3,
36 NdisMedium802_5,
37 NdisMediumFddi,
38 NdisMediumWan,
39 NdisMediumLocalTalk,
40 NdisMediumDix,
41 NdisMediumArcnetRaw,
42 NdisMediumArcnet878_2,
43 NdisMediumAtm,
44 NdisMediumWirelessWan,
45 NdisMediumIrda,
46 NdisMediumBpc,
47 NdisMediumCoWan,
48 NdisMedium1394,
49 NdisMediumMax
50 };
51
52 /* global list and lock of Miniports NDIS has registered */
53 LIST_ENTRY MiniportListHead;
54 KSPIN_LOCK MiniportListLock;
55
56 /* global list and lock of adapters NDIS has registered */
57 LIST_ENTRY AdapterListHead;
58 KSPIN_LOCK AdapterListLock;
59
60 VOID
61 MiniDisplayPacket(
62 PNDIS_PACKET Packet)
63 {
64 #if DBG
65 ULONG i, Length;
66 UCHAR Buffer[64];
67 if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
68 Length = CopyPacketToBuffer(
69 Buffer,
70 Packet,
71 0,
72 64);
73
74 DbgPrint("*** PACKET START ***");
75
76 for (i = 0; i < Length; i++) {
77 if (i % 12 == 0)
78 DbgPrint("\n%04X ", i);
79 DbgPrint("%02X ", Buffer[i]);
80 }
81
82 DbgPrint("*** PACKET STOP ***\n");
83 }
84 #endif /* DBG */
85 }
86
87 VOID
88 MiniDisplayPacket2(
89 PVOID HeaderBuffer,
90 UINT HeaderBufferSize,
91 PVOID LookaheadBuffer,
92 UINT LookaheadBufferSize)
93 {
94 #if DBG
95 if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
96 ULONG i, Length;
97 PUCHAR p;
98
99 DbgPrint("*** RECEIVE PACKET START ***\n");
100 DbgPrint("HEADER:");
101 p = HeaderBuffer;
102 for (i = 0; i < HeaderBufferSize; i++) {
103 if (i % 16 == 0)
104 DbgPrint("\n%04X ", i);
105 DbgPrint("%02X ", *p++);
106 }
107
108 DbgPrint("\nFRAME:");
109
110 p = LookaheadBuffer;
111 Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
112 for (i = 0; i < Length; i++) {
113 if (i % 16 == 0)
114 DbgPrint("\n%04X ", i);
115 DbgPrint("%02X ", *p++);
116 }
117
118 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
119 }
120 #endif /* DBG */
121 }
122
123 PNDIS_MINIPORT_WORK_ITEM
124 MiniGetFirstWorkItem(
125 PLOGICAL_ADAPTER Adapter,
126 NDIS_WORK_ITEM_TYPE Type)
127 {
128 PNDIS_MINIPORT_WORK_ITEM CurrentEntry = Adapter->WorkQueueHead;
129
130 while (CurrentEntry)
131 {
132 if (CurrentEntry->WorkItemType == Type || Type == NdisMaxWorkItems)
133 return CurrentEntry;
134
135 CurrentEntry = (PNDIS_MINIPORT_WORK_ITEM)CurrentEntry->Link.Next;
136 }
137
138 return NULL;
139 }
140
141 BOOLEAN
142 MiniIsBusy(
143 PLOGICAL_ADAPTER Adapter,
144 NDIS_WORK_ITEM_TYPE Type)
145 {
146 BOOLEAN Busy = FALSE;
147 KIRQL OldIrql;
148
149 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
150
151 if (MiniGetFirstWorkItem(Adapter, Type))
152 {
153 Busy = TRUE;
154 }
155 else if (Type == NdisWorkItemRequest && Adapter->NdisMiniportBlock.PendingRequest)
156 {
157 Busy = TRUE;
158 }
159 else if (Type == NdisWorkItemSend && Adapter->NdisMiniportBlock.FirstPendingPacket)
160 {
161 Busy = TRUE;
162 }
163 else if (Type == NdisWorkItemResetRequested &&
164 Adapter->NdisMiniportBlock.ResetStatus == NDIS_STATUS_PENDING)
165 {
166 Busy = TRUE;
167 }
168
169 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
170
171 return Busy;
172 }
173
174 VOID
175 MiniIndicateData(
176 PLOGICAL_ADAPTER Adapter,
177 NDIS_HANDLE MacReceiveContext,
178 PVOID HeaderBuffer,
179 UINT HeaderBufferSize,
180 PVOID LookaheadBuffer,
181 UINT LookaheadBufferSize,
182 UINT PacketSize)
183 /*
184 * FUNCTION: Indicate received data to bound protocols
185 * ARGUMENTS:
186 * Adapter = Pointer to logical adapter
187 * MacReceiveContext = MAC receive context handle
188 * HeaderBuffer = Pointer to header buffer
189 * HeaderBufferSize = Size of header buffer
190 * LookaheadBuffer = Pointer to lookahead buffer
191 * LookaheadBufferSize = Size of lookahead buffer
192 * PacketSize = Total size of received packet
193 */
194 {
195 KIRQL OldIrql;
196 PLIST_ENTRY CurrentEntry;
197 PADAPTER_BINDING AdapterBinding;
198
199 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
200 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
201 Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
202
203 MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
204
205 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
206 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
207 {
208 CurrentEntry = Adapter->ProtocolListHead.Flink;
209 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
210
211 if (CurrentEntry == &Adapter->ProtocolListHead)
212 {
213 NDIS_DbgPrint(MIN_TRACE, ("WARNING: No upper protocol layer.\n"));
214 }
215
216 while (CurrentEntry != &Adapter->ProtocolListHead)
217 {
218 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
219 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
220
221 NDIS_DbgPrint
222 (MID_TRACE,
223 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
224 *AdapterBinding->ProtocolBinding->Chars.ReceiveHandler,
225 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
226 MacReceiveContext,
227 HeaderBuffer,
228 HeaderBufferSize,
229 LookaheadBuffer,
230 LookaheadBufferSize,
231 PacketSize));
232
233 /* call the receive handler */
234 (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
235 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
236 MacReceiveContext,
237 HeaderBuffer,
238 HeaderBufferSize,
239 LookaheadBuffer,
240 LookaheadBufferSize,
241 PacketSize);
242
243 CurrentEntry = CurrentEntry->Flink;
244 }
245 }
246 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
247
248 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
249 }
250
251 /*
252 * @implemented
253 */
254 VOID
255 EXPORT
256 NdisReturnPackets(
257 IN PNDIS_PACKET *PacketsToReturn,
258 IN UINT NumberOfPackets)
259 /*
260 * FUNCTION: Releases ownership of one or more packets
261 * ARGUMENTS:
262 * PacketsToReturn = Pointer to an array of pointers to packet descriptors
263 * NumberOfPackets = Number of pointers in descriptor pointer array
264 */
265 {
266 UINT i;
267 PLOGICAL_ADAPTER Adapter;
268 KIRQL OldIrql;
269
270 NDIS_DbgPrint(MID_TRACE, ("Returning %d packets\n", NumberOfPackets));
271
272 for (i = 0; i < NumberOfPackets; i++)
273 {
274 PacketsToReturn[i]->WrapperReserved[0]--;
275 if (PacketsToReturn[i]->WrapperReserved[0] == 0)
276 {
277 Adapter = (PVOID)(ULONG_PTR)PacketsToReturn[i]->Reserved[1];
278
279 NDIS_DbgPrint(MAX_TRACE, ("Freeing packet %d (adapter = 0x%p)\n", i, Adapter));
280
281 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
282 Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ReturnPacketHandler(
283 Adapter->NdisMiniportBlock.MiniportAdapterContext,
284 PacketsToReturn[i]);
285 KeLowerIrql(OldIrql);
286 }
287 }
288 }
289
290 VOID NTAPI
291 MiniIndicateReceivePacket(
292 IN NDIS_HANDLE MiniportAdapterHandle,
293 IN PPNDIS_PACKET PacketArray,
294 IN UINT NumberOfPackets)
295 /*
296 * FUNCTION: receives miniport packet array indications
297 * ARGUMENTS:
298 * MiniportAdapterHandle: Miniport handle for the adapter
299 * PacketArray: pointer to a list of packet pointers to indicate
300 * NumberOfPackets: number of packets to indicate
301 *
302 */
303 {
304 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
305 PLIST_ENTRY CurrentEntry;
306 PADAPTER_BINDING AdapterBinding;
307 KIRQL OldIrql;
308 UINT i;
309
310 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
311
312 CurrentEntry = Adapter->ProtocolListHead.Flink;
313
314 while (CurrentEntry != &Adapter->ProtocolListHead)
315 {
316 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
317
318 for (i = 0; i < NumberOfPackets; i++)
319 {
320 /* Store the indicating miniport in the packet */
321 PacketArray[i]->Reserved[1] = (ULONG_PTR)Adapter;
322
323 if (AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler &&
324 NDIS_GET_PACKET_STATUS(PacketArray[i]) != NDIS_STATUS_RESOURCES)
325 {
326 NDIS_DbgPrint(MID_TRACE, ("Indicating packet to protocol's ReceivePacket handler\n"));
327 PacketArray[i]->WrapperReserved[0] += (*AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)(
328 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
329 PacketArray[i]);
330 NDIS_DbgPrint(MID_TRACE, ("Protocol is holding %d references to the packet\n", PacketArray[i]->WrapperReserved[0]));
331 }
332 else
333 {
334 UINT FirstBufferLength, TotalBufferLength, LookAheadSize, HeaderSize;
335 PNDIS_BUFFER NdisBuffer;
336 PVOID NdisBufferVA, LookAheadBuffer;
337
338 NdisGetFirstBufferFromPacket(PacketArray[i],
339 &NdisBuffer,
340 &NdisBufferVA,
341 &FirstBufferLength,
342 &TotalBufferLength);
343
344 HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
345
346 LookAheadSize = TotalBufferLength - HeaderSize;
347
348 LookAheadBuffer = ExAllocatePool(NonPagedPool, LookAheadSize);
349 if (!LookAheadBuffer)
350 {
351 NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead buffer!\n"));
352 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
353 return;
354 }
355
356 CopyBufferChainToBuffer(LookAheadBuffer,
357 NdisBuffer,
358 HeaderSize,
359 LookAheadSize);
360
361 NDIS_DbgPrint(MID_TRACE, ("Indicating packet to protocol's legacy Receive handler\n"));
362 (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
363 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
364 AdapterBinding->NdisOpenBlock.MacHandle,
365 NdisBufferVA,
366 HeaderSize,
367 LookAheadBuffer,
368 LookAheadSize,
369 TotalBufferLength - HeaderSize);
370
371 ExFreePool(LookAheadBuffer);
372 }
373 }
374
375 CurrentEntry = CurrentEntry->Flink;
376 }
377
378 /* Loop the packet array to get everything
379 * set up for return the packets to the miniport */
380 for (i = 0; i < NumberOfPackets; i++)
381 {
382 /* First, check the initial packet status */
383 if (NDIS_GET_PACKET_STATUS(PacketArray[i]) == NDIS_STATUS_RESOURCES)
384 {
385 /* The miniport driver gets it back immediately so nothing to do here */
386 NDIS_DbgPrint(MID_TRACE, ("Miniport needs the packet back immediately\n"));
387 continue;
388 }
389
390 /* Different behavior depending on whether it's serialized or not */
391 if (Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
392 {
393 /* We need to check the reference count */
394 if (PacketArray[i]->WrapperReserved[0] == 0)
395 {
396 /* NOTE: Unlike serialized miniports, this is REQUIRED to be called for each
397 * packet received that can be reused immediately, it is not implied! */
398 Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ReturnPacketHandler(
399 Adapter->NdisMiniportBlock.MiniportAdapterContext,
400 PacketArray[i]);
401 NDIS_DbgPrint(MID_TRACE, ("Packet has been returned to miniport (Deserialized)\n"));
402 }
403 else
404 {
405 /* Packet will be returned by the protocol's call to NdisReturnPackets */
406 NDIS_DbgPrint(MID_TRACE, ("Packet will be returned to miniport later (Deserialized)\n"));
407 }
408 }
409 else
410 {
411 /* Check the reference count */
412 if (PacketArray[i]->WrapperReserved[0] == 0)
413 {
414 /* NDIS_STATUS_SUCCESS means the miniport can have the packet back immediately */
415 NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);
416
417 NDIS_DbgPrint(MID_TRACE, ("Packet has been returned to miniport (Serialized)\n"));
418 }
419 else
420 {
421 /* NDIS_STATUS_PENDING means the miniport needs to wait for MiniportReturnPacket */
422 NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_PENDING);
423
424 NDIS_DbgPrint(MID_TRACE, ("Packet will be returned to miniport later (Serialized)\n"));
425 }
426 }
427 }
428
429 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
430 }
431
432 VOID NTAPI
433 MiniResetComplete(
434 IN NDIS_HANDLE MiniportAdapterHandle,
435 IN NDIS_STATUS Status,
436 IN BOOLEAN AddressingReset)
437 {
438 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
439 PLIST_ENTRY CurrentEntry;
440 PADAPTER_BINDING AdapterBinding;
441 KIRQL OldIrql;
442
443 if (AddressingReset)
444 MiniDoAddressingReset(Adapter);
445
446 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
447 NdisMIndicateStatusComplete(Adapter);
448
449 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
450
451 if (Adapter->NdisMiniportBlock.ResetStatus != NDIS_STATUS_PENDING)
452 {
453 KeBugCheckEx(BUGCODE_ID_DRIVER,
454 (ULONG_PTR)MiniportAdapterHandle,
455 (ULONG_PTR)Status,
456 (ULONG_PTR)AddressingReset,
457 0);
458 }
459
460 Adapter->NdisMiniportBlock.ResetStatus = Status;
461
462 CurrentEntry = Adapter->ProtocolListHead.Flink;
463
464 while (CurrentEntry != &Adapter->ProtocolListHead)
465 {
466 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
467
468 (*AdapterBinding->ProtocolBinding->Chars.ResetCompleteHandler)(
469 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
470 Status);
471
472 CurrentEntry = CurrentEntry->Flink;
473 }
474
475 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
476 }
477
478 VOID NTAPI
479 MiniRequestComplete(
480 IN NDIS_HANDLE MiniportAdapterHandle,
481 IN NDIS_STATUS Status)
482 {
483 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
484 PNDIS_REQUEST Request;
485 PNDIS_REQUEST_MAC_BLOCK MacBlock;
486 KIRQL OldIrql;
487
488 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
489
490 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
491
492 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
493 Request = Adapter->NdisMiniportBlock.PendingRequest;
494 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
495
496 MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
497
498 /* We may or may not be doing this request on behalf of an adapter binding */
499 if (MacBlock->Binding != NULL)
500 {
501 /* We are, so invoke its request complete handler */
502 if (MacBlock->Binding->RequestCompleteHandler != NULL)
503 {
504 (*MacBlock->Binding->RequestCompleteHandler)(
505 MacBlock->Binding->ProtocolBindingContext,
506 Request,
507 Status);
508 }
509 }
510 else
511 {
512 /* We are doing this internally, so we'll signal this event we've stashed in the MacBlock */
513 ASSERT(MacBlock->Unknown1 != NULL);
514 ASSERT(MacBlock->Unknown3 == NULL);
515 MacBlock->Unknown3 = (PVOID)Status;
516 KeSetEvent(MacBlock->Unknown1, IO_NO_INCREMENT, FALSE);
517 }
518
519 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
520 Adapter->NdisMiniportBlock.PendingRequest = NULL;
521 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
522 KeLowerIrql(OldIrql);
523
524 MiniWorkItemComplete(Adapter, NdisWorkItemRequest);
525 }
526
527 VOID NTAPI
528 MiniSendComplete(
529 IN NDIS_HANDLE MiniportAdapterHandle,
530 IN PNDIS_PACKET Packet,
531 IN NDIS_STATUS Status)
532 /*
533 * FUNCTION: Forwards a message to the initiating protocol saying
534 * that a packet was handled
535 * ARGUMENTS:
536 * NdisAdapterHandle = Handle input to MiniportInitialize
537 * Packet = Pointer to NDIS packet that was sent
538 * Status = Status of send operation
539 */
540 {
541 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
542 PADAPTER_BINDING AdapterBinding;
543 KIRQL OldIrql;
544 PSCATTER_GATHER_LIST SGList;
545
546 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
547
548 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
549
550 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
551
552 if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
553 {
554 NDIS_DbgPrint(MAX_TRACE, ("Freeing Scatter/Gather list\n"));
555
556 SGList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
557 ScatterGatherListPacketInfo);
558
559 Adapter->NdisMiniportBlock.SystemAdapterObject->
560 DmaOperations->PutScatterGatherList(
561 Adapter->NdisMiniportBlock.SystemAdapterObject,
562 SGList,
563 TRUE);
564
565 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
566 ScatterGatherListPacketInfo) = NULL;
567 }
568
569 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
570 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
571 Packet,
572 Status);
573
574 KeLowerIrql(OldIrql);
575
576 MiniWorkItemComplete(Adapter, NdisWorkItemSend);
577 }
578
579
580 VOID NTAPI
581 MiniSendResourcesAvailable(
582 IN NDIS_HANDLE MiniportAdapterHandle)
583 {
584 /* Run the work if anything is waiting */
585 MiniWorkItemComplete((PLOGICAL_ADAPTER)MiniportAdapterHandle, NdisWorkItemSend);
586 }
587
588
589 VOID NTAPI
590 MiniTransferDataComplete(
591 IN NDIS_HANDLE MiniportAdapterHandle,
592 IN PNDIS_PACKET Packet,
593 IN NDIS_STATUS Status,
594 IN UINT BytesTransferred)
595 {
596 PADAPTER_BINDING AdapterBinding;
597 KIRQL OldIrql;
598
599 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
600
601 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
602
603 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
604 (*AdapterBinding->ProtocolBinding->Chars.TransferDataCompleteHandler)(
605 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
606 Packet,
607 Status,
608 BytesTransferred);
609 KeLowerIrql(OldIrql);
610 }
611
612
613 BOOLEAN
614 MiniAdapterHasAddress(
615 PLOGICAL_ADAPTER Adapter,
616 PNDIS_PACKET Packet)
617 /*
618 * FUNCTION: Determines whether a packet has the same destination address as an adapter
619 * ARGUMENTS:
620 * Adapter = Pointer to logical adapter object
621 * Packet = Pointer to NDIS packet
622 * RETURNS:
623 * TRUE if the destination address is that of the adapter, FALSE if not
624 */
625 {
626 UINT Length;
627 PUCHAR Start1;
628 PUCHAR Start2;
629 PNDIS_BUFFER NdisBuffer;
630 UINT BufferLength;
631
632 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
633
634 #if DBG
635 if(!Adapter)
636 {
637 NDIS_DbgPrint(MIN_TRACE, ("Adapter object was null\n"));
638 return FALSE;
639 }
640
641 if(!Packet)
642 {
643 NDIS_DbgPrint(MIN_TRACE, ("Packet was null\n"));
644 return FALSE;
645 }
646 #endif
647
648 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
649
650 if (!NdisBuffer)
651 {
652 NDIS_DbgPrint(MIN_TRACE, ("Packet contains no buffers.\n"));
653 return FALSE;
654 }
655
656 NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
657
658 /* FIXME: Should handle fragmented packets */
659
660 switch (Adapter->NdisMiniportBlock.MediaType)
661 {
662 case NdisMedium802_3:
663 Length = ETH_LENGTH_OF_ADDRESS;
664 /* Destination address is the first field */
665 break;
666
667 default:
668 NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
669 return FALSE;
670 }
671
672 if (BufferLength < Length)
673 {
674 NDIS_DbgPrint(MIN_TRACE, ("Buffer is too small.\n"));
675 return FALSE;
676 }
677
678 Start1 = (PUCHAR)&Adapter->Address;
679 NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
680 *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
681 *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5)));
682
683 return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
684 }
685
686
687 PLOGICAL_ADAPTER
688 MiniLocateDevice(
689 PNDIS_STRING AdapterName)
690 /*
691 * FUNCTION: Finds an adapter object by name
692 * ARGUMENTS:
693 * AdapterName = Pointer to name of adapter
694 * RETURNS:
695 * Pointer to logical adapter object, or NULL if none was found.
696 * If found, the adapter is referenced for the caller. The caller
697 * is responsible for dereferencing after use
698 */
699 {
700 KIRQL OldIrql;
701 PLIST_ENTRY CurrentEntry;
702 PLOGICAL_ADAPTER Adapter = 0;
703
704 ASSERT(AdapterName);
705
706 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
707
708 if(IsListEmpty(&AdapterListHead))
709 {
710 NDIS_DbgPrint(MIN_TRACE, ("No registered miniports for protocol to bind to\n"));
711 return NULL;
712 }
713
714 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
715
716 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
717 {
718 CurrentEntry = AdapterListHead.Flink;
719
720 while (CurrentEntry != &AdapterListHead)
721 {
722 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
723
724 ASSERT(Adapter);
725
726 NDIS_DbgPrint(DEBUG_MINIPORT, ("Examining adapter 0x%lx\n", Adapter));
727
728 /* We're technically not allowed to call this above PASSIVE_LEVEL, but it doesn't break
729 * right now and I'd rather use a working API than reimplement it here */
730 if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
731 {
732 break;
733 }
734
735 Adapter = NULL;
736 CurrentEntry = CurrentEntry->Flink;
737 }
738 }
739 KeReleaseSpinLock(&AdapterListLock, OldIrql);
740
741 if(Adapter)
742 {
743 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
744 }
745 else
746 {
747 NDIS_DbgPrint(MIN_TRACE, ("Leaving (adapter not found for %wZ).\n", AdapterName));
748 }
749
750 return Adapter;
751 }
752
753 NDIS_STATUS
754 MiniSetInformation(
755 PLOGICAL_ADAPTER Adapter,
756 NDIS_OID Oid,
757 ULONG Size,
758 PVOID Buffer,
759 PULONG BytesRead)
760 {
761 NDIS_STATUS NdisStatus;
762 PNDIS_REQUEST NdisRequest;
763 KEVENT Event;
764 PNDIS_REQUEST_MAC_BLOCK MacBlock;
765
766 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
767
768 NdisRequest = ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
769 if (!NdisRequest) {
770 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
771 return NDIS_STATUS_RESOURCES;
772 }
773
774 RtlZeroMemory(NdisRequest, sizeof(NDIS_REQUEST));
775
776 NdisRequest->RequestType = NdisRequestSetInformation;
777 NdisRequest->DATA.SET_INFORMATION.Oid = Oid;
778 NdisRequest->DATA.SET_INFORMATION.InformationBuffer = Buffer;
779 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = Size;
780
781 /* We'll need to give the completion routine some way of letting us know
782 * when it's finished. We'll stash a pointer to an event in the MacBlock */
783 KeInitializeEvent(&Event, NotificationEvent, FALSE);
784 MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
785 MacBlock->Unknown1 = &Event;
786
787 NdisStatus = MiniDoRequest(Adapter, NdisRequest);
788
789 if (NdisStatus == NDIS_STATUS_PENDING)
790 {
791 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
792 NdisStatus = (NDIS_STATUS)MacBlock->Unknown3;
793 }
794
795 *BytesRead = NdisRequest->DATA.SET_INFORMATION.BytesRead;
796
797 ExFreePool(NdisRequest);
798
799 return NdisStatus;
800 }
801
802 NDIS_STATUS
803 MiniQueryInformation(
804 PLOGICAL_ADAPTER Adapter,
805 NDIS_OID Oid,
806 ULONG Size,
807 PVOID Buffer,
808 PULONG BytesWritten)
809 /*
810 * FUNCTION: Queries a logical adapter for properties
811 * ARGUMENTS:
812 * Adapter = Pointer to the logical adapter object to query
813 * Oid = Specifies the Object ID to query for
814 * Size = Size of the passed buffer
815 * Buffer = Buffer for the output
816 * BytesWritten = Address of buffer to place number of bytes written
817 * RETURNS:
818 * Status of operation
819 */
820 {
821 NDIS_STATUS NdisStatus;
822 PNDIS_REQUEST NdisRequest;
823 KEVENT Event;
824 PNDIS_REQUEST_MAC_BLOCK MacBlock;
825
826 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
827
828 NdisRequest = ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
829 if (!NdisRequest) {
830 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
831 return NDIS_STATUS_RESOURCES;
832 }
833
834 RtlZeroMemory(NdisRequest, sizeof(NDIS_REQUEST));
835
836 NdisRequest->RequestType = NdisRequestQueryInformation;
837 NdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
838 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
839 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size;
840
841 /* We'll need to give the completion routine some way of letting us know
842 * when it's finished. We'll stash a pointer to an event in the MacBlock */
843 KeInitializeEvent(&Event, NotificationEvent, FALSE);
844 MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
845 MacBlock->Unknown1 = &Event;
846
847 NdisStatus = MiniDoRequest(Adapter, NdisRequest);
848
849 if (NdisStatus == NDIS_STATUS_PENDING)
850 {
851 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
852 NdisStatus = (NDIS_STATUS)MacBlock->Unknown3;
853 }
854
855 *BytesWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
856
857 ExFreePool(NdisRequest);
858
859 return NdisStatus;
860 }
861
862 BOOLEAN
863 MiniCheckForHang( PLOGICAL_ADAPTER Adapter )
864 /*
865 * FUNCTION: Checks to see if the miniport is hung
866 * ARGUMENTS:
867 * Adapter = Pointer to the logical adapter object
868 * RETURNS:
869 * TRUE if the miniport is hung
870 * FALSE if the miniport is not hung
871 */
872 {
873 BOOLEAN Ret = FALSE;
874 KIRQL OldIrql;
875
876 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
877 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)
878 Ret = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)(
879 Adapter->NdisMiniportBlock.MiniportAdapterContext);
880 KeLowerIrql(OldIrql);
881
882 return Ret;
883 }
884
885 VOID
886 MiniDoAddressingReset(PLOGICAL_ADAPTER Adapter)
887 {
888 ULONG BytesRead;
889
890 MiniSetInformation(Adapter,
891 OID_GEN_CURRENT_LOOKAHEAD,
892 sizeof(ULONG),
893 &Adapter->NdisMiniportBlock.CurrentLookahead,
894 &BytesRead);
895
896 /* FIXME: Set more stuff */
897 }
898
899 NDIS_STATUS
900 MiniReset(
901 PLOGICAL_ADAPTER Adapter)
902 /*
903 * FUNCTION: Resets the miniport
904 * ARGUMENTS:
905 * Adapter = Pointer to the logical adapter object
906 * RETURNS:
907 * Status of the operation
908 */
909 {
910 NDIS_STATUS Status;
911 KIRQL OldIrql;
912 BOOLEAN AddressingReset = TRUE;
913
914 if (MiniIsBusy(Adapter, NdisWorkItemResetRequested)) {
915 MiniQueueWorkItem(Adapter, NdisWorkItemResetRequested, NULL, FALSE);
916 return NDIS_STATUS_PENDING;
917 }
918
919 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
920 NdisMIndicateStatusComplete(Adapter);
921
922 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
923 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
924 &AddressingReset,
925 Adapter->NdisMiniportBlock.MiniportAdapterContext);
926
927 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
928 Adapter->NdisMiniportBlock.ResetStatus = Status;
929 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
930
931 KeLowerIrql(OldIrql);
932
933 if (Status != NDIS_STATUS_PENDING) {
934 if (AddressingReset)
935 MiniDoAddressingReset(Adapter);
936
937 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
938 NdisMIndicateStatusComplete(Adapter);
939
940 MiniWorkItemComplete(Adapter, NdisWorkItemResetRequested);
941 }
942
943 return Status;
944 }
945
946 VOID NTAPI
947 MiniportHangDpc(
948 PKDPC Dpc,
949 PVOID DeferredContext,
950 PVOID SystemArgument1,
951 PVOID SystemArgument2)
952 {
953 PLOGICAL_ADAPTER Adapter = DeferredContext;
954
955 if (MiniCheckForHang(Adapter)) {
956 NDIS_DbgPrint(MIN_TRACE, ("Miniport detected adapter hang\n"));
957 MiniReset(Adapter);
958 }
959 }
960
961 VOID
962 MiniWorkItemComplete(
963 PLOGICAL_ADAPTER Adapter,
964 NDIS_WORK_ITEM_TYPE WorkItemType)
965 {
966 PIO_WORKITEM IoWorkItem;
967
968 /* Check if there's anything queued to run after this work item */
969 if (!MiniIsBusy(Adapter, WorkItemType))
970 return;
971
972 /* There is, so fire the worker */
973 IoWorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
974 if (IoWorkItem)
975 IoQueueWorkItem(IoWorkItem, MiniportWorker, DelayedWorkQueue, IoWorkItem);
976 }
977
978 VOID
979 FASTCALL
980 MiniQueueWorkItem(
981 PLOGICAL_ADAPTER Adapter,
982 NDIS_WORK_ITEM_TYPE WorkItemType,
983 PVOID WorkItemContext,
984 BOOLEAN Top)
985 /*
986 * FUNCTION: Queues a work item for execution at a later time
987 * ARGUMENTS:
988 * Adapter = Pointer to the logical adapter object to queue work item on
989 * WorkItemType = Type of work item to queue
990 * WorkItemContext = Pointer to context information for work item
991 * RETURNS:
992 * Status of operation
993 */
994 {
995 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
996 KIRQL OldIrql;
997
998 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
999
1000 ASSERT(Adapter);
1001
1002 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1003 if (Top)
1004 {
1005 if (WorkItemType == NdisWorkItemSend)
1006 {
1007 NDIS_DbgPrint(MIN_TRACE, ("Requeuing failed packet (%x).\n", WorkItemContext));
1008 Adapter->NdisMiniportBlock.FirstPendingPacket = WorkItemContext;
1009 }
1010 else
1011 {
1012 //This should never happen
1013 ASSERT(FALSE);
1014 }
1015 }
1016 else
1017 {
1018 MiniportWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
1019 if (!MiniportWorkItem)
1020 {
1021 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1022 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1023 return;
1024 }
1025
1026 MiniportWorkItem->WorkItemType = WorkItemType;
1027 MiniportWorkItem->WorkItemContext = WorkItemContext;
1028
1029 /* safe due to adapter lock held */
1030 MiniportWorkItem->Link.Next = NULL;
1031 if (!Adapter->WorkQueueHead)
1032 {
1033 Adapter->WorkQueueHead = MiniportWorkItem;
1034 Adapter->WorkQueueTail = MiniportWorkItem;
1035 }
1036 else
1037 {
1038 Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)MiniportWorkItem;
1039 Adapter->WorkQueueTail = MiniportWorkItem;
1040 }
1041 }
1042
1043 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1044 }
1045
1046 NDIS_STATUS
1047 FASTCALL
1048 MiniDequeueWorkItem(
1049 PLOGICAL_ADAPTER Adapter,
1050 NDIS_WORK_ITEM_TYPE *WorkItemType,
1051 PVOID *WorkItemContext)
1052 /*
1053 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
1054 * ARGUMENTS:
1055 * Adapter = Pointer to the logical adapter object to dequeue work item from
1056 * AdapterBinding = Address of buffer for adapter binding for this request
1057 * WorkItemType = Address of buffer for work item type
1058 * WorkItemContext = Address of buffer for pointer to context information
1059 * NOTES:
1060 * Adapter lock must be held when called
1061 * RETURNS:
1062 * Status of operation
1063 */
1064 {
1065 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
1066 PNDIS_PACKET Packet;
1067
1068 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1069
1070 MiniportWorkItem = Adapter->WorkQueueHead;
1071
1072 if ((Packet = Adapter->NdisMiniportBlock.FirstPendingPacket))
1073 {
1074 Adapter->NdisMiniportBlock.FirstPendingPacket = NULL;
1075
1076 *WorkItemType = NdisWorkItemSend;
1077 *WorkItemContext = Packet;
1078
1079 return NDIS_STATUS_SUCCESS;
1080 }
1081 else if (MiniportWorkItem)
1082 {
1083 /* safe due to adapter lock held */
1084 Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)MiniportWorkItem->Link.Next;
1085
1086 if (MiniportWorkItem == Adapter->WorkQueueTail)
1087 Adapter->WorkQueueTail = NULL;
1088
1089 *WorkItemType = MiniportWorkItem->WorkItemType;
1090 *WorkItemContext = MiniportWorkItem->WorkItemContext;
1091
1092 ExFreePool(MiniportWorkItem);
1093
1094 return NDIS_STATUS_SUCCESS;
1095 }
1096 else
1097 {
1098 NDIS_DbgPrint(MIN_TRACE, ("No work item to dequeue\n"));
1099
1100 return NDIS_STATUS_FAILURE;
1101 }
1102 }
1103
1104 NDIS_STATUS
1105 MiniDoRequest(
1106 PLOGICAL_ADAPTER Adapter,
1107 PNDIS_REQUEST NdisRequest)
1108 /*
1109 * FUNCTION: Sends a request to a miniport
1110 * ARGUMENTS:
1111 * AdapterBinding = Pointer to binding used in the request
1112 * NdisRequest = Pointer to NDIS request structure describing request
1113 * RETURNS:
1114 * Status of operation
1115 */
1116 {
1117 NDIS_STATUS Status;
1118 KIRQL OldIrql;
1119 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1120
1121 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1122
1123 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1124 Adapter->NdisMiniportBlock.PendingRequest = NdisRequest;
1125 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1126
1127 if (!Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)
1128 {
1129 switch (NdisRequest->RequestType)
1130 {
1131 case NdisRequestQueryInformation:
1132 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
1133 Adapter->NdisMiniportBlock.MiniportAdapterContext,
1134 NdisRequest->DATA.QUERY_INFORMATION.Oid,
1135 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
1136 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
1137 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
1138 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
1139 break;
1140
1141 case NdisRequestSetInformation:
1142 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SetInformationHandler)(
1143 Adapter->NdisMiniportBlock.MiniportAdapterContext,
1144 NdisRequest->DATA.SET_INFORMATION.Oid,
1145 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
1146 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
1147 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
1148 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
1149 break;
1150
1151 default:
1152 NDIS_DbgPrint(MIN_TRACE, ("Bad request type\n"));
1153 Status = NDIS_STATUS_FAILURE;
1154 }
1155 }
1156 else
1157 {
1158 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)(
1159 Adapter->NdisMiniportBlock.MiniportAdapterContext,
1160 NULL, /* FIXME */
1161 NdisRequest);
1162 }
1163
1164 if (Status != NDIS_STATUS_PENDING) {
1165 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1166 Adapter->NdisMiniportBlock.PendingRequest = NULL;
1167 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1168 }
1169
1170 KeLowerIrql(OldIrql);
1171
1172 if (Status != NDIS_STATUS_PENDING) {
1173 MiniWorkItemComplete(Adapter, NdisWorkItemRequest);
1174 }
1175
1176 return Status;
1177 }
1178
1179 /*
1180 * @implemented
1181 */
1182 #undef NdisMSetInformationComplete
1183 VOID
1184 EXPORT
1185 NdisMSetInformationComplete(
1186 IN NDIS_HANDLE MiniportAdapterHandle,
1187 IN NDIS_STATUS Status)
1188 {
1189 PLOGICAL_ADAPTER Adapter =
1190 (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1191 KIRQL OldIrql;
1192 ASSERT(Adapter);
1193 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1194 if (Adapter->NdisMiniportBlock.SetCompleteHandler)
1195 (Adapter->NdisMiniportBlock.SetCompleteHandler)(MiniportAdapterHandle, Status);
1196 KeLowerIrql(OldIrql);
1197 }
1198
1199 /*
1200 * @implemented
1201 */
1202 #undef NdisMQueryInformationComplete
1203 VOID
1204 EXPORT
1205 NdisMQueryInformationComplete(
1206 IN NDIS_HANDLE MiniportAdapterHandle,
1207 IN NDIS_STATUS Status)
1208 {
1209 PLOGICAL_ADAPTER Adapter =
1210 (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1211 KIRQL OldIrql;
1212 ASSERT(Adapter);
1213 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1214 if( Adapter->NdisMiniportBlock.QueryCompleteHandler )
1215 (Adapter->NdisMiniportBlock.QueryCompleteHandler)(MiniportAdapterHandle, Status);
1216 KeLowerIrql(OldIrql);
1217 }
1218
1219 VOID
1220 NTAPI
1221 MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
1222 {
1223 PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
1224 KIRQL OldIrql, RaiseOldIrql;
1225 NDIS_STATUS NdisStatus;
1226 PVOID WorkItemContext;
1227 NDIS_WORK_ITEM_TYPE WorkItemType;
1228 BOOLEAN AddressingReset;
1229
1230 IoFreeWorkItem((PIO_WORKITEM)Context);
1231
1232 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1233
1234 NdisStatus =
1235 MiniDequeueWorkItem
1236 (Adapter, &WorkItemType, &WorkItemContext);
1237
1238 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1239
1240 if (NdisStatus == NDIS_STATUS_SUCCESS)
1241 {
1242 switch (WorkItemType)
1243 {
1244 case NdisWorkItemSend:
1245 /*
1246 * called by ProSend when protocols want to send packets to the miniport
1247 */
1248
1249 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
1250 {
1251 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
1252 {
1253 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
1254 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
1255 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
1256 NdisStatus = NDIS_STATUS_PENDING;
1257 }
1258 else
1259 {
1260 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
1261 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
1262 {
1263 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
1264 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
1265 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
1266 }
1267 KeLowerIrql(RaiseOldIrql);
1268
1269 NdisStatus = NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
1270 if( NdisStatus == NDIS_STATUS_RESOURCES ) {
1271 MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext, TRUE);
1272 break;
1273 }
1274 }
1275 }
1276 else
1277 {
1278 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
1279 {
1280 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
1281 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
1282 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext,
1283 ((PNDIS_PACKET)WorkItemContext)->Private.Flags);
1284 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
1285 }
1286 else
1287 {
1288 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
1289 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
1290 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
1291 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
1292 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext,
1293 ((PNDIS_PACKET)WorkItemContext)->Private.Flags);
1294 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
1295 KeLowerIrql(RaiseOldIrql);
1296 if( NdisStatus == NDIS_STATUS_RESOURCES ) {
1297 MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext, TRUE);
1298 break;
1299 }
1300 }
1301 }
1302
1303 if( NdisStatus != NDIS_STATUS_PENDING ) {
1304 MiniSendComplete
1305 ( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
1306 }
1307 break;
1308
1309 case NdisWorkItemSendLoopback:
1310 /*
1311 * called by ProSend when protocols want to send loopback packets
1312 */
1313 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
1314 NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
1315
1316 if( NdisStatus != NDIS_STATUS_PENDING )
1317 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
1318 break;
1319
1320 case NdisWorkItemReturnPackets:
1321 break;
1322
1323 case NdisWorkItemResetRequested:
1324 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
1325 NdisMIndicateStatusComplete(Adapter);
1326
1327 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1328 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
1329 &AddressingReset,
1330 Adapter->NdisMiniportBlock.MiniportAdapterContext);
1331
1332 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1333 Adapter->NdisMiniportBlock.ResetStatus = NdisStatus;
1334 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1335
1336 KeLowerIrql(OldIrql);
1337
1338 if (NdisStatus != NDIS_STATUS_PENDING)
1339 MiniResetComplete(Adapter, NdisStatus, AddressingReset);
1340 break;
1341
1342 case NdisWorkItemResetInProgress:
1343 break;
1344
1345 case NdisWorkItemMiniportCallback:
1346 break;
1347
1348 case NdisWorkItemRequest:
1349 NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
1350
1351 if (NdisStatus == NDIS_STATUS_PENDING)
1352 break;
1353
1354 Adapter->NdisMiniportBlock.PendingRequest = (PNDIS_REQUEST)WorkItemContext;
1355 switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
1356 {
1357 case NdisRequestQueryInformation:
1358 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
1359 break;
1360
1361 case NdisRequestSetInformation:
1362 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
1363 break;
1364
1365 default:
1366 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
1367 break;
1368 }
1369 Adapter->NdisMiniportBlock.PendingRequest = NULL;
1370 break;
1371
1372 default:
1373 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
1374 break;
1375 }
1376 }
1377 }
1378
1379
1380 VOID
1381 NTAPI
1382 MiniStatus(
1383 IN NDIS_HANDLE MiniportHandle,
1384 IN NDIS_STATUS GeneralStatus,
1385 IN PVOID StatusBuffer,
1386 IN UINT StatusBufferSize)
1387 {
1388 PLOGICAL_ADAPTER Adapter = MiniportHandle;
1389 PLIST_ENTRY CurrentEntry;
1390 PADAPTER_BINDING AdapterBinding;
1391 KIRQL OldIrql;
1392
1393 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1394
1395 CurrentEntry = Adapter->ProtocolListHead.Flink;
1396
1397 while (CurrentEntry != &Adapter->ProtocolListHead)
1398 {
1399 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
1400
1401 (*AdapterBinding->ProtocolBinding->Chars.StatusHandler)(
1402 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1403 GeneralStatus,
1404 StatusBuffer,
1405 StatusBufferSize);
1406
1407 CurrentEntry = CurrentEntry->Flink;
1408 }
1409
1410 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1411 }
1412
1413 VOID
1414 NTAPI
1415 MiniStatusComplete(
1416 IN NDIS_HANDLE MiniportAdapterHandle)
1417 {
1418 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
1419 PLIST_ENTRY CurrentEntry;
1420 PADAPTER_BINDING AdapterBinding;
1421 KIRQL OldIrql;
1422
1423 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1424
1425 CurrentEntry = Adapter->ProtocolListHead.Flink;
1426
1427 while (CurrentEntry != &Adapter->ProtocolListHead)
1428 {
1429 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
1430
1431 (*AdapterBinding->ProtocolBinding->Chars.StatusCompleteHandler)(
1432 AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
1433
1434 CurrentEntry = CurrentEntry->Flink;
1435 }
1436
1437 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1438 }
1439
1440 /*
1441 * @implemented
1442 */
1443 VOID
1444 EXPORT
1445 NdisMCloseLog(
1446 IN NDIS_HANDLE LogHandle)
1447 {
1448 PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
1449 PNDIS_MINIPORT_BLOCK Miniport = Log->Miniport;
1450 KIRQL OldIrql;
1451
1452 NDIS_DbgPrint(MAX_TRACE, ("called: LogHandle 0x%x\n", LogHandle));
1453
1454 KeAcquireSpinLock(&(Miniport)->Lock, &OldIrql);
1455 Miniport->Log = NULL;
1456 KeReleaseSpinLock(&(Miniport)->Lock, OldIrql);
1457
1458 ExFreePool(Log);
1459 }
1460
1461 /*
1462 * @implemented
1463 */
1464 NDIS_STATUS
1465 EXPORT
1466 NdisMCreateLog(
1467 IN NDIS_HANDLE MiniportAdapterHandle,
1468 IN UINT Size,
1469 OUT PNDIS_HANDLE LogHandle)
1470 {
1471 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
1472 PNDIS_LOG Log;
1473 KIRQL OldIrql;
1474
1475 NDIS_DbgPrint(MAX_TRACE, ("called: MiniportAdapterHandle 0x%x, Size %ld\n", MiniportAdapterHandle, Size));
1476
1477 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1478
1479 if (Adapter->NdisMiniportBlock.Log)
1480 {
1481 *LogHandle = NULL;
1482 return NDIS_STATUS_FAILURE;
1483 }
1484
1485 Log = ExAllocatePool(NonPagedPool, Size + sizeof(NDIS_LOG));
1486 if (!Log)
1487 {
1488 *LogHandle = NULL;
1489 return NDIS_STATUS_RESOURCES;
1490 }
1491
1492 Adapter->NdisMiniportBlock.Log = Log;
1493
1494 KeInitializeSpinLock(&Log->LogLock);
1495
1496 Log->Miniport = &Adapter->NdisMiniportBlock;
1497 Log->TotalSize = Size;
1498 Log->CurrentSize = 0;
1499 Log->OutPtr = 0;
1500 Log->InPtr = 0;
1501 Log->Irp = NULL;
1502
1503 *LogHandle = Log;
1504
1505 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1506
1507 return NDIS_STATUS_SUCCESS;
1508 }
1509
1510 /*
1511 * @implemented
1512 */
1513 VOID
1514 EXPORT
1515 NdisMDeregisterAdapterShutdownHandler(
1516 IN NDIS_HANDLE MiniportHandle)
1517 /*
1518 * FUNCTION: de-registers a shutdown handler
1519 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1520 */
1521 {
1522 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1523
1524 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1525
1526 if(Adapter->BugcheckContext->ShutdownHandler) {
1527 KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
1528 IoUnregisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
1529 }
1530 }
1531
1532 /*
1533 * @implemented
1534 */
1535 VOID
1536 EXPORT
1537 NdisMFlushLog(
1538 IN NDIS_HANDLE LogHandle)
1539 {
1540 PNDIS_LOG Log = (PNDIS_LOG) LogHandle;
1541 KIRQL OldIrql;
1542
1543 NDIS_DbgPrint(MAX_TRACE, ("called: LogHandle 0x%x\n", LogHandle));
1544
1545 /* Lock object */
1546 KeAcquireSpinLock(&Log->LogLock, &OldIrql);
1547
1548 /* Set buffers size */
1549 Log->CurrentSize = 0;
1550 Log->OutPtr = 0;
1551 Log->InPtr = 0;
1552
1553 /* Unlock object */
1554 KeReleaseSpinLock(&Log->LogLock, OldIrql);
1555 }
1556
1557 /*
1558 * @implemented
1559 */
1560 #undef NdisMIndicateStatus
1561 VOID
1562 EXPORT
1563 NdisMIndicateStatus(
1564 IN NDIS_HANDLE MiniportAdapterHandle,
1565 IN NDIS_STATUS GeneralStatus,
1566 IN PVOID StatusBuffer,
1567 IN UINT StatusBufferSize)
1568 {
1569 MiniStatus(MiniportAdapterHandle, GeneralStatus, StatusBuffer, StatusBufferSize);
1570 }
1571
1572 /*
1573 * @implemented
1574 */
1575 #undef NdisMIndicateStatusComplete
1576 VOID
1577 EXPORT
1578 NdisMIndicateStatusComplete(
1579 IN NDIS_HANDLE MiniportAdapterHandle)
1580 {
1581 MiniStatusComplete(MiniportAdapterHandle);
1582 }
1583
1584 /*
1585 * @implemented
1586 */
1587 VOID
1588 EXPORT
1589 NdisInitializeWrapper(
1590 OUT PNDIS_HANDLE NdisWrapperHandle,
1591 IN PVOID SystemSpecific1,
1592 IN PVOID SystemSpecific2,
1593 IN PVOID SystemSpecific3)
1594 /*
1595 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1596 * ARGUMENTS:
1597 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1598 * SystemSpecific1 = Pointer to the driver's driver object
1599 * SystemSpecific2 = Pointer to the driver's registry path
1600 * SystemSpecific3 = Always NULL
1601 * NOTES:
1602 * - SystemSpecific2 goes invalid so we copy it
1603 */
1604 {
1605 PNDIS_M_DRIVER_BLOCK Miniport;
1606 PUNICODE_STRING RegistryPath;
1607 WCHAR *RegistryBuffer;
1608
1609 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1610
1611 ASSERT(NdisWrapperHandle);
1612
1613 *NdisWrapperHandle = NULL;
1614
1615 #if BREAK_ON_MINIPORT_INIT
1616 DbgBreakPoint();
1617 #endif
1618
1619 Miniport = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DRIVER_BLOCK));
1620
1621 if (!Miniport)
1622 {
1623 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1624 return;
1625 }
1626
1627 RtlZeroMemory(Miniport, sizeof(NDIS_M_DRIVER_BLOCK));
1628
1629 KeInitializeSpinLock(&Miniport->Lock);
1630
1631 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
1632
1633 /* set the miniport's driver registry path */
1634 RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
1635 if(!RegistryPath)
1636 {
1637 ExFreePool(Miniport);
1638 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1639 return;
1640 }
1641
1642 RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
1643 RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR); /* room for 0-term */
1644
1645 RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
1646 if(!RegistryBuffer)
1647 {
1648 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1649 ExFreePool(Miniport);
1650 ExFreePool(RegistryPath);
1651 return;
1652 }
1653
1654 RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
1655 RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
1656
1657 RegistryPath->Buffer = RegistryBuffer;
1658 Miniport->RegistryPath = RegistryPath;
1659
1660 InitializeListHead(&Miniport->DeviceList);
1661
1662 /* Put miniport in global miniport list */
1663 ExInterlockedInsertTailList(&MiniportListHead, &Miniport->ListEntry, &MiniportListLock);
1664
1665 *NdisWrapperHandle = Miniport;
1666 }
1667
1668 VOID NTAPI NdisIBugcheckCallback(
1669 IN PVOID Buffer,
1670 IN ULONG Length)
1671 /*
1672 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1673 * ARGUMENTS:
1674 * Buffer: Pointer to a bugcheck callback context
1675 * Length: Unused
1676 */
1677 {
1678 PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
1679 ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
1680
1681 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1682
1683 if(sh)
1684 sh(Context->DriverContext);
1685 }
1686
1687 /*
1688 * @implemented
1689 */
1690 VOID
1691 EXPORT
1692 NdisMRegisterAdapterShutdownHandler(
1693 IN NDIS_HANDLE MiniportHandle,
1694 IN PVOID ShutdownContext,
1695 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
1696 /*
1697 * FUNCTION: Register a shutdown handler for an adapter
1698 * ARGUMENTS:
1699 * MiniportHandle: Handle originally passed into MiniportInitialize
1700 * ShutdownContext: Pre-initialized bugcheck context
1701 * ShutdownHandler: Function to call to handle the bugcheck
1702 * NOTES:
1703 * - I'm not sure about ShutdownContext
1704 */
1705 {
1706 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1707 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext;
1708
1709 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1710
1711 if (Adapter->BugcheckContext != NULL)
1712 {
1713 NDIS_DbgPrint(MIN_TRACE, ("Attempted to register again for a shutdown callback\n"));
1714 return;
1715 }
1716
1717 BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
1718 if(!BugcheckContext)
1719 {
1720 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1721 return;
1722 }
1723
1724 BugcheckContext->ShutdownHandler = ShutdownHandler;
1725 BugcheckContext->DriverContext = ShutdownContext;
1726
1727 BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
1728 if (!BugcheckContext->CallbackRecord) {
1729 ExFreePool(BugcheckContext);
1730 return;
1731 }
1732
1733 Adapter->BugcheckContext = BugcheckContext;
1734
1735 KeInitializeCallbackRecord(BugcheckContext->CallbackRecord);
1736
1737 KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
1738 BugcheckContext, sizeof(*BugcheckContext), (PUCHAR)"Ndis Miniport");
1739
1740 IoRegisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
1741 }
1742
1743 NDIS_STATUS
1744 DoQueries(
1745 PLOGICAL_ADAPTER Adapter,
1746 NDIS_OID AddressOID)
1747 /*
1748 * FUNCTION: Queries miniport for information
1749 * ARGUMENTS:
1750 * Adapter = Pointer to logical adapter
1751 * AddressOID = OID to use to query for current address
1752 * RETURNS:
1753 * Status of operation
1754 */
1755 {
1756 ULONG BytesWritten;
1757 NDIS_STATUS NdisStatus;
1758
1759 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1760
1761 /* Get MAC options for adapter */
1762 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, sizeof(UINT),
1763 &Adapter->NdisMiniportBlock.MacOptions,
1764 &BytesWritten);
1765
1766 if (NdisStatus != NDIS_STATUS_SUCCESS)
1767 {
1768 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
1769 return NdisStatus;
1770 }
1771
1772 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
1773
1774 /* Get current hardware address of adapter */
1775 NdisStatus = MiniQueryInformation(Adapter, AddressOID, Adapter->AddressLength,
1776 &Adapter->Address, &BytesWritten);
1777
1778 if (NdisStatus != NDIS_STATUS_SUCCESS)
1779 {
1780 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
1781 return NdisStatus;
1782 }
1783
1784 #if DBG
1785 {
1786 /* 802.3 only */
1787
1788 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
1789
1790 NDIS_DbgPrint(MAX_TRACE, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n", A[0], A[1], A[2], A[3], A[4], A[5]));
1791 }
1792 #endif /* DBG */
1793
1794 /* Get maximum lookahead buffer size of adapter */
1795 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, sizeof(ULONG),
1796 &Adapter->NdisMiniportBlock.MaximumLookahead, &BytesWritten);
1797
1798 if (NdisStatus != NDIS_STATUS_SUCCESS)
1799 {
1800 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1801 return NdisStatus;
1802 }
1803
1804 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.MaximumLookahead));
1805
1806 /* Get current lookahead buffer size of adapter */
1807 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, sizeof(ULONG),
1808 &Adapter->NdisMiniportBlock.CurrentLookahead, &BytesWritten);
1809
1810 if (NdisStatus != NDIS_STATUS_SUCCESS)
1811 {
1812 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1813 return NdisStatus;
1814 }
1815
1816 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_SEND_PACKETS, sizeof(ULONG),
1817 &Adapter->NdisMiniportBlock.MaxSendPackets, &BytesWritten);
1818
1819 if (NdisStatus != NDIS_STATUS_SUCCESS)
1820 {
1821 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus));
1822
1823 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1824 Adapter->NdisMiniportBlock.MaxSendPackets = 1;
1825 }
1826
1827 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
1828
1829 return STATUS_SUCCESS;
1830 }
1831
1832 NTSTATUS
1833 NTAPI
1834 NdisIForwardIrpAndWaitCompletionRoutine(
1835 PDEVICE_OBJECT Fdo,
1836 PIRP Irp,
1837 PVOID Context)
1838 {
1839 PKEVENT Event = Context;
1840
1841 if (Irp->PendingReturned)
1842 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
1843
1844 return STATUS_MORE_PROCESSING_REQUIRED;
1845 }
1846
1847 NTSTATUS
1848 NTAPI
1849 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter, PIRP Irp)
1850 {
1851 KEVENT Event;
1852 NTSTATUS Status;
1853
1854 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1855 IoCopyCurrentIrpStackLocationToNext(Irp);
1856 IoSetCompletionRoutine(Irp, NdisIForwardIrpAndWaitCompletionRoutine, &Event,
1857 TRUE, TRUE, TRUE);
1858 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1859 if (Status == STATUS_PENDING)
1860 {
1861 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1862 Status = Irp->IoStatus.Status;
1863 }
1864 return Status;
1865 }
1866
1867 NTSTATUS
1868 NTAPI
1869 NdisICreateClose(
1870 IN PDEVICE_OBJECT DeviceObject,
1871 IN PIRP Irp)
1872 {
1873 Irp->IoStatus.Status = STATUS_SUCCESS;
1874 Irp->IoStatus.Information = 0;
1875
1876 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1877
1878 return STATUS_SUCCESS;
1879 }
1880
1881 NTSTATUS
1882 NTAPI
1883 NdisIPnPStartDevice(
1884 IN PDEVICE_OBJECT DeviceObject,
1885 PIRP Irp)
1886 /*
1887 * FUNCTION: Handle the PnP start device event
1888 * ARGUMENTS:
1889 * DeviceObject = Functional Device Object
1890 * Irp = IRP_MN_START_DEVICE I/O request packet
1891 * RETURNS:
1892 * Status of operation
1893 */
1894 {
1895 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1896 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1897 NDIS_WRAPPER_CONTEXT WrapperContext;
1898 NDIS_STATUS NdisStatus;
1899 NDIS_STATUS OpenErrorStatus;
1900 NTSTATUS Status;
1901 UINT SelectedMediumIndex = 0;
1902 NDIS_OID AddressOID;
1903 BOOLEAN Success = FALSE;
1904 ULONG ResourceCount;
1905 ULONG ResourceListSize;
1906 UNICODE_STRING ParamName;
1907 PNDIS_CONFIGURATION_PARAMETER ConfigParam;
1908 NDIS_HANDLE ConfigHandle;
1909 ULONG Size;
1910 LARGE_INTEGER Timeout;
1911 UINT MaxMulticastAddresses;
1912 ULONG BytesWritten;
1913 PLIST_ENTRY CurrentEntry;
1914 PPROTOCOL_BINDING ProtocolBinding;
1915
1916 /*
1917 * Prepare wrapper context used by HW and configuration routines.
1918 */
1919
1920 NDIS_DbgPrint(DEBUG_MINIPORT, ("Start Device %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
1921
1922 NDIS_DbgPrint(MAX_TRACE, ("Inserting adapter 0x%x into adapter list\n", Adapter));
1923
1924 /* Put adapter in global adapter list */
1925 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1926
1927 Status = IoOpenDeviceRegistryKey(
1928 Adapter->NdisMiniportBlock.PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
1929 KEY_ALL_ACCESS, &WrapperContext.RegistryHandle);
1930 if (!NT_SUCCESS(Status))
1931 {
1932 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
1933 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1934 return Status;
1935 }
1936
1937 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
1938
1939 WrapperContext.DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
1940
1941 /*
1942 * Store the adapter resources used by HW routines such as
1943 * NdisMQueryAdapterResources.
1944 */
1945
1946 if (Stack->Parameters.StartDevice.AllocatedResources != NULL)
1947 {
1948 ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
1949 PartialResourceList.Count;
1950 ResourceListSize =
1951 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1952 PartialDescriptors[ResourceCount]);
1953
1954 Adapter->NdisMiniportBlock.AllocatedResources =
1955 ExAllocatePool(PagedPool, ResourceListSize);
1956 if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
1957 {
1958 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1959 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1960 return STATUS_INSUFFICIENT_RESOURCES;
1961 }
1962
1963 Adapter->NdisMiniportBlock.Resources =
1964 ExAllocatePool(PagedPool, ResourceListSize);
1965 if (!Adapter->NdisMiniportBlock.Resources)
1966 {
1967 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1968 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1969 ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
1970 return STATUS_INSUFFICIENT_RESOURCES;
1971 }
1972
1973 RtlCopyMemory(Adapter->NdisMiniportBlock.Resources,
1974 Stack->Parameters.StartDevice.AllocatedResources,
1975 ResourceListSize);
1976
1977 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
1978 Stack->Parameters.StartDevice.AllocatedResources,
1979 ResourceListSize);
1980 }
1981
1982 if (Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
1983 {
1984 ResourceCount = Stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].
1985 PartialResourceList.Count;
1986 ResourceListSize =
1987 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1988 PartialDescriptors[ResourceCount]);
1989
1990 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
1991 ExAllocatePool(PagedPool, ResourceListSize);
1992 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
1993 {
1994 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1995 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1996 return STATUS_INSUFFICIENT_RESOURCES;
1997 }
1998
1999 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
2000 Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
2001 ResourceListSize);
2002 }
2003
2004 /*
2005 * Store the Bus Type, Bus Number and Slot information. It's used by
2006 * the hardware routines then.
2007 */
2008
2009 NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
2010 if (NdisStatus != NDIS_STATUS_SUCCESS)
2011 {
2012 NDIS_DbgPrint(MIN_TRACE, ("Failed to open configuration key\n"));
2013 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2014 return NdisStatus;
2015 }
2016
2017 Size = sizeof(ULONG);
2018 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
2019 DevicePropertyLegacyBusType, Size,
2020 &Adapter->NdisMiniportBlock.BusType, &Size);
2021 if (!NT_SUCCESS(Status) || (INTERFACE_TYPE)Adapter->NdisMiniportBlock.BusType == InterfaceTypeUndefined)
2022 {
2023 NdisInitUnicodeString(&ParamName, L"BusType");
2024 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
2025 &ParamName, NdisParameterInteger);
2026 if (NdisStatus == NDIS_STATUS_SUCCESS)
2027 Adapter->NdisMiniportBlock.BusType = ConfigParam->ParameterData.IntegerData;
2028 else
2029 Adapter->NdisMiniportBlock.BusType = Isa;
2030 }
2031
2032 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
2033 DevicePropertyBusNumber, Size,
2034 &Adapter->NdisMiniportBlock.BusNumber, &Size);
2035 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusNumber == 0xFFFFFFF0)
2036 {
2037 NdisInitUnicodeString(&ParamName, L"BusNumber");
2038 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
2039 &ParamName, NdisParameterInteger);
2040 if (NdisStatus == NDIS_STATUS_SUCCESS)
2041 Adapter->NdisMiniportBlock.BusNumber = ConfigParam->ParameterData.IntegerData;
2042 else
2043 Adapter->NdisMiniportBlock.BusNumber = 0;
2044 }
2045 WrapperContext.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
2046
2047 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
2048 DevicePropertyAddress, Size,
2049 &Adapter->NdisMiniportBlock.SlotNumber, &Size);
2050 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.SlotNumber == (NDIS_INTERFACE_TYPE)-1)
2051 {
2052 NdisInitUnicodeString(&ParamName, L"SlotNumber");
2053 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
2054 &ParamName, NdisParameterInteger);
2055 if (NdisStatus == NDIS_STATUS_SUCCESS)
2056 Adapter->NdisMiniportBlock.SlotNumber = ConfigParam->ParameterData.IntegerData;
2057 else
2058 Adapter->NdisMiniportBlock.SlotNumber = 0;
2059 }
2060 else
2061 {
2062 /* Convert slotnumber to PCI_SLOT_NUMBER */
2063 ULONG PciSlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
2064 PCI_SLOT_NUMBER SlotNumber;
2065
2066 SlotNumber.u.AsULONG = 0;
2067 SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF;
2068 SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF;
2069
2070 Adapter->NdisMiniportBlock.SlotNumber = SlotNumber.u.AsULONG;
2071 }
2072 WrapperContext.SlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
2073
2074 NdisCloseConfiguration(ConfigHandle);
2075
2076 /* Set handlers (some NDIS macros require these) */
2077 Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
2078 Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
2079 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
2080 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
2081 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
2082 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
2083 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
2084 Adapter->NdisMiniportBlock.StatusHandler = MiniStatus;
2085 Adapter->NdisMiniportBlock.StatusCompleteHandler= MiniStatusComplete;
2086 Adapter->NdisMiniportBlock.SendPacketsHandler = ProSendPackets;
2087 Adapter->NdisMiniportBlock.QueryCompleteHandler = MiniRequestComplete;
2088 Adapter->NdisMiniportBlock.SetCompleteHandler = MiniRequestComplete;
2089
2090 /*
2091 * Call MiniportInitialize.
2092 */
2093
2094 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
2095 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.InitializeHandler)(
2096 &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
2097 MEDIA_ARRAY_SIZE, Adapter, (NDIS_HANDLE)&WrapperContext);
2098
2099 ZwClose(WrapperContext.RegistryHandle);
2100
2101 if (NdisStatus != NDIS_STATUS_SUCCESS)
2102 {
2103 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter (%lx).\n", NdisStatus));
2104 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2105 if (Adapter->NdisMiniportBlock.Interrupt)
2106 {
2107 KeBugCheckEx(BUGCODE_ID_DRIVER,
2108 (ULONG_PTR)Adapter,
2109 (ULONG_PTR)Adapter->NdisMiniportBlock.Interrupt,
2110 (ULONG_PTR)Adapter->NdisMiniportBlock.TimerQueue,
2111 1);
2112 }
2113 if (Adapter->NdisMiniportBlock.TimerQueue)
2114 {
2115 KeBugCheckEx(BUGCODE_ID_DRIVER,
2116 (ULONG_PTR)Adapter,
2117 (ULONG_PTR)Adapter->NdisMiniportBlock.Interrupt,
2118 (ULONG_PTR)Adapter->NdisMiniportBlock.TimerQueue,
2119 1);
2120 }
2121 return NdisStatus;
2122 }
2123
2124 if (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
2125 {
2126 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() selected a bad index\n"));
2127 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2128 return NDIS_STATUS_UNSUPPORTED_MEDIA;
2129 }
2130
2131 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
2132
2133 switch (Adapter->NdisMiniportBlock.MediaType)
2134 {
2135 case NdisMedium802_3:
2136 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
2137 AddressOID = OID_802_3_CURRENT_ADDRESS;
2138 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
2139 NdisStatus = DoQueries(Adapter, AddressOID);
2140 if (NdisStatus == NDIS_STATUS_SUCCESS)
2141 {
2142 NdisStatus = MiniQueryInformation(Adapter, OID_802_3_MAXIMUM_LIST_SIZE, sizeof(UINT),
2143 &MaxMulticastAddresses, &BytesWritten);
2144
2145 if (NdisStatus != NDIS_STATUS_SUCCESS)
2146 {
2147 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2148 NDIS_DbgPrint(MIN_TRACE, ("MiniQueryInformation failed (%x)\n", NdisStatus));
2149 return NdisStatus;
2150 }
2151
2152 Success = EthCreateFilter(MaxMulticastAddresses,
2153 Adapter->Address.Type.Medium802_3,
2154 &Adapter->NdisMiniportBlock.EthDB);
2155 if (Success)
2156 ((PETHI_FILTER)Adapter->NdisMiniportBlock.EthDB)->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
2157 else
2158 NdisStatus = NDIS_STATUS_RESOURCES;
2159 }
2160 break;
2161
2162 default:
2163 /* FIXME: Support other types of media */
2164 NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
2165 ASSERT(FALSE);
2166 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2167 return STATUS_UNSUCCESSFUL;
2168 }
2169
2170 if (NdisStatus != NDIS_STATUS_SUCCESS)
2171 {
2172 NDIS_DbgPrint(MIN_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
2173 return NdisStatus;
2174 }
2175
2176 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
2177 if (Adapter->NdisMiniportBlock.CheckForHangSeconds == 0)
2178 Adapter->NdisMiniportBlock.CheckForHangSeconds = 2;
2179
2180 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
2181 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
2182
2183 IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, TRUE);
2184
2185 Timeout.QuadPart = Int32x32To64(Adapter->NdisMiniportBlock.CheckForHangSeconds, -1000000);
2186 KeSetTimerEx(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer, Timeout,
2187 Adapter->NdisMiniportBlock.CheckForHangSeconds * 1000,
2188 &Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc);
2189
2190 /* Put adapter in adapter list for this miniport */
2191 ExInterlockedInsertTailList(&Adapter->NdisMiniportBlock.DriverHandle->DeviceList, &Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
2192
2193 /* Refresh bindings for all protocols */
2194 CurrentEntry = ProtocolListHead.Flink;
2195 while (CurrentEntry != &ProtocolListHead)
2196 {
2197 ProtocolBinding = CONTAINING_RECORD(CurrentEntry, PROTOCOL_BINDING, ListEntry);
2198
2199 ndisBindMiniportsToProtocol(&NdisStatus, ProtocolBinding);
2200
2201 CurrentEntry = CurrentEntry->Flink;
2202 }
2203
2204 return STATUS_SUCCESS;
2205 }
2206
2207 NTSTATUS
2208 NTAPI
2209 NdisIPnPStopDevice(
2210 IN PDEVICE_OBJECT DeviceObject,
2211 PIRP Irp)
2212 /*
2213 * FUNCTION: Handle the PnP stop device event
2214 * ARGUMENTS:
2215 * DeviceObject = Functional Device Object
2216 * Irp = IRP_MN_STOP_DEVICE I/O request packet
2217 * RETURNS:
2218 * Status of operation
2219 */
2220 {
2221 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2222
2223 /* Remove adapter from adapter list for this miniport */
2224 ExInterlockedRemoveEntryList(&Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
2225
2226 /* Remove adapter from global adapter list */
2227 ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
2228
2229 KeCancelTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
2230
2231 /* Set this here so MiniportISR will be forced to run for interrupts generated in MiniportHalt */
2232 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
2233 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
2234
2235 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HaltHandler)(Adapter);
2236
2237 IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, FALSE);
2238
2239 if (Adapter->NdisMiniportBlock.AllocatedResources)
2240 {
2241 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
2242 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
2243 }
2244 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated)
2245 {
2246 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated);
2247 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
2248 }
2249
2250 if (Adapter->NdisMiniportBlock.Resources)
2251 {
2252 ExFreePool(Adapter->NdisMiniportBlock.Resources);
2253 Adapter->NdisMiniportBlock.Resources = NULL;
2254 }
2255
2256 if (Adapter->NdisMiniportBlock.EthDB)
2257 {
2258 EthDeleteFilter(Adapter->NdisMiniportBlock.EthDB);
2259 Adapter->NdisMiniportBlock.EthDB = NULL;
2260 }
2261
2262 return STATUS_SUCCESS;
2263 }
2264
2265 NTSTATUS
2266 NTAPI
2267 NdisIShutdown(
2268 IN PDEVICE_OBJECT DeviceObject,
2269 PIRP Irp)
2270 {
2271 PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
2272 PMINIPORT_BUGCHECK_CONTEXT Context = Adapter->BugcheckContext;
2273 ADAPTER_SHUTDOWN_HANDLER ShutdownHandler = Context->ShutdownHandler;
2274
2275 ASSERT(ShutdownHandler);
2276
2277 ShutdownHandler(Context->DriverContext);
2278
2279 Irp->IoStatus.Status = STATUS_SUCCESS;
2280 Irp->IoStatus.Information = 0;
2281
2282 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2283
2284 return STATUS_SUCCESS;
2285 }
2286
2287 NTSTATUS
2288 NTAPI
2289 NdisIDeviceIoControl(
2290 IN PDEVICE_OBJECT DeviceObject,
2291 PIRP Irp)
2292 {
2293 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2294 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
2295 NDIS_STATUS Status = STATUS_NOT_SUPPORTED;
2296 ULONG ControlCode;
2297 ULONG Written;
2298
2299 Irp->IoStatus.Information = 0;
2300
2301 ASSERT(Adapter);
2302
2303 ControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
2304 switch (ControlCode)
2305 {
2306 case IOCTL_NDIS_QUERY_GLOBAL_STATS:
2307 Status = MiniQueryInformation(Adapter,
2308 *(PNDIS_OID)Irp->AssociatedIrp.SystemBuffer,
2309 Stack->Parameters.DeviceIoControl.OutputBufferLength,
2310 MmGetSystemAddressForMdl(Irp->MdlAddress),
2311 &Written);
2312 Irp->IoStatus.Information = Written;
2313 break;
2314
2315 default:
2316 NDIS_DbgPrint(MIN_TRACE, ("NdisIDeviceIoControl: unsupported control code 0x%lx\n", ControlCode));
2317 break;
2318 }
2319
2320 if (Status != NDIS_STATUS_PENDING)
2321 {
2322 Irp->IoStatus.Status = Status;
2323 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2324 }
2325 else
2326 IoMarkIrpPending(Irp);
2327
2328 return Status;
2329 }
2330
2331 NTSTATUS
2332 NTAPI
2333 NdisIDispatchPnp(
2334 IN PDEVICE_OBJECT DeviceObject,
2335 PIRP Irp)
2336 {
2337 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
2338 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2339 NTSTATUS Status;
2340
2341 switch (Stack->MinorFunction)
2342 {
2343 case IRP_MN_START_DEVICE:
2344 Status = NdisIForwardIrpAndWait(Adapter, Irp);
2345 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
2346 {
2347 Status = NdisIPnPStartDevice(DeviceObject, Irp);
2348 }
2349 else
2350 NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed device start\n"));
2351 Irp->IoStatus.Status = Status;
2352 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2353 return Status;
2354
2355 case IRP_MN_STOP_DEVICE:
2356 Status = NdisIPnPStopDevice(DeviceObject, Irp);
2357 if (!NT_SUCCESS(Status))
2358 NDIS_DbgPrint(MIN_TRACE, ("WARNING: Ignoring halt device failure! Passing the IRP down anyway\n"));
2359 Irp->IoStatus.Status = STATUS_SUCCESS;
2360 break;
2361
2362 case IRP_MN_QUERY_REMOVE_DEVICE:
2363 case IRP_MN_QUERY_STOP_DEVICE:
2364 Status = NdisIPnPQueryStopDevice(DeviceObject, Irp);
2365 Irp->IoStatus.Status = Status;
2366 if (Status != STATUS_SUCCESS)
2367 {
2368 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2369 NDIS_DbgPrint(MIN_TRACE, ("Failing miniport halt request\n"));
2370 return Status;
2371 }
2372 break;
2373
2374 case IRP_MN_CANCEL_REMOVE_DEVICE:
2375 case IRP_MN_CANCEL_STOP_DEVICE:
2376 Status = NdisIForwardIrpAndWait(Adapter, Irp);
2377 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
2378 {
2379 Status = NdisIPnPCancelStopDevice(DeviceObject, Irp);
2380 }
2381 else
2382 {
2383 NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed cancel stop/remove request\n"));
2384 }
2385 Irp->IoStatus.Status = Status;
2386 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2387 return Status;
2388
2389 case IRP_MN_QUERY_PNP_DEVICE_STATE:
2390 Status = NDIS_STATUS_SUCCESS;
2391 Irp->IoStatus.Status = Status;
2392 Irp->IoStatus.Information |= Adapter->NdisMiniportBlock.PnPFlags;
2393 break;
2394
2395 default:
2396 break;
2397 }
2398
2399 IoSkipCurrentIrpStackLocation(Irp);
2400 return IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
2401 }
2402
2403 NTSTATUS
2404 NTAPI
2405 NdisIPower(
2406 _In_ PDEVICE_OBJECT DeviceObject,
2407 _In_ PIRP Irp)
2408 {
2409 PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
2410
2411 PoStartNextPowerIrp(Irp);
2412 IoSkipCurrentIrpStackLocation(Irp);
2413 return PoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
2414 }
2415
2416 NTSTATUS
2417 NTAPI
2418 NdisIAddDevice(
2419 IN PDRIVER_OBJECT DriverObject,
2420 IN PDEVICE_OBJECT PhysicalDeviceObject)
2421 /*
2422 * FUNCTION: Create a device for an adapter found using PnP
2423 * ARGUMENTS:
2424 * DriverObject = Pointer to the miniport driver object
2425 * PhysicalDeviceObject = Pointer to the PDO for our adapter
2426 */
2427 {
2428 static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
2429 static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
2430 PNDIS_M_DRIVER_BLOCK Miniport;
2431 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
2432 WCHAR *LinkageKeyBuffer;
2433 ULONG DriverKeyLength;
2434 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
2435 UNICODE_STRING ExportName;
2436 PDEVICE_OBJECT DeviceObject;
2437 PLOGICAL_ADAPTER Adapter;
2438 NTSTATUS Status;
2439
2440 /*
2441 * Gain the access to the miniport data structure first.
2442 */
2443
2444 MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)'NMID');
2445 if (MiniportPtr == NULL)
2446 {
2447 NDIS_DbgPrint(MIN_TRACE, ("Can't get driver object extension.\n"));
2448 return NDIS_STATUS_FAILURE;
2449 }
2450 Miniport = *MiniportPtr;
2451
2452 /*
2453 * Get name of the Linkage registry key for our adapter. It's located under
2454 * the driver key for our driver and so we have basicly two ways to do it.
2455 * Either we can use IoOpenDriverRegistryKey or compose it using information
2456 * gathered by IoGetDeviceProperty. I chose the second because
2457 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
2458 */
2459
2460 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
2461 0, NULL, &DriverKeyLength);
2462 if (Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_SUCCESS)
2463 {
2464 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key length.\n"));
2465 return Status;
2466 }
2467
2468 LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
2469 sizeof(ClassKeyName) + sizeof(LinkageKeyName));
2470 if (LinkageKeyBuffer == NULL)
2471 {
2472 NDIS_DbgPrint(MIN_TRACE, ("Can't allocate memory for driver key name.\n"));
2473 return STATUS_INSUFFICIENT_RESOURCES;
2474 }
2475
2476 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
2477 DriverKeyLength, LinkageKeyBuffer +
2478 (sizeof(ClassKeyName) / sizeof(WCHAR)),
2479 &DriverKeyLength);
2480 if (!NT_SUCCESS(Status))
2481 {
2482 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key.\n"));
2483 ExFreePool(LinkageKeyBuffer);
2484 return Status;
2485 }
2486
2487 /* Compose the linkage key name. */
2488 RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
2489 RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
2490 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
2491
2492 NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
2493
2494 /*
2495 * Now open the linkage key and read the "Export" and "RootDevice" values
2496 * which contains device name and root service respectively.
2497 */
2498
2499 RtlZeroMemory(QueryTable, sizeof(QueryTable));
2500 RtlInitUnicodeString(&ExportName, NULL);
2501 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
2502 QueryTable[0].Name = L"Export";
2503 QueryTable[0].EntryContext = &ExportName;
2504
2505 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
2506 QueryTable, NULL, NULL);
2507 ExFreePool(LinkageKeyBuffer);
2508 if (!NT_SUCCESS(Status))
2509 {
2510 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport device name. (%x)\n", Status));
2511 return Status;
2512 }
2513
2514 /*
2515 * Create the device object.
2516 */
2517
2518 NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", &ExportName));
2519
2520 Status = IoCreateDevice(Miniport->DriverObject, sizeof(LOGICAL_ADAPTER),
2521 &ExportName, FILE_DEVICE_PHYSICAL_NETCARD,
2522 0, FALSE, &DeviceObject);
2523 if (!NT_SUCCESS(Status))
2524 {
2525 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
2526 RtlFreeUnicodeString(&ExportName);
2527 return Status;
2528 }
2529
2530 /*
2531 * Initialize the adapter structure.
2532 */
2533
2534 Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2535 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
2536 InitializeListHead(&Adapter->ProtocolListHead);
2537
2538 Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
2539 &GUID_DEVINTERFACE_NET,
2540 NULL,
2541 &Adapter->NdisMiniportBlock.SymbolicLinkName);
2542
2543 if (!NT_SUCCESS(Status))
2544 {
2545 NDIS_DbgPrint(MIN_TRACE, ("Could not create device interface.\n"));
2546 IoDeleteDevice(DeviceObject);
2547 RtlFreeUnicodeString(&ExportName);
2548 return Status;
2549 }
2550
2551 Adapter->NdisMiniportBlock.DriverHandle = Miniport;
2552 Adapter->NdisMiniportBlock.MiniportName = ExportName;
2553 Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
2554 Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
2555 Adapter->NdisMiniportBlock.NextDeviceObject =
2556 IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
2557 PhysicalDeviceObject);
2558
2559 Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
2560 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
2561
2562 KeInitializeTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
2563 KeInitializeDpc(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc, MiniportHangDpc, Adapter);
2564
2565 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
2566
2567 return STATUS_SUCCESS;
2568 }
2569
2570 NTSTATUS
2571 NTAPI
2572 NdisGenericIrpHandler(
2573 IN PDEVICE_OBJECT DeviceObject,
2574 IN PIRP Irp)
2575 {
2576 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
2577
2578 /* Use the characteristics to classify the device */
2579 if (DeviceObject->DeviceType == FILE_DEVICE_PHYSICAL_NETCARD)
2580 {
2581 if ((IrpSp->MajorFunction == IRP_MJ_CREATE) ||
2582 (IrpSp->MajorFunction == IRP_MJ_CLOSE) ||
2583 (IrpSp->MajorFunction == IRP_MJ_CLEANUP))
2584 {
2585 return NdisICreateClose(DeviceObject, Irp);
2586 }
2587 else if (IrpSp->MajorFunction == IRP_MJ_PNP)
2588 {
2589 return NdisIDispatchPnp(DeviceObject, Irp);
2590 }
2591 else if (IrpSp->MajorFunction == IRP_MJ_SHUTDOWN)
2592 {
2593 return NdisIShutdown(DeviceObject, Irp);
2594 }
2595 else if (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
2596 {
2597 return NdisIDeviceIoControl(DeviceObject, Irp);
2598 }
2599 else if (IrpSp->MajorFunction == IRP_MJ_POWER)
2600 {
2601 return NdisIPower(DeviceObject, Irp);
2602 }
2603 NDIS_DbgPrint(MIN_TRACE, ("Unexpected IRP MajorFunction 0x%x\n", IrpSp->MajorFunction));
2604 ASSERT(FALSE);
2605 }
2606 else if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK)
2607 {
2608 PNDIS_M_DEVICE_BLOCK DeviceBlock = DeviceObject->DeviceExtension;
2609
2610 ASSERT(DeviceBlock->DeviceObject == DeviceObject);
2611
2612 if (DeviceBlock->MajorFunction[IrpSp->MajorFunction] != NULL)
2613 {
2614 return DeviceBlock->MajorFunction[IrpSp->MajorFunction](DeviceObject, Irp);
2615 }
2616 }
2617 else
2618 {
2619 ASSERT(FALSE);
2620 }
2621
2622 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
2623 Irp->IoStatus.Information = 0;
2624
2625 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2626
2627 return STATUS_INVALID_DEVICE_REQUEST;
2628 }
2629
2630 /*
2631 * @implemented
2632 */
2633 NDIS_STATUS
2634 EXPORT
2635 NdisMRegisterMiniport(
2636 IN NDIS_HANDLE NdisWrapperHandle,
2637 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
2638 IN UINT CharacteristicsLength)
2639 /*
2640 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2641 * ARGUMENTS:
2642 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2643 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2644 * CharacteristicsLength = Number of bytes in characteristics buffer
2645 * RETURNS:
2646 * Status of operation
2647 */
2648 {
2649 UINT MinSize;
2650 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2651 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
2652 NTSTATUS Status;
2653 ULONG i;
2654
2655 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2656
2657 switch (MiniportCharacteristics->MajorNdisVersion)
2658 {
2659 case 0x03:
2660 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
2661 break;
2662
2663 case 0x04:
2664 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
2665 break;
2666
2667 case 0x05:
2668 switch (MiniportCharacteristics->MinorNdisVersion)
2669 {
2670 case 0x00:
2671 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
2672 break;
2673
2674 case 0x01:
2675 MinSize = sizeof(NDIS51_MINIPORT_CHARACTERISTICS);
2676 break;
2677
2678 default:
2679 NDIS_DbgPrint(MIN_TRACE, ("Bad 5.x minor characteristics version.\n"));
2680 return NDIS_STATUS_BAD_VERSION;
2681 }
2682 break;
2683
2684 default:
2685 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics version.\n"));
2686 return NDIS_STATUS_BAD_VERSION;
2687 }
2688
2689 NDIS_DbgPrint(MID_TRACE, ("Initializing an NDIS %u.%u miniport\n",
2690 MiniportCharacteristics->MajorNdisVersion,
2691 MiniportCharacteristics->MinorNdisVersion));
2692
2693 if (CharacteristicsLength < MinSize)
2694 {
2695 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics length.\n"));
2696 return NDIS_STATUS_BAD_CHARACTERISTICS;
2697 }
2698
2699 /* Check if mandatory MiniportXxx functions are specified */
2700 if ((!MiniportCharacteristics->HaltHandler) ||
2701 (!MiniportCharacteristics->InitializeHandler)||
2702 (!MiniportCharacteristics->ResetHandler))
2703 {
2704 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics.\n"));
2705 return NDIS_STATUS_BAD_CHARACTERISTICS;
2706 }
2707
2708 if (MiniportCharacteristics->MajorNdisVersion < 0x05)
2709 {
2710 if ((!MiniportCharacteristics->QueryInformationHandler) ||
2711 (!MiniportCharacteristics->SetInformationHandler))
2712 {
2713 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
2714 return NDIS_STATUS_BAD_CHARACTERISTICS;
2715 }
2716 }
2717 else
2718 {
2719 if (((!MiniportCharacteristics->QueryInformationHandler) ||
2720 (!MiniportCharacteristics->SetInformationHandler)) &&
2721 (!MiniportCharacteristics->CoRequestHandler))
2722 {
2723 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
2724 return NDIS_STATUS_BAD_CHARACTERISTICS;
2725 }
2726 }
2727
2728 if (MiniportCharacteristics->MajorNdisVersion == 0x03)
2729 {
2730 if (!MiniportCharacteristics->SendHandler)
2731 {
2732 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 3.0)\n"));
2733 return NDIS_STATUS_BAD_CHARACTERISTICS;
2734 }
2735 }
2736 else if (MiniportCharacteristics->MajorNdisVersion == 0x04)
2737 {
2738 /* NDIS 4.0 */
2739 if ((!MiniportCharacteristics->SendHandler) &&
2740 (!MiniportCharacteristics->SendPacketsHandler))
2741 {
2742 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 4.0)\n"));
2743 return NDIS_STATUS_BAD_CHARACTERISTICS;
2744 }
2745 }
2746 else if (MiniportCharacteristics->MajorNdisVersion == 0x05)
2747 {
2748 /* TODO: Add more checks here */
2749
2750 if ((!MiniportCharacteristics->SendHandler) &&
2751 (!MiniportCharacteristics->SendPacketsHandler) &&
2752 (!MiniportCharacteristics->CoSendPacketsHandler))
2753 {
2754 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 5.0)\n"));
2755 return NDIS_STATUS_BAD_CHARACTERISTICS;
2756 }
2757 }
2758
2759 RtlCopyMemory(&Miniport->MiniportCharacteristics, MiniportCharacteristics, MinSize);
2760
2761 /*
2762 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2763 * structure in the driver extension or what?
2764 */
2765
2766 Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)'NMID',
2767 sizeof(PNDIS_M_DRIVER_BLOCK), (PVOID*)&MiniportPtr);
2768 if (!NT_SUCCESS(Status))
2769 {
2770 NDIS_DbgPrint(MIN_TRACE, ("Can't allocate driver object extension.\n"));
2771 return NDIS_STATUS_RESOURCES;
2772 }
2773
2774 *MiniportPtr = Miniport;
2775
2776 /* We have to register for all of these so handler registered in NdisMRegisterDevice work */
2777 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
2778 {
2779 Miniport->DriverObject->MajorFunction[i] = NdisGenericIrpHandler;
2780 }
2781
2782 Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
2783
2784 return NDIS_STATUS_SUCCESS;
2785 }
2786
2787 /*
2788 * @implemented
2789 */
2790 #undef NdisMResetComplete
2791 VOID
2792 EXPORT
2793 NdisMResetComplete(
2794 IN NDIS_HANDLE MiniportAdapterHandle,
2795 IN NDIS_STATUS Status,
2796 IN BOOLEAN AddressingReset)
2797 {
2798 MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
2799 }
2800
2801 /*
2802 * @implemented
2803 */
2804 #undef NdisMSendComplete
2805 VOID
2806 EXPORT
2807 NdisMSendComplete(
2808 IN NDIS_HANDLE MiniportAdapterHandle,
2809 IN PNDIS_PACKET Packet,
2810 IN NDIS_STATUS Status)
2811 /*
2812 * FUNCTION: Forwards a message to the initiating protocol saying
2813 * that a packet was handled
2814 * ARGUMENTS:
2815 * NdisAdapterHandle = Handle input to MiniportInitialize
2816 * Packet = Pointer to NDIS packet that was sent
2817 * Status = Status of send operation
2818 */
2819 {
2820 MiniSendComplete(MiniportAdapterHandle, Packet, Status);
2821 }
2822
2823 /*
2824 * @implemented
2825 */
2826 #undef NdisMSendResourcesAvailable
2827 VOID
2828 EXPORT
2829 NdisMSendResourcesAvailable(
2830 IN NDIS_HANDLE MiniportAdapterHandle)
2831 {
2832 MiniSendResourcesAvailable(MiniportAdapterHandle);
2833 }
2834
2835 /*
2836 * @implemented
2837 */
2838 #undef NdisMTransferDataComplete
2839 VOID
2840 EXPORT
2841 NdisMTransferDataComplete(
2842 IN NDIS_HANDLE MiniportAdapterHandle,
2843 IN PNDIS_PACKET Packet,
2844 IN NDIS_STATUS Status,
2845 IN UINT BytesTransferred)
2846 {
2847 MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
2848 }
2849
2850 /*
2851 * @implemented
2852 */
2853 #undef NdisMSetAttributes
2854 VOID
2855 EXPORT
2856 NdisMSetAttributes(
2857 IN NDIS_HANDLE MiniportAdapterHandle,
2858 IN NDIS_HANDLE MiniportAdapterContext,
2859 IN BOOLEAN BusMaster,
2860 IN NDIS_INTERFACE_TYPE AdapterType)
2861 /*
2862 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2863 * ARGUMENTS:
2864 * MiniportAdapterHandle = Handle input to MiniportInitialize
2865 * MiniportAdapterContext = Pointer to context information
2866 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2867 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2868 */
2869 {
2870 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2871 NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0,
2872 BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
2873 AdapterType);
2874 }
2875
2876 /*
2877 * @implemented
2878 */
2879 VOID
2880 EXPORT
2881 NdisMSetAttributesEx(
2882 IN NDIS_HANDLE MiniportAdapterHandle,
2883 IN NDIS_HANDLE MiniportAdapterContext,
2884 IN UINT CheckForHangTimeInSeconds OPTIONAL,
2885 IN ULONG AttributeFlags,
2886 IN NDIS_INTERFACE_TYPE AdapterType)
2887 /*
2888 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2889 * ARGUMENTS:
2890 * MiniportAdapterHandle = Handle input to MiniportInitialize
2891 * MiniportAdapterContext = Pointer to context information
2892 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2893 * MiniportCheckForHang should be called
2894 * AttributeFlags = Bitmask that indicates specific attributes
2895 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2896 */
2897 {
2898 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
2899
2900 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2901
2902 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
2903 Adapter->NdisMiniportBlock.Flags = AttributeFlags;
2904 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
2905 if (CheckForHangTimeInSeconds > 0)
2906 Adapter->NdisMiniportBlock.CheckForHangSeconds = CheckForHangTimeInSeconds;
2907 if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
2908 NDIS_DbgPrint(MIN_TRACE, ("Intermediate drivers not supported yet.\n"));
2909
2910 NDIS_DbgPrint(MID_TRACE, ("Miniport attribute flags: 0x%x\n", AttributeFlags));
2911
2912 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler)
2913 {
2914 NDIS_DbgPrint(MAX_TRACE, ("Miniport set AdapterShutdownHandler in MiniportCharacteristics\n"));
2915 NdisMRegisterAdapterShutdownHandler(Adapter,
2916 Adapter->NdisMiniportBlock.MiniportAdapterContext,
2917 Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler);
2918 }
2919 }
2920
2921 /*
2922 * @implemented
2923 */
2924 VOID
2925 EXPORT
2926 NdisMSleep(
2927 IN ULONG MicrosecondsToSleep)
2928 /*
2929 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2930 * ARGUMENTS:
2931 * MicrosecondsToSleep: duh...
2932 * NOTES:
2933 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2934 */
2935 {
2936 KTIMER Timer;
2937 LARGE_INTEGER DueTime;
2938
2939 PAGED_CODE();
2940
2941 DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
2942
2943 KeInitializeTimer(&Timer);
2944 KeSetTimer(&Timer, DueTime, 0);
2945 KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
2946 }
2947
2948 /*
2949 * @implemented
2950 */
2951 BOOLEAN
2952 EXPORT
2953 NdisMSynchronizeWithInterrupt(
2954 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
2955 IN PVOID SynchronizeFunction,
2956 IN PVOID SynchronizeContext)
2957 {
2958 return(KeSynchronizeExecution(Interrupt->InterruptObject,
2959 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
2960 SynchronizeContext));
2961 }
2962
2963 /*
2964 * @unimplemented
2965 */
2966 NDIS_STATUS
2967 EXPORT
2968 NdisMWriteLogData(
2969 IN NDIS_HANDLE LogHandle,
2970 IN PVOID LogBuffer,
2971 IN UINT LogBufferSize)
2972 {
2973 PUCHAR Buffer = LogBuffer;
2974 UINT i, j, idx;
2975
2976 UNIMPLEMENTED;
2977 for (i = 0; i < LogBufferSize; i += 16)
2978 {
2979 DbgPrint("%08x |", i);
2980 for (j = 0; j < 16; j++)
2981 {
2982 idx = i + j;
2983 if (idx < LogBufferSize)
2984 DbgPrint(" %02x", Buffer[idx]);
2985 else
2986 DbgPrint(" ");
2987 }
2988 DbgPrint(" | ");
2989 for (j = 0; j < 16; j++)
2990 {
2991 idx = i + j;
2992 if (idx == LogBufferSize)
2993 break;
2994 if (Buffer[idx] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2995 DbgPrint("%c", Buffer[idx]);
2996 else
2997 DbgPrint(".");
2998 }
2999 DbgPrint("\n");
3000 }
3001
3002 return NDIS_STATUS_FAILURE;
3003 }
3004
3005 /*
3006 * @implemented
3007 */
3008 VOID
3009 EXPORT
3010 NdisTerminateWrapper(
3011 IN NDIS_HANDLE NdisWrapperHandle,
3012 IN PVOID SystemSpecific)
3013 /*
3014 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
3015 * ARGUMENTS:
3016 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
3017 * SystemSpecific = Always NULL
3018 */
3019 {
3020 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
3021
3022 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
3023
3024 ExFreePool(Miniport->RegistryPath->Buffer);
3025 ExFreePool(Miniport->RegistryPath);
3026 ExInterlockedRemoveEntryList(&Miniport->ListEntry, &MiniportListLock);
3027 ExFreePool(Miniport);
3028 }
3029
3030
3031 /*
3032 * @implemented
3033 */
3034 NDIS_STATUS
3035 EXPORT
3036 NdisMQueryAdapterInstanceName(
3037 OUT PNDIS_STRING AdapterInstanceName,
3038 IN NDIS_HANDLE MiniportAdapterHandle)
3039 /*
3040 * FUNCTION:
3041 * ARGUMENTS:
3042 * NOTES:
3043 * NDIS 5.0
3044 */
3045 {
3046 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
3047 UNICODE_STRING AdapterName;
3048
3049 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
3050
3051 AdapterName.Length = 0;
3052 AdapterName.MaximumLength = Adapter->NdisMiniportBlock.MiniportName.MaximumLength;
3053 AdapterName.Buffer = ExAllocatePool(PagedPool, AdapterName.MaximumLength);
3054 if (!AdapterName.Buffer) {
3055 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
3056 return NDIS_STATUS_RESOURCES;
3057 }
3058
3059 RtlCopyUnicodeString(&AdapterName, &Adapter->NdisMiniportBlock.MiniportName);
3060
3061 *AdapterInstanceName = AdapterName;
3062
3063 return NDIS_STATUS_SUCCESS;
3064 }
3065
3066 /*
3067 * @implemented
3068 */
3069 VOID
3070 EXPORT
3071 NdisDeregisterAdapterShutdownHandler(
3072 IN NDIS_HANDLE NdisAdapterHandle)
3073 /*
3074 * FUNCTION:
3075 * ARGUMENTS:
3076 * NOTES:
3077 * NDIS 4.0
3078 */
3079 {
3080 NdisMDeregisterAdapterShutdownHandler(NdisAdapterHandle);
3081 }
3082
3083
3084 /*
3085 * @implemented
3086 */
3087 VOID
3088 EXPORT
3089 NdisRegisterAdapterShutdownHandler(
3090 IN NDIS_HANDLE NdisAdapterHandle,
3091 IN PVOID ShutdownContext,
3092 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
3093 /*
3094 * FUNCTION:
3095 * ARGUMENTS:
3096 * NOTES:
3097 * NDIS 4.0
3098 */
3099 {
3100 NdisMRegisterAdapterShutdownHandler(NdisAdapterHandle,
3101 ShutdownContext,
3102 ShutdownHandler);
3103 }
3104
3105 /*
3106 * @implemented
3107 */
3108 VOID
3109 EXPORT
3110 NdisMGetDeviceProperty(
3111 IN NDIS_HANDLE MiniportAdapterHandle,
3112 IN OUT PDEVICE_OBJECT *PhysicalDeviceObject OPTIONAL,
3113 IN OUT PDEVICE_OBJECT *FunctionalDeviceObject OPTIONAL,
3114 IN OUT PDEVICE_OBJECT *NextDeviceObject OPTIONAL,
3115 IN OUT PCM_RESOURCE_LIST *AllocatedResources OPTIONAL,
3116 IN OUT PCM_RESOURCE_LIST *AllocatedResourcesTranslated OPTIONAL)
3117 /*
3118 * FUNCTION:
3119 * ARGUMENTS:
3120 * NOTES:
3121 * NDIS 5.0
3122 */
3123 {
3124 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
3125
3126 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
3127
3128 if (PhysicalDeviceObject != NULL)
3129 *PhysicalDeviceObject = Adapter->NdisMiniportBlock.PhysicalDeviceObject;
3130
3131 if (FunctionalDeviceObject != NULL)
3132 *FunctionalDeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
3133
3134 if (NextDeviceObject != NULL)
3135 *NextDeviceObject = Adapter->NdisMiniportBlock.NextDeviceObject;
3136
3137 if (AllocatedResources != NULL)
3138 *AllocatedResources = Adapter->NdisMiniportBlock.AllocatedResources;
3139
3140 if (AllocatedResourcesTranslated != NULL)
3141 *AllocatedResourcesTranslated = Adapter->NdisMiniportBlock.AllocatedResourcesTranslated;
3142 }
3143
3144 /*
3145 * @implemented
3146 */
3147 VOID
3148 EXPORT
3149 NdisMRegisterUnloadHandler(
3150 IN NDIS_HANDLE NdisWrapperHandle,
3151 IN PDRIVER_UNLOAD UnloadHandler)
3152 /*
3153 * FUNCTION:
3154 * ARGUMENTS:
3155 * NOTES:
3156 * NDIS 5.0
3157 */
3158 {
3159 PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
3160
3161 NDIS_DbgPrint(MAX_TRACE, ("Miniport registered unload handler\n"));
3162
3163 DriverBlock->DriverObject->DriverUnload = UnloadHandler;
3164 }
3165
3166 /*
3167 * @implemented
3168 */
3169 NDIS_STATUS
3170 EXPORT
3171 NdisMRegisterDevice(
3172 IN NDIS_HANDLE NdisWrapperHandle,
3173 IN PNDIS_STRING DeviceName,
3174 IN PNDIS_STRING SymbolicName,
3175 IN PDRIVER_DISPATCH MajorFunctions[],
3176 OUT PDEVICE_OBJECT *pDeviceObject,
3177 OUT NDIS_HANDLE *NdisDeviceHandle)
3178 /*
3179 * FUNCTION:
3180 * ARGUMENTS:
3181 * NOTES:
3182 * NDIS 5.0
3183 */
3184 {
3185 PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
3186 PNDIS_M_DEVICE_BLOCK DeviceBlock;
3187 PDEVICE_OBJECT DeviceObject;
3188 NDIS_STATUS Status;
3189 UINT i;
3190
3191 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
3192
3193 Status = IoCreateDevice(DriverBlock->DriverObject,
3194 sizeof(NDIS_M_DEVICE_BLOCK),
3195 DeviceName,
3196 FILE_DEVICE_NETWORK,
3197 0,
3198 FALSE,
3199 &DeviceObject);
3200
3201 if (!NT_SUCCESS(Status))
3202 {
3203 NDIS_DbgPrint(MIN_TRACE, ("IoCreateDevice failed (%x)\n", Status));
3204 return Status;
3205 }
3206
3207 Status = IoCreateSymbolicLink(SymbolicName, DeviceName);
3208
3209 if (!NT_SUCCESS(Status))
3210 {
3211 NDIS_DbgPrint(MIN_TRACE, ("IoCreateSymbolicLink failed (%x)\n", Status));
3212 IoDeleteDevice(DeviceObject);
3213 return Status;
3214 }
3215
3216 DeviceBlock = DeviceObject->DeviceExtension;
3217
3218 if (!DeviceBlock)
3219 {
3220 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
3221 IoDeleteDevice(DeviceObject);
3222 IoDeleteSymbolicLink(SymbolicName);
3223 return NDIS_STATUS_RESOURCES;
3224 }
3225
3226 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
3227 DeviceBlock->MajorFunction[i] = MajorFunctions[i];
3228
3229 DeviceBlock->DeviceObject = DeviceObject;
3230 DeviceBlock->SymbolicName = SymbolicName;
3231
3232 *pDeviceObject = DeviceObject;
3233 *NdisDeviceHandle = DeviceBlock;
3234
3235 return NDIS_STATUS_SUCCESS;
3236 }
3237
3238 /*
3239 * @implemented
3240 */
3241 NDIS_STATUS
3242 EXPORT
3243 NdisMDeregisterDevice(
3244 IN NDIS_HANDLE NdisDeviceHandle)
3245 /*
3246 * FUNCTION:
3247 * ARGUMENTS:
3248 * NOTES:
3249 * NDIS 5.0
3250 */
3251 {
3252 PNDIS_M_DEVICE_BLOCK DeviceBlock = NdisDeviceHandle;
3253
3254 IoDeleteDevice(DeviceBlock->DeviceObject);
3255
3256 IoDeleteSymbolicLink(DeviceBlock->SymbolicName);
3257
3258 return NDIS_STATUS_SUCCESS;
3259 }
3260
3261 /*
3262 * @implemented
3263 */
3264 NDIS_STATUS
3265 EXPORT
3266 NdisQueryAdapterInstanceName(
3267 OUT PNDIS_STRING AdapterInstanceName,
3268 IN NDIS_HANDLE NdisBindingHandle)
3269 /*
3270 * FUNCTION:
3271 * ARGUMENTS:
3272 * NOTES:
3273 * NDIS 5.0
3274 */
3275 {
3276 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3277 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3278
3279 return NdisMQueryAdapterInstanceName(AdapterInstanceName,
3280 Adapter);
3281 }
3282
3283 /*
3284 * @implemented
3285 */
3286 VOID
3287 EXPORT
3288 NdisCompletePnPEvent(
3289 IN NDIS_STATUS Status,
3290 IN NDIS_HANDLE NdisBindingHandle,
3291 IN PNET_PNP_EVENT NetPnPEvent)
3292 /*
3293 * FUNCTION:
3294 * ARGUMENTS:
3295 * NOTES:
3296 * NDIS 5.0
3297 */
3298 {
3299 PIRP Irp = (PIRP)NetPnPEvent->NdisReserved[0];
3300 PLIST_ENTRY CurrentEntry = (PLIST_ENTRY)NetPnPEvent->NdisReserved[1];
3301 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3302 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3303 NDIS_STATUS NdisStatus;
3304
3305 if (Status != NDIS_STATUS_SUCCESS)
3306 {
3307 if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);