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