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