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