- Initially set PoolHandle, ConfigurationHandle, KeyHandle, and Filter to NULL
[reactos.git] / 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 \f
138 VOID
139 MiniIndicateData(
140 PLOGICAL_ADAPTER Adapter,
141 NDIS_HANDLE MacReceiveContext,
142 PVOID HeaderBuffer,
143 UINT HeaderBufferSize,
144 PVOID LookaheadBuffer,
145 UINT LookaheadBufferSize,
146 UINT PacketSize)
147 /*
148 * FUNCTION: Indicate received data to bound protocols
149 * ARGUMENTS:
150 * Adapter = Pointer to logical adapter
151 * MacReceiveContext = MAC receive context handle
152 * HeaderBuffer = Pointer to header buffer
153 * HeaderBufferSize = Size of header buffer
154 * LookaheadBuffer = Pointer to lookahead buffer
155 * LookaheadBufferSize = Size of lookahead buffer
156 * PacketSize = Total size of received packet
157 */
158 {
159 KIRQL OldIrql;
160 PLIST_ENTRY CurrentEntry;
161 PADAPTER_BINDING AdapterBinding;
162
163 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
164 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
165 Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
166
167 MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
168
169 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
170 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
171 {
172 CurrentEntry = Adapter->ProtocolListHead.Flink;
173 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
174
175 if (CurrentEntry == &Adapter->ProtocolListHead)
176 {
177 NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n"));
178 }
179
180 while (CurrentEntry != &Adapter->ProtocolListHead)
181 {
182 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
183 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
184
185 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
186
187 #ifdef DBG
188 if(!AdapterBinding)
189 {
190 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding was null\n"));
191 break;
192 }
193
194 if(!AdapterBinding->ProtocolBinding)
195 {
196 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding was null\n"));
197 break;
198 }
199
200 if(!AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)
201 {
202 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding->Chars.ReceiveHandler was null\n"));
203 break;
204 }
205 #endif
206
207 NDIS_DbgPrint
208 (MID_TRACE,
209 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
210 *AdapterBinding->ProtocolBinding->Chars.ReceiveHandler,
211 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
212 MacReceiveContext,
213 HeaderBuffer,
214 HeaderBufferSize,
215 LookaheadBuffer,
216 LookaheadBufferSize,
217 PacketSize));
218
219 /* call the receive handler */
220 (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
221 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
222 MacReceiveContext,
223 HeaderBuffer,
224 HeaderBufferSize,
225 LookaheadBuffer,
226 LookaheadBufferSize,
227 PacketSize);
228
229 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
230
231 CurrentEntry = CurrentEntry->Flink;
232 }
233 }
234 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
235
236 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
237 }
238
239 \f
240 VOID NTAPI
241 MiniIndicateReceivePacket(
242 IN NDIS_HANDLE Miniport,
243 IN PPNDIS_PACKET PacketArray,
244 IN UINT NumberOfPackets)
245 /*
246 * FUNCTION: receives miniport packet array indications
247 * ARGUMENTS:
248 * Miniport: Miniport handle for the adapter
249 * PacketArray: pointer to a list of packet pointers to indicate
250 * NumberOfPackets: number of packets to indicate
251 * NOTES:
252 * - This currently is a big temporary hack. In the future this should
253 * call ProtocolReceivePacket() on each bound protocol if it exists.
254 * For now it just mimics NdisMEthIndicateReceive.
255 */
256 {
257 UINT i;
258
259 for(i = 0; i < NumberOfPackets; i++)
260 {
261 PCHAR PacketBuffer = 0;
262 UINT PacketLength = 0;
263 PNDIS_BUFFER NdisBuffer = 0;
264
265 #define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
266
267 NdisAllocateMemoryWithTag((PVOID)&PacketBuffer, 1518, PACKET_TAG);
268 if(!PacketBuffer)
269 {
270 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources\n"));
271 return;
272 }
273
274 NdisQueryPacket(PacketArray[i], NULL, NULL, &NdisBuffer, NULL);
275
276 while(NdisBuffer)
277 {
278 PNDIS_BUFFER CurrentBuffer;
279 PVOID BufferVa;
280 UINT BufferLen;
281
282 NdisQueryBuffer(NdisBuffer, &BufferVa, &BufferLen);
283 memcpy(PacketBuffer + PacketLength, BufferVa, BufferLen);
284 PacketLength += BufferLen;
285
286 CurrentBuffer = NdisBuffer;
287 NdisGetNextBuffer(CurrentBuffer, &NdisBuffer);
288 }
289
290 NDIS_DbgPrint(MID_TRACE, ("indicating a %d-byte packet\n", PacketLength));
291
292 MiniIndicateData(Miniport, NULL, PacketBuffer, 14, PacketBuffer+14, PacketLength-14, PacketLength-14);
293
294 NdisFreeMemory(PacketBuffer, 0, 0);
295 }
296 }
297
298 \f
299 VOID NTAPI
300 MiniResetComplete(
301 IN NDIS_HANDLE MiniportAdapterHandle,
302 IN NDIS_STATUS Status,
303 IN BOOLEAN AddressingReset)
304 {
305 UNIMPLEMENTED
306 }
307
308
309 \f
310 VOID NTAPI
311 MiniRequestComplete(
312 IN PNDIS_MINIPORT_BLOCK Adapter,
313 IN PNDIS_REQUEST Request,
314 IN NDIS_STATUS Status)
315 {
316 PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
317
318 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
319
320 if( MacBlock->Binding->RequestCompleteHandler ) {
321 (*MacBlock->Binding->RequestCompleteHandler)(
322 MacBlock->Binding->ProtocolBindingContext,
323 Request,
324 Status);
325 }
326 }
327
328 VOID NTAPI
329 MiniSendComplete(
330 IN NDIS_HANDLE MiniportAdapterHandle,
331 IN PNDIS_PACKET Packet,
332 IN NDIS_STATUS Status)
333 /*
334 * FUNCTION: Forwards a message to the initiating protocol saying
335 * that a packet was handled
336 * ARGUMENTS:
337 * NdisAdapterHandle = Handle input to MiniportInitialize
338 * Packet = Pointer to NDIS packet that was sent
339 * Status = Status of send operation
340 */
341 {
342 PADAPTER_BINDING AdapterBinding;
343
344 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
345
346 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
347
348 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
349 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
350 Packet,
351 Status);
352 }
353
354
355 VOID NTAPI
356 MiniSendResourcesAvailable(
357 IN NDIS_HANDLE MiniportAdapterHandle)
358 {
359 /*
360 UNIMPLEMENTED
361 */
362 }
363
364
365 VOID NTAPI
366 MiniTransferDataComplete(
367 IN NDIS_HANDLE MiniportAdapterHandle,
368 IN PNDIS_PACKET Packet,
369 IN NDIS_STATUS Status,
370 IN UINT BytesTransferred)
371 {
372 PADAPTER_BINDING AdapterBinding;
373
374 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
375
376 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
377
378 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
379 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
380 Packet,
381 Status);
382 }
383
384 \f
385 BOOLEAN
386 MiniAdapterHasAddress(
387 PLOGICAL_ADAPTER Adapter,
388 PNDIS_PACKET Packet)
389 /*
390 * FUNCTION: Determines whether a packet has the same destination address as an adapter
391 * ARGUMENTS:
392 * Adapter = Pointer to logical adapter object
393 * Packet = Pointer to NDIS packet
394 * RETURNS:
395 * TRUE if the destination address is that of the adapter, FALSE if not
396 */
397 {
398 UINT Length;
399 PUCHAR Start1;
400 PUCHAR Start2;
401 PNDIS_BUFFER NdisBuffer;
402 UINT BufferLength;
403
404 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
405
406 #ifdef DBG
407 if(!Adapter)
408 {
409 NDIS_DbgPrint(MID_TRACE, ("Adapter object was null\n"));
410 return FALSE;
411 }
412
413 if(!Packet)
414 {
415 NDIS_DbgPrint(MID_TRACE, ("Packet was null\n"));
416 return FALSE;
417 }
418 #endif
419
420 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
421
422 if (!NdisBuffer)
423 {
424 NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
425 return FALSE;
426 }
427
428 NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
429
430 /* FIXME: Should handle fragmented packets */
431
432 switch (Adapter->NdisMiniportBlock.MediaType)
433 {
434 case NdisMedium802_3:
435 Length = ETH_LENGTH_OF_ADDRESS;
436 /* Destination address is the first field */
437 break;
438
439 default:
440 NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
441 return FALSE;
442 }
443
444 if (BufferLength < Length)
445 {
446 NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
447 return FALSE;
448 }
449
450 Start1 = (PUCHAR)&Adapter->Address;
451 NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
452 *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
453 *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5))
454 );
455
456 return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
457 }
458
459 \f
460 PLOGICAL_ADAPTER
461 MiniLocateDevice(
462 PNDIS_STRING AdapterName)
463 /*
464 * FUNCTION: Finds an adapter object by name
465 * ARGUMENTS:
466 * AdapterName = Pointer to name of adapter
467 * RETURNS:
468 * Pointer to logical adapter object, or NULL if none was found.
469 * If found, the adapter is referenced for the caller. The caller
470 * is responsible for dereferencing after use
471 */
472 {
473 KIRQL OldIrql;
474 PLIST_ENTRY CurrentEntry;
475 PLOGICAL_ADAPTER Adapter = 0;
476
477 ASSERT(AdapterName);
478
479 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
480
481 if(IsListEmpty(&AdapterListHead))
482 {
483 NDIS_DbgPrint(DEBUG_MINIPORT, ("No registered miniports for protocol to bind to\n"));
484 return NULL;
485 }
486
487 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
488 {
489 CurrentEntry = AdapterListHead.Flink;
490
491 while (CurrentEntry != &AdapterListHead)
492 {
493 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
494
495 ASSERT(Adapter);
496
497 NDIS_DbgPrint(DEBUG_MINIPORT, ("Examining adapter 0x%lx\n", Adapter));
498 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
499 NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
500
501 if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
502 {
503 break;
504 }
505
506 Adapter = NULL;
507 CurrentEntry = CurrentEntry->Flink;
508 }
509 }
510 KeReleaseSpinLock(&AdapterListLock, OldIrql);
511
512 if(Adapter)
513 {
514 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
515 }
516 else
517 {
518 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n"));
519 }
520
521 return Adapter;
522 }
523
524 \f
525 NDIS_STATUS
526 MiniQueryInformation(
527 PLOGICAL_ADAPTER Adapter,
528 NDIS_OID Oid,
529 ULONG Size,
530 PVOID Buffer,
531 PULONG BytesWritten)
532 /*
533 * FUNCTION: Queries a logical adapter for properties
534 * ARGUMENTS:
535 * Adapter = Pointer to the logical adapter object to query
536 * Oid = Specifies the Object ID to query for
537 * Size = Size of the passed buffer
538 * Buffer = Buffer for the output
539 * BytesWritten = Address of buffer to place number of bytes written
540 * NOTES:
541 * If the specified buffer is too small, a new buffer is allocated,
542 * and the query is attempted again
543 * RETURNS:
544 * Status of operation
545 * TODO:
546 * Is there any way to use the buffer provided by the protocol?
547 */
548 {
549 NDIS_STATUS NdisStatus;
550 ULONG BytesNeeded;
551
552 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
553
554 /* call the miniport's queryinfo handler */
555 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
556 Adapter->NdisMiniportBlock.MiniportAdapterContext,
557 Oid,
558 Buffer,
559 Size,
560 BytesWritten,
561 &BytesNeeded);
562
563 /* FIXME: Wait in pending case! */
564
565 return NdisStatus;
566 }
567
568 \f
569 NDIS_STATUS
570 FASTCALL
571 MiniQueueWorkItem(
572 PLOGICAL_ADAPTER Adapter,
573 NDIS_WORK_ITEM_TYPE WorkItemType,
574 PVOID WorkItemContext)
575 /*
576 * FUNCTION: Queues a work item for execution at a later time
577 * ARGUMENTS:
578 * Adapter = Pointer to the logical adapter object to queue work item on
579 * WorkItemType = Type of work item to queue
580 * WorkItemContext = Pointer to context information for work item
581 * NOTES:
582 * Adapter lock must be held when called
583 * RETURNS:
584 * Status of operation
585 */
586 {
587 PNDIS_MINIPORT_WORK_ITEM Item;
588
589 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
590
591 ASSERT(Adapter);
592 ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
593
594 Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
595 if (Item == NULL)
596 {
597 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
598 return NDIS_STATUS_RESOURCES;
599 }
600
601 Item->WorkItemType = WorkItemType;
602 Item->WorkItemContext = WorkItemContext;
603
604 /* safe due to adapter lock held */
605 Item->Link.Next = NULL;
606 if (!Adapter->WorkQueueHead)
607 {
608 Adapter->WorkQueueHead = Item;
609 Adapter->WorkQueueTail = Item;
610 }
611 else
612 {
613 Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
614 Adapter->WorkQueueTail = Item;
615 }
616
617 KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
618
619 return NDIS_STATUS_SUCCESS;
620 }
621
622 \f
623 NDIS_STATUS
624 FASTCALL
625 MiniDequeueWorkItem(
626 PLOGICAL_ADAPTER Adapter,
627 NDIS_WORK_ITEM_TYPE *WorkItemType,
628 PVOID *WorkItemContext)
629 /*
630 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
631 * ARGUMENTS:
632 * Adapter = Pointer to the logical adapter object to dequeue work item from
633 * AdapterBinding = Address of buffer for adapter binding for this request
634 * WorkItemType = Address of buffer for work item type
635 * WorkItemContext = Address of buffer for pointer to context information
636 * NOTES:
637 * Adapter lock must be held when called
638 * RETURNS:
639 * Status of operation
640 */
641 {
642 PNDIS_MINIPORT_WORK_ITEM Item;
643
644 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
645
646 Item = Adapter->WorkQueueHead;
647
648 if (Item)
649 {
650 /* safe due to adapter lock held */
651 Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
652
653 if (Item == Adapter->WorkQueueTail)
654 Adapter->WorkQueueTail = NULL;
655
656 *WorkItemType = Item->WorkItemType;
657 *WorkItemContext = Item->WorkItemContext;
658
659 ExFreePool(Item);
660
661 return NDIS_STATUS_SUCCESS;
662 }
663
664 return NDIS_STATUS_FAILURE;
665 }
666
667 \f
668 NDIS_STATUS
669 MiniDoRequest(
670 PNDIS_MINIPORT_BLOCK Adapter,
671 PNDIS_REQUEST NdisRequest)
672 /*
673 * FUNCTION: Sends a request to a miniport
674 * ARGUMENTS:
675 * AdapterBinding = Pointer to binding used in the request
676 * NdisRequest = Pointer to NDIS request structure describing request
677 * RETURNS:
678 * Status of operation
679 */
680 {
681 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
682
683 Adapter->MediaRequest = NdisRequest;
684
685 switch (NdisRequest->RequestType)
686 {
687 case NdisRequestQueryInformation:
688 return (*Adapter->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
689 Adapter->MiniportAdapterContext,
690 NdisRequest->DATA.QUERY_INFORMATION.Oid,
691 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
692 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
693 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
694 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
695 break;
696
697 case NdisRequestSetInformation:
698 return (*Adapter->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
699 Adapter->MiniportAdapterContext,
700 NdisRequest->DATA.SET_INFORMATION.Oid,
701 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
702 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
703 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
704 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
705 break;
706
707 default:
708 return NDIS_STATUS_FAILURE;
709 }
710 }
711
712 \f
713 /*
714 * @implemented
715 */
716 #undef NdisMQueryInformationComplete
717 VOID
718 EXPORT
719 NdisMQueryInformationComplete(
720 IN NDIS_HANDLE MiniportAdapterHandle,
721 IN NDIS_STATUS Status)
722 {
723 PNDIS_MINIPORT_BLOCK MiniportBlock =
724 (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
725 ASSERT(MiniportBlock);
726 if( MiniportBlock->QueryCompleteHandler )
727 (MiniportBlock->QueryCompleteHandler)(MiniportAdapterHandle, Status);
728 }
729
730 \f
731 VOID NTAPI MiniportDpc(
732 IN PKDPC Dpc,
733 IN PVOID DeferredContext,
734 IN PVOID SystemArgument1,
735 IN PVOID SystemArgument2)
736 /*
737 * FUNCTION: Deferred routine to handle serialization
738 * ARGUMENTS:
739 * Dpc = Pointer to DPC object
740 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
741 * SystemArgument1 = Unused
742 * SystemArgument2 = Unused
743 */
744 {
745 NDIS_STATUS NdisStatus;
746 PVOID WorkItemContext;
747 NDIS_WORK_ITEM_TYPE WorkItemType;
748 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
749
750 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
751
752 NdisStatus =
753 MiniDequeueWorkItem
754 (Adapter, &WorkItemType, &WorkItemContext);
755
756 if (NdisStatus == NDIS_STATUS_SUCCESS)
757 {
758 switch (WorkItemType)
759 {
760 case NdisWorkItemSend:
761 /*
762 * called by ProSend when protocols want to send packets to the miniport
763 */
764 #ifdef DBG
765 MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
766 #endif
767 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
768 {
769 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
770
771 /*
772 * XXX assumes single-packet - prolly OK since we'll call something
773 * different on multi-packet sends
774 */
775 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
776 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
777 NdisStatus =
778 NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
779
780 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's SendPackets handler\n"));
781 }
782 else
783 {
784 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
785
786 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
787 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);
788
789 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's Send handler\n"));
790 }
791 if( NdisStatus != NDIS_STATUS_PENDING ) {
792 NdisMSendComplete
793 ( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
794 Adapter->MiniportBusy = FALSE;
795 }
796 break;
797
798 case NdisWorkItemSendLoopback:
799 /*
800 * called by ProSend when protocols want to send loopback packets
801 */
802 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
803 NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
804 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
805 break;
806
807 case NdisWorkItemReturnPackets:
808 break;
809
810 case NdisWorkItemResetRequested:
811 break;
812
813 case NdisWorkItemResetInProgress:
814 break;
815
816 case NdisWorkItemMiniportCallback:
817 break;
818
819 case NdisWorkItemRequest:
820 NdisStatus = MiniDoRequest(&Adapter->NdisMiniportBlock, (PNDIS_REQUEST)WorkItemContext);
821
822 if (NdisStatus == NDIS_STATUS_PENDING)
823 break;
824
825 switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
826 {
827 case NdisRequestQueryInformation:
828 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
829 MiniRequestComplete( &Adapter->NdisMiniportBlock, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
830 break;
831
832 case NdisRequestSetInformation:
833 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
834 MiniRequestComplete( &Adapter->NdisMiniportBlock, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
835 break;
836
837 default:
838 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
839 break;
840 }
841 break;
842
843 default:
844 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
845 break;
846 }
847 }
848 }
849
850 \f
851 VOID
852 NTAPI
853 MiniStatus(
854 IN NDIS_HANDLE MiniportHandle,
855 IN NDIS_STATUS GeneralStatus,
856 IN PVOID StatusBuffer,
857 IN UINT StatusBufferSize)
858 {
859 UNIMPLEMENTED
860 }
861
862 \f
863 VOID
864 NTAPI
865 MiniStatusComplete(
866 IN NDIS_HANDLE MiniportAdapterHandle)
867 {
868 UNIMPLEMENTED
869 }
870
871 \f
872 /*
873 * @unimplemented
874 */
875 VOID
876 EXPORT
877 NdisMCloseLog(
878 IN NDIS_HANDLE LogHandle)
879 {
880 UNIMPLEMENTED
881 }
882
883 \f
884 /*
885 * @unimplemented
886 */
887 NDIS_STATUS
888 EXPORT
889 NdisMCreateLog(
890 IN NDIS_HANDLE MiniportAdapterHandle,
891 IN UINT Size,
892 OUT PNDIS_HANDLE LogHandle)
893 {
894 UNIMPLEMENTED
895
896 return NDIS_STATUS_FAILURE;
897 }
898
899 \f
900 /*
901 * @implemented
902 */
903 VOID
904 EXPORT
905 NdisMDeregisterAdapterShutdownHandler(
906 IN NDIS_HANDLE MiniportHandle)
907 /*
908 * FUNCTION: de-registers a shutdown handler
909 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
910 */
911 {
912 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
913
914 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
915
916 if(Adapter->BugcheckContext->ShutdownHandler)
917 KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
918 }
919
920 \f
921 /*
922 * @unimplemented
923 */
924 VOID
925 EXPORT
926 NdisMFlushLog(
927 IN NDIS_HANDLE LogHandle)
928 {
929 UNIMPLEMENTED
930 }
931
932 /*
933 * @unimplemented
934 */
935 #undef NdisMIndicateStatus
936 VOID
937 EXPORT
938 NdisMIndicateStatus(
939 IN NDIS_HANDLE MiniportAdapterHandle,
940 IN NDIS_STATUS GeneralStatus,
941 IN PVOID StatusBuffer,
942 IN UINT StatusBufferSize)
943 {
944 UNIMPLEMENTED
945 }
946
947 /*
948 * @unimplemented
949 */
950 #undef NdisMIndicateStatusComplete
951 VOID
952 EXPORT
953 NdisMIndicateStatusComplete(
954 IN NDIS_HANDLE MiniportAdapterHandle)
955 {
956 UNIMPLEMENTED
957 }
958
959 \f
960 /*
961 * @implemented
962 */
963 VOID
964 EXPORT
965 NdisInitializeWrapper(
966 OUT PNDIS_HANDLE NdisWrapperHandle,
967 IN PVOID SystemSpecific1,
968 IN PVOID SystemSpecific2,
969 IN PVOID SystemSpecific3)
970 /*
971 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
972 * ARGUMENTS:
973 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
974 * SystemSpecific1 = Pointer to the driver's driver object
975 * SystemSpecific2 = Pointer to the driver's registry path
976 * SystemSpecific3 = Always NULL
977 * NOTES:
978 * - SystemSpecific2 goes invalid so we copy it
979 */
980 {
981 PNDIS_M_DRIVER_BLOCK Miniport;
982 PUNICODE_STRING RegistryPath;
983 WCHAR *RegistryBuffer;
984
985 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
986
987 ASSERT(NdisWrapperHandle);
988
989 *NdisWrapperHandle = NULL;
990
991 #if BREAK_ON_MINIPORT_INIT
992 __asm__ ("int $3\n");
993 #endif
994
995 Miniport = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DRIVER_BLOCK));
996
997 if (!Miniport)
998 {
999 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1000 return;
1001 }
1002
1003 RtlZeroMemory(Miniport, sizeof(NDIS_M_DRIVER_BLOCK));
1004
1005 KeInitializeSpinLock(&Miniport->Lock);
1006
1007 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
1008
1009 /* set the miniport's driver registry path */
1010 RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
1011 if(!RegistryPath)
1012 {
1013 ExFreePool(Miniport);
1014 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1015 return;
1016 }
1017
1018 RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
1019 RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR); /* room for 0-term */
1020
1021 RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
1022 if(!RegistryBuffer)
1023 {
1024 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1025 ExFreePool(Miniport);
1026 ExFreePool(RegistryPath);
1027 return;
1028 }
1029
1030 RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
1031 RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
1032
1033 RegistryPath->Buffer = RegistryBuffer;
1034 Miniport->RegistryPath = RegistryPath;
1035
1036 InitializeListHead(&Miniport->DeviceList);
1037
1038 /* Put miniport in global miniport list */
1039 ExInterlockedInsertTailList(&MiniportListHead, &Miniport->ListEntry, &MiniportListLock);
1040
1041 *NdisWrapperHandle = Miniport;
1042 }
1043
1044 \f
1045 VOID NTAPI NdisIBugcheckCallback(
1046 IN PVOID Buffer,
1047 IN ULONG Length)
1048 /*
1049 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1050 * ARGUMENTS:
1051 * Buffer: Pointer to a bugcheck callback context
1052 * Length: Unused
1053 */
1054 {
1055 PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
1056 ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
1057
1058 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1059
1060 if(sh)
1061 sh(Context->DriverContext);
1062 }
1063
1064 \f
1065 /*
1066 * @implemented
1067 */
1068 VOID
1069 EXPORT
1070 NdisMRegisterAdapterShutdownHandler(
1071 IN NDIS_HANDLE MiniportHandle,
1072 IN PVOID ShutdownContext,
1073 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
1074 /*
1075 * FUNCTION: Register a shutdown handler for an adapter
1076 * ARGUMENTS:
1077 * MiniportHandle: Handle originally passed into MiniportInitialize
1078 * ShutdownContext: Pre-initialized bugcheck context
1079 * ShutdownHandler: Function to call to handle the bugcheck
1080 * NOTES:
1081 * - I'm not sure about ShutdownContext
1082 * - FIXME - memory leak below
1083 */
1084 {
1085 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1086 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext = Adapter->BugcheckContext;
1087
1088 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1089
1090 if(BugcheckContext)
1091 return;
1092
1093 BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
1094 if(!BugcheckContext)
1095 {
1096 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1097 return;
1098 }
1099
1100 BugcheckContext->ShutdownHandler = ShutdownHandler;
1101 BugcheckContext->DriverContext = ShutdownContext;
1102
1103 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1104 BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
1105
1106 KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
1107 BugcheckContext, sizeof(BugcheckContext), (PUCHAR)"Ndis Miniport");
1108 }
1109
1110 \f
1111 NDIS_STATUS
1112 DoQueries(
1113 PLOGICAL_ADAPTER Adapter,
1114 NDIS_OID AddressOID)
1115 /*
1116 * FUNCTION: Queries miniport for information
1117 * ARGUMENTS:
1118 * Adapter = Pointer to logical adapter
1119 * AddressOID = OID to use to query for current address
1120 * RETURNS:
1121 * Status of operation
1122 */
1123 {
1124 ULONG BytesWritten;
1125 NDIS_STATUS NdisStatus;
1126
1127 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1128
1129 /* Get MAC options for adapter */
1130 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, sizeof(UINT),
1131 &Adapter->NdisMiniportBlock.MacOptions,
1132 &BytesWritten);
1133
1134 if (NdisStatus != NDIS_STATUS_SUCCESS)
1135 {
1136 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
1137 return NdisStatus;
1138 }
1139
1140 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
1141
1142 /* Get current hardware address of adapter */
1143 NdisStatus = MiniQueryInformation(Adapter, AddressOID, Adapter->AddressLength,
1144 &Adapter->Address, &BytesWritten);
1145
1146 if (NdisStatus != NDIS_STATUS_SUCCESS)
1147 {
1148 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
1149 return NdisStatus;
1150 }
1151
1152 #ifdef DBG
1153 {
1154 /* 802.3 only */
1155
1156 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
1157
1158 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]));
1159 }
1160 #endif /* DBG */
1161
1162 /* Get maximum lookahead buffer size of adapter */
1163 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, sizeof(ULONG),
1164 &Adapter->NdisMiniportBlock.MaximumLookahead, &BytesWritten);
1165
1166 if (NdisStatus != NDIS_STATUS_SUCCESS)
1167 {
1168 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1169 return NdisStatus;
1170 }
1171
1172 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.MaximumLookahead));
1173
1174 /* Get current lookahead buffer size of adapter */
1175 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, sizeof(ULONG),
1176 &Adapter->NdisMiniportBlock.CurrentLookahead, &BytesWritten);
1177
1178 if (NdisStatus != NDIS_STATUS_SUCCESS)
1179 {
1180 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1181 return NdisStatus;
1182 }
1183
1184 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
1185
1186 if (Adapter->NdisMiniportBlock.MaximumLookahead != 0)
1187 {
1188 Adapter->LookaheadLength = Adapter->NdisMiniportBlock.MaximumLookahead + Adapter->MediumHeaderSize;
1189 Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool, Adapter->LookaheadLength);
1190
1191 if (!Adapter->LookaheadBuffer)
1192 return NDIS_STATUS_RESOURCES;
1193 }
1194
1195 return STATUS_SUCCESS;
1196 }
1197
1198 \f
1199 NTSTATUS
1200 NTAPI
1201 NdisIForwardIrpAndWaitCompletionRoutine(
1202 PDEVICE_OBJECT Fdo,
1203 PIRP Irp,
1204 PVOID Context)
1205 {
1206 PKEVENT Event = Context;
1207
1208 if (Irp->PendingReturned)
1209 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
1210
1211 return STATUS_MORE_PROCESSING_REQUIRED;
1212 }
1213
1214 \f
1215 NTSTATUS
1216 NTAPI
1217 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter, PIRP Irp)
1218 {
1219 KEVENT Event;
1220 NTSTATUS Status;
1221
1222 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1223 IoCopyCurrentIrpStackLocationToNext(Irp);
1224 IoSetCompletionRoutine(Irp, NdisIForwardIrpAndWaitCompletionRoutine, &Event,
1225 TRUE, TRUE, TRUE);
1226 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1227 if (Status == STATUS_PENDING)
1228 {
1229 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1230 Status = Irp->IoStatus.Status;
1231 }
1232 return Status;
1233 }
1234
1235 \f
1236 NTSTATUS
1237 NTAPI
1238 NdisIPnPStartDevice(
1239 IN PDEVICE_OBJECT DeviceObject,
1240 PIRP Irp)
1241 /*
1242 * FUNCTION: Handle the PnP start device event
1243 * ARGUMENTS:
1244 * DeviceObejct = Functional Device Object
1245 * Irp = IRP_MN_START_DEVICE I/O request packet
1246 * RETURNS:
1247 * Status of operation
1248 */
1249 {
1250 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1251 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1252 NDIS_WRAPPER_CONTEXT WrapperContext;
1253 NDIS_STATUS NdisStatus;
1254 NDIS_STATUS OpenErrorStatus;
1255 NTSTATUS Status;
1256 UINT SelectedMediumIndex = 0;
1257 NDIS_OID AddressOID;
1258 BOOLEAN Success = FALSE;
1259 ULONG ResourceCount;
1260 ULONG ResourceListSize;
1261 UNICODE_STRING ParamName;
1262 PNDIS_CONFIGURATION_PARAMETER ConfigParam;
1263 NDIS_HANDLE ConfigHandle;
1264 ULONG Size;
1265 /* FIXME - KIRQL OldIrql; */
1266
1267 /*
1268 * Prepare wrapper context used by HW and configuration routines.
1269 */
1270
1271 NDIS_DbgPrint(DEBUG_MINIPORT, ("Start Device %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
1272
1273 NDIS_DbgPrint(MAX_TRACE, ("Inserting adapter 0x%x into adapter list\n", Adapter));
1274
1275 /* Put adapter in global adapter list */
1276 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1277
1278 Status = IoOpenDeviceRegistryKey(
1279 Adapter->NdisMiniportBlock.PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
1280 KEY_ALL_ACCESS, &WrapperContext.RegistryHandle);
1281 if (!NT_SUCCESS(Status))
1282 {
1283 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
1284 return Status;
1285 }
1286
1287 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
1288
1289 WrapperContext.DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
1290
1291 /*
1292 * Store the adapter resources used by HW routines such as
1293 * NdisMQueryAdapterResources.
1294 */
1295
1296 if (Stack->Parameters.StartDevice.AllocatedResources != NULL &&
1297 Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
1298 {
1299 ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
1300 PartialResourceList.Count;
1301 ResourceListSize =
1302 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1303 PartialDescriptors[ResourceCount]);
1304
1305 Adapter->NdisMiniportBlock.AllocatedResources =
1306 ExAllocatePool(PagedPool, ResourceListSize);
1307 if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
1308 {
1309 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1310 return STATUS_INSUFFICIENT_RESOURCES;
1311 }
1312
1313 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
1314 ExAllocatePool(PagedPool, ResourceListSize);
1315 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
1316 {
1317 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1318 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
1319 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1320 return STATUS_INSUFFICIENT_RESOURCES;
1321 }
1322
1323 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
1324 Stack->Parameters.StartDevice.AllocatedResources,
1325 ResourceListSize);
1326
1327 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
1328 Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
1329 ResourceListSize);
1330 }
1331
1332 /*
1333 * Store the Bus Type, Bus Number and Slot information. It's used by
1334 * the hardware routines then.
1335 */
1336
1337 NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
1338
1339 Size = sizeof(ULONG);
1340 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1341 DevicePropertyLegacyBusType, Size,
1342 &Adapter->NdisMiniportBlock.BusType, &Size);
1343 if (!NT_SUCCESS(Status) || (INTERFACE_TYPE)Adapter->NdisMiniportBlock.BusType == InterfaceTypeUndefined)
1344 {
1345 NdisInitUnicodeString(&ParamName, L"BusType");
1346 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1347 &ParamName, NdisParameterInteger);
1348 if (NdisStatus == NDIS_STATUS_SUCCESS)
1349 Adapter->NdisMiniportBlock.BusType = ConfigParam->ParameterData.IntegerData;
1350 else
1351 Adapter->NdisMiniportBlock.BusType = Isa;
1352 }
1353
1354 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1355 DevicePropertyBusNumber, Size,
1356 &Adapter->NdisMiniportBlock.BusNumber, &Size);
1357 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusNumber == 0xFFFFFFF0)
1358 {
1359 NdisInitUnicodeString(&ParamName, L"BusNumber");
1360 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1361 &ParamName, NdisParameterInteger);
1362 if (NdisStatus == NDIS_STATUS_SUCCESS)
1363 Adapter->NdisMiniportBlock.BusNumber = ConfigParam->ParameterData.IntegerData;
1364 else
1365 Adapter->NdisMiniportBlock.BusNumber = 0;
1366 }
1367 WrapperContext.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
1368
1369 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1370 DevicePropertyAddress, Size,
1371 &Adapter->NdisMiniportBlock.SlotNumber, &Size);
1372 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.SlotNumber == (NDIS_INTERFACE_TYPE)-1)
1373 {
1374 NdisInitUnicodeString(&ParamName, L"SlotNumber");
1375 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1376 &ParamName, NdisParameterInteger);
1377 if (NdisStatus == NDIS_STATUS_SUCCESS)
1378 Adapter->NdisMiniportBlock.SlotNumber = ConfigParam->ParameterData.IntegerData;
1379 else
1380 Adapter->NdisMiniportBlock.SlotNumber = 0;
1381 }
1382 else
1383 {
1384 /* Convert slotnumber to PCI_SLOT_NUMBER */
1385 ULONG PciSlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
1386 PCI_SLOT_NUMBER SlotNumber;
1387
1388 SlotNumber.u.AsULONG = 0;
1389 SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF;
1390 SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF;
1391
1392 Adapter->NdisMiniportBlock.SlotNumber = SlotNumber.u.AsULONG;
1393 }
1394 NdisCloseConfiguration(ConfigHandle);
1395
1396 /* Set handlers (some NDIS macros require these) */
1397 Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
1398 Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
1399 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
1400 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1401 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1402 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
1403 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
1404 Adapter->NdisMiniportBlock.StatusHandler = MiniStatus;
1405 Adapter->NdisMiniportBlock.StatusCompleteHandler= MiniStatusComplete;
1406
1407 /*
1408 * Call MiniportInitialize.
1409 */
1410
1411 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
1412 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.InitializeHandler)(
1413 &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
1414 MEDIA_ARRAY_SIZE, Adapter, (NDIS_HANDLE)&WrapperContext);
1415
1416 ZwClose(WrapperContext.RegistryHandle);
1417
1418 if (NdisStatus != NDIS_STATUS_SUCCESS ||
1419 SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
1420 {
1421 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
1422 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1423 return (NTSTATUS)NdisStatus;
1424 }
1425
1426 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1427
1428 switch (Adapter->NdisMiniportBlock.MediaType)
1429 {
1430 case NdisMedium802_3:
1431 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
1432 AddressOID = OID_802_3_CURRENT_ADDRESS;
1433 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
1434 NdisStatus = DoQueries(Adapter, AddressOID);
1435 if (NdisStatus == NDIS_STATUS_SUCCESS)
1436 {
1437 Success = EthCreateFilter(32, /* FIXME: Query this from miniport. */
1438 Adapter->Address.Type.Medium802_3,
1439 &Adapter->NdisMiniportBlock.EthDB);
1440 if (Success)
1441 ((PETHI_FILTER)Adapter->NdisMiniportBlock.EthDB)->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
1442 else
1443 NdisStatus = NDIS_STATUS_RESOURCES;
1444 }
1445 break;
1446
1447 default:
1448 /* FIXME: Support other types of media */
1449 NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
1450 ASSERT(FALSE);
1451 /* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
1452 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1453 return STATUS_UNSUCCESSFUL;
1454 }
1455
1456 if (!Success || NdisStatus != NDIS_STATUS_SUCCESS)
1457 {
1458 NDIS_DbgPrint(MAX_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
1459 if (Adapter->LookaheadBuffer)
1460 {
1461 ExFreePool(Adapter->LookaheadBuffer);
1462 Adapter->LookaheadBuffer = NULL;
1463 }
1464 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1465 return (NTSTATUS)NdisStatus;
1466 }
1467
1468 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
1469 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
1470
1471 /* Put adapter in adapter list for this miniport */
1472 ExInterlockedInsertTailList(&Adapter->NdisMiniportBlock.DriverHandle->DeviceList, &Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
1473
1474 return STATUS_SUCCESS;
1475 }
1476
1477 \f
1478 NTSTATUS
1479 NTAPI
1480 NdisIPnPStopDevice(
1481 IN PDEVICE_OBJECT DeviceObject,
1482 PIRP Irp)
1483 /*
1484 * FUNCTION: Handle the PnP stop device event
1485 * ARGUMENTS:
1486 * DeviceObejct = Functional Device Object
1487 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1488 * RETURNS:
1489 * Status of operation
1490 */
1491 {
1492 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1493 KIRQL OldIrql;
1494
1495 /* Remove adapter from adapter list for this miniport */
1496 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.DriverHandle->Lock, &OldIrql);
1497 RemoveEntryList(&Adapter->MiniportListEntry);
1498 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.DriverHandle->Lock, OldIrql);
1499
1500 /* Remove adapter from global adapter list */
1501 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
1502 RemoveEntryList(&Adapter->ListEntry);
1503 KeReleaseSpinLock(&AdapterListLock, OldIrql);
1504
1505 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HaltHandler)(Adapter);
1506
1507 if (Adapter->LookaheadBuffer)
1508 {
1509 ExFreePool(Adapter->LookaheadBuffer);
1510 Adapter->LookaheadBuffer = NULL;
1511 }
1512 if (Adapter->NdisMiniportBlock.AllocatedResources)
1513 {
1514 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1515 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
1516 }
1517 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated)
1518 {
1519 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated);
1520 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
1521 }
1522
1523 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
1524 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
1525
1526 return STATUS_SUCCESS;
1527 }
1528
1529 \f
1530 NTSTATUS
1531 NTAPI
1532 NdisIDispatchPnp(
1533 IN PDEVICE_OBJECT DeviceObject,
1534 PIRP Irp)
1535 {
1536 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1537 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1538 NTSTATUS Status;
1539
1540 switch (Stack->MinorFunction)
1541 {
1542 case IRP_MN_START_DEVICE:
1543 Status = NdisIForwardIrpAndWait(Adapter, Irp);
1544 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
1545 {
1546 Status = NdisIPnPStartDevice(DeviceObject, Irp);
1547 }
1548 Irp->IoStatus.Status = Status;
1549 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1550 break;
1551
1552 case IRP_MN_STOP_DEVICE:
1553 Status = NdisIForwardIrpAndWait(Adapter, Irp);
1554 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
1555 {
1556 Status = NdisIPnPStopDevice(DeviceObject, Irp);
1557 }
1558 Irp->IoStatus.Status = Status;
1559 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1560 break;
1561
1562 case IRP_MN_QUERY_DEVICE_RELATIONS:
1563 Status = STATUS_NOT_SUPPORTED;
1564 Irp->IoStatus.Status = Status;
1565 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1566 break;
1567
1568 default:
1569 IoSkipCurrentIrpStackLocation(Irp);
1570 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1571 break;
1572 }
1573
1574 return Status;
1575 }
1576
1577 \f
1578 NTSTATUS
1579 NTAPI
1580 NdisIAddDevice(
1581 IN PDRIVER_OBJECT DriverObject,
1582 IN PDEVICE_OBJECT PhysicalDeviceObject)
1583 /*
1584 * FUNCTION: Create a device for an adapter found using PnP
1585 * ARGUMENTS:
1586 * DriverObject = Pointer to the miniport driver object
1587 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1588 */
1589 {
1590 static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
1591 static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
1592 PNDIS_M_DRIVER_BLOCK Miniport;
1593 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
1594 WCHAR *LinkageKeyBuffer;
1595 ULONG DriverKeyLength;
1596 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1597 UNICODE_STRING ExportName;
1598 PDEVICE_OBJECT DeviceObject;
1599 PLOGICAL_ADAPTER Adapter;
1600 NTSTATUS Status;
1601
1602 /*
1603 * Gain the access to the miniport data structure first.
1604 */
1605
1606 MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)TAG('D','I','M','N'));
1607 if (MiniportPtr == NULL)
1608 {
1609 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get driver object extension.\n"));
1610 return STATUS_UNSUCCESSFUL;
1611 }
1612 Miniport = *MiniportPtr;
1613
1614 /*
1615 * Get name of the Linkage registry key for our adapter. It's located under
1616 * the driver key for our driver and so we have basicly two ways to do it.
1617 * Either we can use IoOpenDriverRegistryKey or compose it using information
1618 * gathered by IoGetDeviceProperty. I choosed the second because
1619 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1620 */
1621
1622 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1623 0, NULL, &DriverKeyLength);
1624 if (Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW)
1625 {
1626 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key length.\n"));
1627 return Status;
1628 }
1629
1630 LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
1631 sizeof(ClassKeyName) + sizeof(LinkageKeyName));
1632 if (LinkageKeyBuffer == NULL)
1633 {
1634 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate memory for driver key name.\n"));
1635 return STATUS_INSUFFICIENT_RESOURCES;
1636 }
1637
1638 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1639 DriverKeyLength, LinkageKeyBuffer +
1640 (sizeof(ClassKeyName) / sizeof(WCHAR)),
1641 &DriverKeyLength);
1642 if (!NT_SUCCESS(Status))
1643 {
1644 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key.\n"));
1645 ExFreePool(LinkageKeyBuffer);
1646 return Status;
1647 }
1648
1649 /* Compose the linkage key name. */
1650 RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
1651 RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
1652 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
1653
1654 NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
1655
1656 /*
1657 * Now open the linkage key and read the "Export" and "RootDevice" values
1658 * which contains device name and root service respectively.
1659 */
1660
1661 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1662 RtlInitUnicodeString(&ExportName, NULL);
1663 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
1664 QueryTable[0].Name = L"Export";
1665 QueryTable[0].EntryContext = &ExportName;
1666
1667 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
1668 QueryTable, NULL, NULL);
1669 ExFreePool(LinkageKeyBuffer);
1670 if (!NT_SUCCESS(Status))
1671 {
1672 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport device name. (%x)\n", Status));
1673 return Status;
1674 }
1675
1676 /*
1677 * Create the device object.
1678 */
1679
1680 NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", &ExportName));
1681
1682 Status = IoCreateDevice(Miniport->DriverObject, sizeof(LOGICAL_ADAPTER),
1683 &ExportName, FILE_DEVICE_PHYSICAL_NETCARD,
1684 0, FALSE, &DeviceObject);
1685 if (!NT_SUCCESS(Status))
1686 {
1687 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
1688 RtlFreeUnicodeString(&ExportName);
1689 return Status;
1690 }
1691
1692 /*
1693 * Initialize the adapter structure.
1694 */
1695
1696 Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1697 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
1698 InitializeListHead(&Adapter->ProtocolListHead);
1699 Adapter->NdisMiniportBlock.DriverHandle = Miniport;
1700
1701 Adapter->NdisMiniportBlock.MiniportName = ExportName;
1702
1703 Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
1704 Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
1705 Adapter->NdisMiniportBlock.NextDeviceObject =
1706 IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
1707 PhysicalDeviceObject);
1708
1709 Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
1710 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
1711
1712 KeInitializeDpc(&Adapter->NdisMiniportBlock.DeferredDpc, MiniportDpc, (PVOID)Adapter);
1713
1714 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1715
1716 return STATUS_SUCCESS;
1717 }
1718
1719 \f
1720 /*
1721 * @implemented
1722 */
1723 NDIS_STATUS
1724 EXPORT
1725 NdisMRegisterMiniport(
1726 IN NDIS_HANDLE NdisWrapperHandle,
1727 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
1728 IN UINT CharacteristicsLength)
1729 /*
1730 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1731 * ARGUMENTS:
1732 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1733 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1734 * CharacteristicsLength = Number of bytes in characteristics buffer
1735 * RETURNS:
1736 * Status of operation
1737 */
1738 {
1739 UINT MinSize;
1740 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1741 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
1742 NTSTATUS Status;
1743
1744 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1745
1746 switch (MiniportCharacteristics->MajorNdisVersion)
1747 {
1748 case 0x03:
1749 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
1750 break;
1751
1752 case 0x04:
1753 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
1754 break;
1755
1756 case 0x05:
1757 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
1758 break;
1759
1760 default:
1761 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
1762 return NDIS_STATUS_BAD_VERSION;
1763 }
1764
1765 if (CharacteristicsLength < MinSize)
1766 {
1767 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1768 return NDIS_STATUS_BAD_CHARACTERISTICS;
1769 }
1770
1771 /* Check if mandatory MiniportXxx functions are specified */
1772 if ((!MiniportCharacteristics->HaltHandler) ||
1773 (!MiniportCharacteristics->InitializeHandler)||
1774 (!MiniportCharacteristics->QueryInformationHandler) ||
1775 (!MiniportCharacteristics->ResetHandler) ||
1776 (!MiniportCharacteristics->SetInformationHandler))
1777 {
1778 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1779 return NDIS_STATUS_BAD_CHARACTERISTICS;
1780 }
1781
1782 if (MiniportCharacteristics->MajorNdisVersion == 0x03)
1783 {
1784 if (!MiniportCharacteristics->SendHandler)
1785 {
1786 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1787 return NDIS_STATUS_BAD_CHARACTERISTICS;
1788 }
1789 }
1790 else if (MiniportCharacteristics->MajorNdisVersion >= 0x04)
1791 {
1792 /* NDIS 4.0+ */
1793 if ((!MiniportCharacteristics->SendHandler) &&
1794 (!MiniportCharacteristics->SendPacketsHandler))
1795 {
1796 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1797 return NDIS_STATUS_BAD_CHARACTERISTICS;
1798 }
1799 }
1800
1801 /* TODO: verify NDIS5 and NDIS5.1 */
1802
1803 RtlCopyMemory(&Miniport->MiniportCharacteristics, MiniportCharacteristics, MinSize);
1804
1805 /*
1806 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
1807 * structure in the driver extension or what?
1808 */
1809
1810 Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)TAG('D','I','M','N'),
1811 sizeof(PNDIS_M_DRIVER_BLOCK), (PVOID*)&MiniportPtr);
1812 if (!NT_SUCCESS(Status))
1813 {
1814 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate driver object extension.\n"));
1815 return NDIS_STATUS_RESOURCES;
1816 }
1817
1818 *MiniportPtr = Miniport;
1819
1820 Miniport->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
1821 Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
1822
1823 return NDIS_STATUS_SUCCESS;
1824 }
1825
1826 \f
1827 /*
1828 * @implemented
1829 */
1830 #undef NdisMResetComplete
1831 VOID
1832 EXPORT
1833 NdisMResetComplete(
1834 IN NDIS_HANDLE MiniportAdapterHandle,
1835 IN NDIS_STATUS Status,
1836 IN BOOLEAN AddressingReset)
1837 {
1838 MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
1839 }
1840
1841 \f
1842 /*
1843 * @implemented
1844 */
1845 #undef NdisMSendComplete
1846 VOID
1847 EXPORT
1848 NdisMSendComplete(
1849 IN NDIS_HANDLE MiniportAdapterHandle,
1850 IN PNDIS_PACKET Packet,
1851 IN NDIS_STATUS Status)
1852 /*
1853 * FUNCTION: Forwards a message to the initiating protocol saying
1854 * that a packet was handled
1855 * ARGUMENTS:
1856 * NdisAdapterHandle = Handle input to MiniportInitialize
1857 * Packet = Pointer to NDIS packet that was sent
1858 * Status = Status of send operation
1859 */
1860 {
1861 MiniSendComplete(MiniportAdapterHandle, Packet, Status);
1862 }
1863
1864 \f
1865 /*
1866 * @implemented
1867 */
1868 #undef NdisMSendResourcesAvailable
1869 VOID
1870 EXPORT
1871 NdisMSendResourcesAvailable(
1872 IN NDIS_HANDLE MiniportAdapterHandle)
1873 {
1874 MiniSendResourcesAvailable(MiniportAdapterHandle);
1875 }
1876
1877 \f
1878 /*
1879 * @implemented
1880 */
1881 #undef NdisMTransferDataComplete
1882 VOID
1883 EXPORT
1884 NdisMTransferDataComplete(
1885 IN NDIS_HANDLE MiniportAdapterHandle,
1886 IN PNDIS_PACKET Packet,
1887 IN NDIS_STATUS Status,
1888 IN UINT BytesTransferred)
1889 {
1890 MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
1891 }
1892
1893 \f
1894 /*
1895 * @implemented
1896 */
1897 #undef NdisMSetInformationComplete
1898 VOID
1899 EXPORT
1900 NdisMSetInformationComplete(
1901 IN NDIS_HANDLE MiniportAdapterHandle,
1902 IN NDIS_STATUS Status)
1903 {
1904 (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->SetCompleteHandler)(MiniportAdapterHandle, Status);
1905 }
1906
1907 \f
1908 /*
1909 * @implemented
1910 */
1911 #undef NdisMSetAttributes
1912 VOID
1913 EXPORT
1914 NdisMSetAttributes(
1915 IN NDIS_HANDLE MiniportAdapterHandle,
1916 IN NDIS_HANDLE MiniportAdapterContext,
1917 IN BOOLEAN BusMaster,
1918 IN NDIS_INTERFACE_TYPE AdapterType)
1919 /*
1920 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1921 * ARGUMENTS:
1922 * MiniportAdapterHandle = Handle input to MiniportInitialize
1923 * MiniportAdapterContext = Pointer to context information
1924 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1925 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1926 */
1927 {
1928 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1929 NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0,
1930 BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
1931 AdapterType);
1932 }
1933
1934 \f
1935 /*
1936 * @implemented
1937 */
1938 VOID
1939 EXPORT
1940 NdisMSetAttributesEx(
1941 IN NDIS_HANDLE MiniportAdapterHandle,
1942 IN NDIS_HANDLE MiniportAdapterContext,
1943 IN UINT CheckForHangTimeInSeconds OPTIONAL,
1944 IN ULONG AttributeFlags,
1945 IN NDIS_INTERFACE_TYPE AdapterType)
1946 /*
1947 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1948 * ARGUMENTS:
1949 * MiniportAdapterHandle = Handle input to MiniportInitialize
1950 * MiniportAdapterContext = Pointer to context information
1951 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1952 * MiniportCheckForHang should be called
1953 * AttributeFlags = Bitmask that indicates specific attributes
1954 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1955 */
1956 {
1957 /* TODO: Take CheckForHandTimeInSeconds into account! */
1958
1959 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1960
1961 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1962
1963 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1964 Adapter->NdisMiniportBlock.Flags = AttributeFlags;
1965 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
1966 if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
1967 NDIS_DbgPrint(MAX_TRACE, ("Intermediate drivers not supported yet.\n"));
1968 }
1969
1970 \f
1971 /*
1972 * @implemented
1973 */
1974 VOID
1975 EXPORT
1976 NdisMSleep(
1977 IN ULONG MicrosecondsToSleep)
1978 /*
1979 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
1980 * ARGUMENTS:
1981 * MicrosecondsToSleep: duh...
1982 * NOTES:
1983 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
1984 */
1985 {
1986 KTIMER Timer;
1987 LARGE_INTEGER DueTime;
1988
1989 PAGED_CODE();
1990
1991 DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
1992
1993 KeInitializeTimer(&Timer);
1994 KeSetTimer(&Timer, DueTime, 0);
1995 KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
1996 }
1997
1998 \f
1999 /*
2000 * @implemented
2001 */
2002 BOOLEAN
2003 EXPORT
2004 NdisMSynchronizeWithInterrupt(
2005 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
2006 IN PVOID SynchronizeFunction,
2007 IN PVOID SynchronizeContext)
2008 {
2009 return(KeSynchronizeExecution(Interrupt->InterruptObject,
2010 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
2011 SynchronizeContext));
2012 }
2013
2014 \f
2015 /*
2016 * @unimplemented
2017 */
2018 NDIS_STATUS
2019 EXPORT
2020 NdisMWriteLogData(
2021 IN NDIS_HANDLE LogHandle,
2022 IN PVOID LogBuffer,
2023 IN UINT LogBufferSize)
2024 {
2025 PUCHAR Buffer = LogBuffer;
2026 UINT i, j, idx;
2027
2028 UNIMPLEMENTED;
2029 for (i = 0; i < LogBufferSize; i += 16)
2030 {
2031 DbgPrint("%08x |", i);
2032 for (j = 0; j < 16; j++)
2033 {
2034 idx = i + j;
2035 if (idx < LogBufferSize)
2036 DbgPrint(" %02x", Buffer[idx]);
2037 else
2038 DbgPrint(" ");
2039 }
2040 DbgPrint(" | ");
2041 for (j = 0; j < 16; j++)
2042 {
2043 idx = i + j;
2044 if (idx == LogBufferSize)
2045 break;
2046 if (Buffer[idx] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2047 DbgPrint("%c", Buffer[idx]);
2048 else
2049 DbgPrint(".");
2050 }
2051 DbgPrint("\n");
2052 }
2053
2054 return NDIS_STATUS_FAILURE;
2055 }
2056
2057 \f
2058 /*
2059 * @implemented
2060 */
2061 VOID
2062 EXPORT
2063 NdisTerminateWrapper(
2064 IN NDIS_HANDLE NdisWrapperHandle,
2065 IN PVOID SystemSpecific)
2066 /*
2067 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2068 * ARGUMENTS:
2069 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2070 * SystemSpecific = Always NULL
2071 */
2072 {
2073 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2074
2075 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2076
2077 ExFreePool(Miniport->RegistryPath->Buffer);
2078 ExFreePool(Miniport->RegistryPath);
2079 ExFreePool(Miniport);
2080 }
2081
2082 /* EOF */
2083