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