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