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