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