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