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