ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

miniport.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS NDIS library
00004  * FILE:        ndis/miniport.c
00005  * PURPOSE:     Routines used by NDIS miniport drivers
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  *              Vizzini (vizzini@plasmic.com)
00008  * REVISIONS:
00009  *   CSH 01/08-2000 Created
00010  *   20 Aug 2003 vizzini - DMA support
00011  *   3  Oct 2003 vizzini - SendPackets support
00012  */
00013 
00014 #include "ndissys.h"
00015 
00016 /*
00017  * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
00018  * for each new miniport starting up
00019  */
00020 #define BREAK_ON_MINIPORT_INIT 0
00021 
00022 /*
00023  * This has to be big enough to hold the results of querying the Route value
00024  * from the Linkage key.  Please re-code me to determine this dynamically.
00025  */
00026 #define ROUTE_DATA_SIZE 256
00027 
00028 /* Number of media we know */
00029 #define MEDIA_ARRAY_SIZE    15
00030 
00031 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] =
00032 {
00033     NdisMedium802_3,
00034     NdisMedium802_5,
00035     NdisMediumFddi,
00036     NdisMediumWan,
00037     NdisMediumLocalTalk,
00038     NdisMediumDix,
00039     NdisMediumArcnetRaw,
00040     NdisMediumArcnet878_2,
00041     NdisMediumAtm,
00042     NdisMediumWirelessWan,
00043     NdisMediumIrda,
00044     NdisMediumBpc,
00045     NdisMediumCoWan,
00046     NdisMedium1394,
00047     NdisMediumMax
00048 };
00049 
00050 /* global list and lock of Miniports NDIS has registered */
00051 LIST_ENTRY MiniportListHead;
00052 KSPIN_LOCK MiniportListLock;
00053 
00054 /* global list and lock of adapters NDIS has registered */
00055 LIST_ENTRY AdapterListHead;
00056 KSPIN_LOCK AdapterListLock;
00057 
00058 VOID
00059 MiniDisplayPacket(
00060     PNDIS_PACKET Packet)
00061 {
00062 #if DBG
00063     ULONG i, Length;
00064     UCHAR Buffer[64];
00065     if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
00066         Length = CopyPacketToBuffer(
00067             Buffer,
00068             Packet,
00069             0,
00070             64);
00071 
00072         DbgPrint("*** PACKET START ***");
00073 
00074         for (i = 0; i < Length; i++) {
00075             if (i % 12 == 0)
00076                 DbgPrint("\n%04X ", i);
00077             DbgPrint("%02X ", Buffer[i]);
00078         }
00079 
00080         DbgPrint("*** PACKET STOP ***\n");
00081     }
00082 #endif /* DBG */
00083 }
00084 
00085 VOID
00086 MiniDisplayPacket2(
00087     PVOID  HeaderBuffer,
00088     UINT   HeaderBufferSize,
00089     PVOID  LookaheadBuffer,
00090     UINT   LookaheadBufferSize)
00091 {
00092 #if DBG
00093     if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
00094         ULONG i, Length;
00095         PUCHAR p;
00096 
00097         DbgPrint("*** RECEIVE PACKET START ***\n");
00098         DbgPrint("HEADER:");
00099         p = HeaderBuffer;
00100         for (i = 0; i < HeaderBufferSize; i++) {
00101             if (i % 16 == 0)
00102                 DbgPrint("\n%04X ", i);
00103             DbgPrint("%02X ", *p++);
00104         }
00105 
00106         DbgPrint("\nFRAME:");
00107 
00108         p = LookaheadBuffer;
00109         Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
00110         for (i = 0; i < Length; i++) {
00111             if (i % 16 == 0)
00112                 DbgPrint("\n%04X ", i);
00113             DbgPrint("%02X ", *p++);
00114         }
00115 
00116         DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
00117     }
00118 #endif /* DBG */
00119 }
00120 
00121 PNDIS_MINIPORT_WORK_ITEM
00122 MiniGetFirstWorkItem(
00123     PLOGICAL_ADAPTER Adapter,
00124     NDIS_WORK_ITEM_TYPE Type)
00125 {
00126     PNDIS_MINIPORT_WORK_ITEM CurrentEntry = Adapter->WorkQueueHead;
00127 
00128     while (CurrentEntry)
00129     {
00130       if (CurrentEntry->WorkItemType == Type)
00131           return CurrentEntry;
00132 
00133       CurrentEntry = (PNDIS_MINIPORT_WORK_ITEM)CurrentEntry->Link.Next;
00134     }
00135 
00136     return NULL;
00137 }
00138 
00139 BOOLEAN
00140 MiniIsBusy(
00141     PLOGICAL_ADAPTER Adapter,
00142     NDIS_WORK_ITEM_TYPE Type)
00143 {
00144     BOOLEAN Busy = FALSE;
00145     KIRQL OldIrql;
00146 
00147     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
00148 
00149     if (Type == NdisWorkItemRequest &&
00150         (Adapter->NdisMiniportBlock.PendingRequest || MiniGetFirstWorkItem(Adapter, NdisWorkItemRequest)))
00151     {
00152        Busy = TRUE;
00153     }
00154     else if (Type == NdisWorkItemSend &&
00155              (Adapter->NdisMiniportBlock.FirstPendingPacket || MiniGetFirstWorkItem(Adapter, NdisWorkItemSend)))
00156     {
00157        Busy = TRUE;
00158     }
00159     else if (Type == NdisWorkItemResetRequested &&
00160              (Adapter->NdisMiniportBlock.ResetStatus == NDIS_STATUS_PENDING || MiniGetFirstWorkItem(Adapter, NdisWorkItemResetRequested)))
00161     {
00162        Busy = TRUE;
00163     }
00164 
00165     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
00166 
00167     return Busy;
00168 }
00169 
00170 
00171 VOID
00172 MiniIndicateData(
00173     PLOGICAL_ADAPTER    Adapter,
00174     NDIS_HANDLE         MacReceiveContext,
00175     PVOID               HeaderBuffer,
00176     UINT                HeaderBufferSize,
00177     PVOID               LookaheadBuffer,
00178     UINT                LookaheadBufferSize,
00179     UINT                PacketSize)
00180 /*
00181  * FUNCTION: Indicate received data to bound protocols
00182  * ARGUMENTS:
00183  *     Adapter             = Pointer to logical adapter
00184  *     MacReceiveContext   = MAC receive context handle
00185  *     HeaderBuffer        = Pointer to header buffer
00186  *     HeaderBufferSize    = Size of header buffer
00187  *     LookaheadBuffer     = Pointer to lookahead buffer
00188  *     LookaheadBufferSize = Size of lookahead buffer
00189  *     PacketSize          = Total size of received packet
00190  */
00191 {
00192   KIRQL OldIrql;
00193   PLIST_ENTRY CurrentEntry;
00194   PADAPTER_BINDING AdapterBinding;
00195 
00196   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X)  HeaderBuffer (0x%X)  "
00197       "HeaderBufferSize (0x%X)  LookaheadBuffer (0x%X)  LookaheadBufferSize (0x%X).\n",
00198       Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
00199 
00200   MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
00201 
00202   NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
00203   KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
00204     {
00205       CurrentEntry = Adapter->ProtocolListHead.Flink;
00206       NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
00207 
00208       if (CurrentEntry == &Adapter->ProtocolListHead)
00209         {
00210           NDIS_DbgPrint(MIN_TRACE, ("WARNING: No upper protocol layer.\n"));
00211         }
00212 
00213       while (CurrentEntry != &Adapter->ProtocolListHead)
00214         {
00215           AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
00216       NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
00217 
00218       NDIS_DbgPrint
00219           (MID_TRACE,
00220            ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
00221         *AdapterBinding->ProtocolBinding->Chars.ReceiveHandler,
00222         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
00223         MacReceiveContext,
00224         HeaderBuffer,
00225         HeaderBufferSize,
00226         LookaheadBuffer,
00227         LookaheadBufferSize,
00228         PacketSize));
00229 
00230           /* call the receive handler */
00231           (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
00232               AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
00233               MacReceiveContext,
00234               HeaderBuffer,
00235               HeaderBufferSize,
00236               LookaheadBuffer,
00237               LookaheadBufferSize,
00238               PacketSize);
00239 
00240           CurrentEntry = CurrentEntry->Flink;
00241         }
00242     }
00243   KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
00244 
00245   NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00246 }
00247 
00248 /*
00249  * @implemented
00250  */
00251 VOID
00252 EXPORT
00253 NdisReturnPackets(
00254     IN  PNDIS_PACKET    *PacketsToReturn,
00255     IN  UINT            NumberOfPackets)
00256 /*
00257  * FUNCTION: Releases ownership of one or more packets
00258  * ARGUMENTS:
00259  *     PacketsToReturn = Pointer to an array of pointers to packet descriptors
00260  *     NumberOfPackets = Number of pointers in descriptor pointer array
00261  */
00262 {
00263     UINT i;
00264     PLOGICAL_ADAPTER Adapter;
00265     KIRQL OldIrql;
00266 
00267     NDIS_DbgPrint(MID_TRACE, ("Returning %d packets\n", NumberOfPackets));
00268 
00269     for (i = 0; i < NumberOfPackets; i++)
00270     {
00271         PacketsToReturn[i]->WrapperReserved[0]--;
00272         if (PacketsToReturn[i]->WrapperReserved[0] == 0)
00273         {
00274             Adapter = (PVOID)(ULONG_PTR)PacketsToReturn[i]->Reserved[1];
00275 
00276             NDIS_DbgPrint(MAX_TRACE, ("Freeing packet %d (adapter = 0x%p)\n", i, Adapter));
00277 
00278             KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00279             Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ReturnPacketHandler(
00280                   Adapter->NdisMiniportBlock.MiniportAdapterContext,
00281                   PacketsToReturn[i]);
00282             KeLowerIrql(OldIrql);
00283         }
00284     }
00285 }
00286 VOID NTAPI
00287 MiniIndicateReceivePacket(
00288     IN  NDIS_HANDLE    MiniportAdapterHandle,
00289     IN  PPNDIS_PACKET  PacketArray,
00290     IN  UINT           NumberOfPackets)
00291 /*
00292  * FUNCTION: receives miniport packet array indications
00293  * ARGUMENTS:
00294  *     MiniportAdapterHandle: Miniport handle for the adapter
00295  *     PacketArray: pointer to a list of packet pointers to indicate
00296  *     NumberOfPackets: number of packets to indicate
00297  *
00298  */
00299 {
00300     PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
00301     PLIST_ENTRY CurrentEntry;
00302     PADAPTER_BINDING AdapterBinding;
00303     KIRQL OldIrql;
00304     UINT i;
00305 
00306     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
00307 
00308     CurrentEntry = Adapter->ProtocolListHead.Flink;
00309 
00310     while (CurrentEntry != &Adapter->ProtocolListHead)
00311     {
00312         AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
00313 
00314         for (i = 0; i < NumberOfPackets; i++)
00315         {
00316             /* Store the indicating miniport in the packet */
00317             PacketArray[i]->Reserved[1] = (ULONG_PTR)Adapter;
00318 
00319             if (AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler &&
00320                 NDIS_GET_PACKET_STATUS(PacketArray[i]) != NDIS_STATUS_RESOURCES)
00321             {
00322                 NDIS_DbgPrint(MID_TRACE, ("Indicating packet to protocol's ReceivePacket handler\n"));
00323                 PacketArray[i]->WrapperReserved[0] += (*AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)(
00324                                                        AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
00325                                                        PacketArray[i]);
00326                 NDIS_DbgPrint(MID_TRACE, ("Protocol is holding %d references to the packet\n", PacketArray[i]->WrapperReserved[0]));
00327             }
00328             else
00329             {
00330                 UINT FirstBufferLength, TotalBufferLength, LookAheadSize, HeaderSize;
00331                 PNDIS_BUFFER NdisBuffer;
00332                 PVOID NdisBufferVA, LookAheadBuffer;
00333 
00334                 NdisGetFirstBufferFromPacket(PacketArray[i],
00335                                              &NdisBuffer,
00336                                              &NdisBufferVA,
00337                                              &FirstBufferLength,
00338                                              &TotalBufferLength);
00339                 
00340                 HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
00341 
00342                 LookAheadSize = TotalBufferLength - HeaderSize;
00343 
00344                 LookAheadBuffer = ExAllocatePool(NonPagedPool, LookAheadSize);
00345                 if (!LookAheadBuffer)
00346                 {
00347                     NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead buffer!\n"));
00348                     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
00349                     return;
00350                 }
00351                 
00352                 CopyBufferChainToBuffer(LookAheadBuffer,
00353                                         NdisBuffer,
00354                                         HeaderSize,
00355                                         LookAheadSize);
00356                 
00357                 NDIS_DbgPrint(MID_TRACE, ("Indicating packet to protocol's legacy Receive handler\n"));
00358                 (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
00359                      AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
00360                      AdapterBinding->NdisOpenBlock.MacHandle,
00361                      NdisBufferVA,
00362                      HeaderSize,
00363                      LookAheadBuffer,
00364                      LookAheadSize,
00365                      TotalBufferLength - HeaderSize);
00366                 
00367                 ExFreePool(LookAheadBuffer);
00368             }
00369         }
00370 
00371         CurrentEntry = CurrentEntry->Flink;
00372     }
00373 
00374     /* Loop the packet array to get everything
00375      * set up for return the packets to the miniport */
00376     for (i = 0; i < NumberOfPackets; i++)
00377     {
00378         /* First, check the initial packet status */
00379         if (NDIS_GET_PACKET_STATUS(PacketArray[i]) == NDIS_STATUS_RESOURCES)
00380         {
00381             /* The miniport driver gets it back immediately so nothing to do here */
00382             NDIS_DbgPrint(MID_TRACE, ("Miniport needs the packet back immediately\n"));
00383             continue;
00384         }
00385 
00386         /* Different behavior depending on whether it's serialized or not */
00387         if (Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
00388         {
00389             /* We need to check the reference count */
00390             if (PacketArray[i]->WrapperReserved[0] == 0)
00391             {
00392                 /* NOTE: Unlike serialized miniports, this is REQUIRED to be called for each
00393                  * packet received that can be reused immediately, it is not implied! */
00394                 Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ReturnPacketHandler(
00395                       Adapter->NdisMiniportBlock.MiniportAdapterContext,
00396                       PacketArray[i]);
00397                 NDIS_DbgPrint(MID_TRACE, ("Packet has been returned to miniport (Deserialized)\n"));
00398             }
00399             else
00400             {
00401                 /* Packet will be returned by the protocol's call to NdisReturnPackets */
00402                 NDIS_DbgPrint(MID_TRACE, ("Packet will be returned to miniport later (Deserialized)\n"));
00403             }
00404         }
00405         else
00406         {
00407             /* Check the reference count */
00408             if (PacketArray[i]->WrapperReserved[0] == 0)
00409             {
00410                 /* NDIS_STATUS_SUCCESS means the miniport can have the packet back immediately */
00411                 NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);
00412 
00413                 NDIS_DbgPrint(MID_TRACE, ("Packet has been returned to miniport (Serialized)\n"));
00414             }
00415             else
00416             {
00417                 /* NDIS_STATUS_PENDING means the miniport needs to wait for MiniportReturnPacket */
00418                 NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_PENDING);
00419 
00420                 NDIS_DbgPrint(MID_TRACE, ("Packet will be returned to miniport later (Serialized)\n"));
00421             }
00422         }
00423     }
00424 
00425     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
00426 }
00427 
00428 
00429 VOID NTAPI
00430 MiniResetComplete(
00431     IN  NDIS_HANDLE MiniportAdapterHandle,
00432     IN  NDIS_STATUS Status,
00433     IN  BOOLEAN     AddressingReset)
00434 {
00435     PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
00436     PLIST_ENTRY CurrentEntry;
00437     PADAPTER_BINDING AdapterBinding;
00438     KIRQL OldIrql;
00439 
00440     if (AddressingReset)
00441         MiniDoAddressingReset(Adapter);
00442 
00443     NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
00444     NdisMIndicateStatusComplete(Adapter);
00445 
00446     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
00447 
00448     if (Adapter->NdisMiniportBlock.ResetStatus != NDIS_STATUS_PENDING)
00449     {
00450         KeBugCheckEx(BUGCODE_ID_DRIVER,
00451                      (ULONG_PTR)MiniportAdapterHandle,
00452                      (ULONG_PTR)Status,
00453                      (ULONG_PTR)AddressingReset,
00454                      0);
00455     }
00456 
00457     Adapter->NdisMiniportBlock.ResetStatus = Status;
00458 
00459     CurrentEntry = Adapter->ProtocolListHead.Flink;
00460 
00461     while (CurrentEntry != &Adapter->ProtocolListHead)
00462     {
00463         AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
00464 
00465         (*AdapterBinding->ProtocolBinding->Chars.ResetCompleteHandler)(
00466                AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
00467                Status);
00468 
00469         CurrentEntry = CurrentEntry->Flink;
00470     }
00471 
00472     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
00473 }
00474 
00475 VOID NTAPI
00476 MiniRequestComplete(
00477     IN NDIS_HANDLE MiniportAdapterHandle,
00478     IN NDIS_STATUS Status)
00479 {
00480     PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
00481     PNDIS_REQUEST Request;
00482     PNDIS_REQUEST_MAC_BLOCK MacBlock;
00483     KIRQL OldIrql;
00484 
00485     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
00486 
00487     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00488 
00489     KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
00490     Request = Adapter->NdisMiniportBlock.PendingRequest;
00491     KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
00492 
00493     MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
00494 
00495     if( MacBlock->Binding->RequestCompleteHandler ) {
00496         (*MacBlock->Binding->RequestCompleteHandler)(
00497             MacBlock->Binding->ProtocolBindingContext,
00498             Request,
00499             Status);
00500     }
00501 
00502     KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
00503     Adapter->NdisMiniportBlock.PendingRequest = NULL;
00504     KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
00505 
00506     KeLowerIrql(OldIrql);
00507 }
00508 
00509 VOID NTAPI
00510 MiniSendComplete(
00511     IN  NDIS_HANDLE     MiniportAdapterHandle,
00512     IN  PNDIS_PACKET    Packet,
00513     IN  NDIS_STATUS     Status)
00514 /*
00515  * FUNCTION: Forwards a message to the initiating protocol saying
00516  *           that a packet was handled
00517  * ARGUMENTS:
00518  *     NdisAdapterHandle = Handle input to MiniportInitialize
00519  *     Packet            = Pointer to NDIS packet that was sent
00520  *     Status            = Status of send operation
00521  */
00522 {
00523     PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
00524     PADAPTER_BINDING AdapterBinding;
00525     KIRQL OldIrql;
00526     PSCATTER_GATHER_LIST SGList;
00527 
00528     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
00529 
00530     AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
00531 
00532     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00533 
00534     if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
00535     {
00536         NDIS_DbgPrint(MAX_TRACE, ("Freeing Scatter/Gather list\n"));
00537 
00538         SGList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
00539                                                   ScatterGatherListPacketInfo);
00540 
00541         Adapter->NdisMiniportBlock.SystemAdapterObject->
00542             DmaOperations->PutScatterGatherList(
00543                            Adapter->NdisMiniportBlock.SystemAdapterObject,
00544                            SGList,
00545                            TRUE);
00546 
00547         NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
00548                                          ScatterGatherListPacketInfo) = NULL;
00549     }
00550 
00551     (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
00552         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
00553         Packet,
00554         Status);
00555 
00556     KeLowerIrql(OldIrql);
00557 }
00558 
00559 
00560 VOID NTAPI
00561 MiniSendResourcesAvailable(
00562     IN  NDIS_HANDLE MiniportAdapterHandle)
00563 {
00564 /*
00565     UNIMPLEMENTED
00566 */
00567 }
00568 
00569 
00570 VOID NTAPI
00571 MiniTransferDataComplete(
00572     IN  NDIS_HANDLE     MiniportAdapterHandle,
00573     IN  PNDIS_PACKET    Packet,
00574     IN  NDIS_STATUS     Status,
00575     IN  UINT            BytesTransferred)
00576 {
00577     PADAPTER_BINDING AdapterBinding;
00578     KIRQL OldIrql;
00579 
00580     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
00581 
00582     AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
00583 
00584     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00585     (*AdapterBinding->ProtocolBinding->Chars.TransferDataCompleteHandler)(
00586         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
00587         Packet,
00588         Status,
00589         BytesTransferred);
00590     KeLowerIrql(OldIrql);
00591 }
00592 
00593 
00594 BOOLEAN
00595 MiniAdapterHasAddress(
00596     PLOGICAL_ADAPTER Adapter,
00597     PNDIS_PACKET Packet)
00598 /*
00599  * FUNCTION: Determines whether a packet has the same destination address as an adapter
00600  * ARGUMENTS:
00601  *     Adapter = Pointer to logical adapter object
00602  *     Packet  = Pointer to NDIS packet
00603  * RETURNS:
00604  *     TRUE if the destination address is that of the adapter, FALSE if not
00605  */
00606 {
00607     UINT Length;
00608     PUCHAR Start1;
00609     PUCHAR Start2;
00610     PNDIS_BUFFER NdisBuffer;
00611     UINT BufferLength;
00612 
00613     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
00614 
00615 #if DBG
00616     if(!Adapter)
00617     {
00618         NDIS_DbgPrint(MIN_TRACE, ("Adapter object was null\n"));
00619         return FALSE;
00620     }
00621 
00622     if(!Packet)
00623     {
00624         NDIS_DbgPrint(MIN_TRACE, ("Packet was null\n"));
00625         return FALSE;
00626     }
00627 #endif
00628 
00629     NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
00630 
00631     if (!NdisBuffer)
00632     {
00633         NDIS_DbgPrint(MIN_TRACE, ("Packet contains no buffers.\n"));
00634         return FALSE;
00635     }
00636 
00637     NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
00638 
00639     /* FIXME: Should handle fragmented packets */
00640 
00641     switch (Adapter->NdisMiniportBlock.MediaType)
00642     {
00643         case NdisMedium802_3:
00644             Length = ETH_LENGTH_OF_ADDRESS;
00645             /* Destination address is the first field */
00646             break;
00647 
00648         default:
00649             NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
00650             return FALSE;
00651     }
00652 
00653     if (BufferLength < Length)
00654     {
00655         NDIS_DbgPrint(MIN_TRACE, ("Buffer is too small.\n"));
00656         return FALSE;
00657     }
00658 
00659     Start1 = (PUCHAR)&Adapter->Address;
00660     NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
00661                               *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
00662                               *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5)));
00663 
00664     return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
00665 }
00666 
00667 
00668 PLOGICAL_ADAPTER
00669 MiniLocateDevice(
00670     PNDIS_STRING AdapterName)
00671 /*
00672  * FUNCTION: Finds an adapter object by name
00673  * ARGUMENTS:
00674  *     AdapterName = Pointer to name of adapter
00675  * RETURNS:
00676  *     Pointer to logical adapter object, or NULL if none was found.
00677  *     If found, the adapter is referenced for the caller. The caller
00678  *     is responsible for dereferencing after use
00679  */
00680 {
00681     KIRQL OldIrql;
00682     PLIST_ENTRY CurrentEntry;
00683     PLOGICAL_ADAPTER Adapter = 0;
00684 
00685     ASSERT(AdapterName);
00686 
00687     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
00688 
00689     if(IsListEmpty(&AdapterListHead))
00690     {
00691         NDIS_DbgPrint(MIN_TRACE, ("No registered miniports for protocol to bind to\n"));
00692         return NULL;
00693     }
00694 
00695     NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
00696 
00697     KeAcquireSpinLock(&AdapterListLock, &OldIrql);
00698     {
00699         CurrentEntry = AdapterListHead.Flink;
00700         
00701         while (CurrentEntry != &AdapterListHead)
00702         {
00703             Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
00704 
00705             ASSERT(Adapter);
00706 
00707             NDIS_DbgPrint(DEBUG_MINIPORT, ("Examining adapter 0x%lx\n", Adapter));
00708 
00709             /* We're technically not allowed to call this above PASSIVE_LEVEL, but it doesn't break
00710              * right now and I'd rather use a working API than reimplement it here */
00711             if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
00712             {
00713                 break;
00714             }
00715 
00716             Adapter = NULL;
00717             CurrentEntry = CurrentEntry->Flink;
00718         }
00719     }
00720     KeReleaseSpinLock(&AdapterListLock, OldIrql);
00721 
00722     if(Adapter)
00723     {
00724         NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
00725     }
00726     else
00727     {
00728         NDIS_DbgPrint(MIN_TRACE, ("Leaving (adapter not found for %wZ).\n", AdapterName));
00729     }
00730 
00731     return Adapter;
00732 }
00733 
00734 NDIS_STATUS
00735 MiniSetInformation(
00736     PLOGICAL_ADAPTER    Adapter,
00737     NDIS_OID            Oid,
00738     ULONG               Size,
00739     PVOID               Buffer,
00740     PULONG              BytesRead)
00741 {
00742   NDIS_STATUS NdisStatus;
00743   PNDIS_REQUEST NdisRequest;
00744 
00745   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
00746 
00747   NdisRequest = ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
00748   if (!NdisRequest) {
00749       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00750       return NDIS_STATUS_RESOURCES;
00751   }
00752 
00753   RtlZeroMemory(NdisRequest, sizeof(NDIS_REQUEST));
00754 
00755   NdisRequest->RequestType = NdisRequestSetInformation;
00756   NdisRequest->DATA.SET_INFORMATION.Oid = Oid;
00757   NdisRequest->DATA.SET_INFORMATION.InformationBuffer = Buffer;
00758   NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = Size;
00759 
00760   NdisStatus = MiniDoRequest(Adapter, NdisRequest);
00761 
00762   /* FIXME: Wait in pending case! */
00763 
00764   ASSERT(NdisStatus != NDIS_STATUS_PENDING);
00765 
00766   *BytesRead = NdisRequest->DATA.SET_INFORMATION.BytesRead;
00767 
00768   ExFreePool(NdisRequest);
00769 
00770   return NdisStatus;
00771 }
00772 
00773 NDIS_STATUS
00774 MiniQueryInformation(
00775     PLOGICAL_ADAPTER    Adapter,
00776     NDIS_OID            Oid,
00777     ULONG               Size,
00778     PVOID               Buffer,
00779     PULONG              BytesWritten)
00780 /*
00781  * FUNCTION: Queries a logical adapter for properties
00782  * ARGUMENTS:
00783  *     Adapter      = Pointer to the logical adapter object to query
00784  *     Oid          = Specifies the Object ID to query for
00785  *     Size         = Size of the passed buffer
00786  *     Buffer       = Buffer for the output
00787  *     BytesWritten = Address of buffer to place number of bytes written
00788  * RETURNS:
00789  *     Status of operation
00790  */
00791 {
00792   NDIS_STATUS NdisStatus;
00793   PNDIS_REQUEST NdisRequest;
00794 
00795   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
00796 
00797   NdisRequest = ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
00798   if (!NdisRequest) {
00799       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00800       return NDIS_STATUS_RESOURCES;
00801   }
00802 
00803   RtlZeroMemory(NdisRequest, sizeof(NDIS_REQUEST));
00804 
00805   NdisRequest->RequestType = NdisRequestQueryInformation;
00806   NdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
00807   NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
00808   NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size;
00809 
00810   NdisStatus = MiniDoRequest(Adapter, NdisRequest);
00811 
00812   /* FIXME: Wait in pending case! */
00813 
00814   ASSERT(NdisStatus != NDIS_STATUS_PENDING);
00815 
00816   *BytesWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
00817 
00818   ExFreePool(NdisRequest);
00819 
00820   return NdisStatus;
00821 }
00822 
00823 BOOLEAN
00824 MiniCheckForHang( PLOGICAL_ADAPTER Adapter )
00825 /*
00826  * FUNCTION: Checks to see if the miniport is hung
00827  * ARGUMENTS:
00828  *     Adapter = Pointer to the logical adapter object
00829  * RETURNS:
00830  *     TRUE if the miniport is hung
00831  *     FALSE if the miniport is not hung
00832  */
00833 {
00834    BOOLEAN Ret = FALSE;
00835    KIRQL OldIrql;
00836 
00837    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00838    if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)
00839        Ret = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)(
00840          Adapter->NdisMiniportBlock.MiniportAdapterContext);
00841    KeLowerIrql(OldIrql);
00842 
00843    return Ret;
00844 }
00845 
00846 VOID
00847 MiniDoAddressingReset(PLOGICAL_ADAPTER Adapter)
00848 {
00849    ULONG BytesRead;
00850 
00851    MiniSetInformation(Adapter,
00852                       OID_GEN_CURRENT_LOOKAHEAD,
00853                       sizeof(ULONG),
00854                       &Adapter->NdisMiniportBlock.CurrentLookahead,
00855                       &BytesRead);
00856 
00857    /* FIXME: Set more stuff */
00858 }
00859 
00860 NDIS_STATUS
00861 MiniReset(
00862     PLOGICAL_ADAPTER Adapter)
00863 /*
00864  * FUNCTION: Resets the miniport
00865  * ARGUMENTS:
00866  *     Adapter = Pointer to the logical adapter object
00867  * RETURNS:
00868  *     Status of the operation
00869  */
00870 {
00871    NDIS_STATUS Status;
00872    KIRQL OldIrql;
00873    BOOLEAN AddressingReset = TRUE;
00874 
00875    if (MiniIsBusy(Adapter, NdisWorkItemResetRequested)) {
00876        MiniQueueWorkItem(Adapter, NdisWorkItemResetRequested, NULL, FALSE);
00877        return NDIS_STATUS_PENDING;
00878    }
00879 
00880    NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
00881    NdisMIndicateStatusComplete(Adapter);
00882 
00883    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00884    Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
00885             Adapter->NdisMiniportBlock.MiniportAdapterContext,
00886             &AddressingReset);
00887 
00888    KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
00889    Adapter->NdisMiniportBlock.ResetStatus = Status;
00890    KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
00891 
00892    KeLowerIrql(OldIrql);
00893 
00894    if (Status != NDIS_STATUS_PENDING) {
00895        if (AddressingReset)
00896            MiniDoAddressingReset(Adapter);
00897 
00898        NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
00899        NdisMIndicateStatusComplete(Adapter);
00900    }
00901 
00902    return Status;
00903 }
00904 
00905 VOID NTAPI
00906 MiniportHangDpc(
00907         PKDPC Dpc,
00908         PVOID DeferredContext,
00909         PVOID SystemArgument1,
00910         PVOID SystemArgument2)
00911 {
00912   PLOGICAL_ADAPTER Adapter = DeferredContext;
00913 
00914   if (MiniCheckForHang(Adapter)) {
00915       NDIS_DbgPrint(MIN_TRACE, ("Miniport detected adapter hang\n"));
00916       MiniReset(Adapter);
00917   }
00918 }
00919 
00920 
00921 VOID
00922 FASTCALL
00923 MiniQueueWorkItem(
00924     PLOGICAL_ADAPTER     Adapter,
00925     NDIS_WORK_ITEM_TYPE  WorkItemType,
00926     PVOID                WorkItemContext,
00927     BOOLEAN              Top)
00928 /*
00929  * FUNCTION: Queues a work item for execution at a later time
00930  * ARGUMENTS:
00931  *     Adapter         = Pointer to the logical adapter object to queue work item on
00932  *     WorkItemType    = Type of work item to queue
00933  *     WorkItemContext = Pointer to context information for work item
00934  * RETURNS:
00935  *     Status of operation
00936  */
00937 {
00938     PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
00939     PIO_WORKITEM IoWorkItem;
00940     KIRQL OldIrql;
00941 
00942     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00943 
00944     ASSERT(Adapter);
00945 
00946     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
00947     if (Top)
00948     {
00949         if (WorkItemType == NdisWorkItemSend)
00950         {
00951             NDIS_DbgPrint(MIN_TRACE, ("Requeuing failed packet (%x).\n", WorkItemContext));
00952             Adapter->NdisMiniportBlock.FirstPendingPacket = WorkItemContext;
00953         }
00954         else
00955         {
00956             //This should never happen
00957             ASSERT(FALSE);
00958         }
00959     }
00960     else
00961     {
00962         MiniportWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
00963         if (!MiniportWorkItem)
00964         {
00965             KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
00966             NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00967             return;
00968         }
00969 
00970         MiniportWorkItem->WorkItemType    = WorkItemType;
00971         MiniportWorkItem->WorkItemContext = WorkItemContext;
00972 
00973         /* safe due to adapter lock held */
00974         MiniportWorkItem->Link.Next = NULL;
00975         if (!Adapter->WorkQueueHead)
00976         {
00977             Adapter->WorkQueueHead = MiniportWorkItem;
00978             Adapter->WorkQueueTail = MiniportWorkItem;
00979         }
00980         else
00981         {
00982             Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)MiniportWorkItem;
00983             Adapter->WorkQueueTail = MiniportWorkItem;
00984         }
00985     }
00986 
00987     IoWorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
00988     if (IoWorkItem)
00989         IoQueueWorkItem(IoWorkItem, MiniportWorker, DelayedWorkQueue, IoWorkItem);
00990 
00991     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
00992 }
00993 
00994 
00995 NDIS_STATUS
00996 FASTCALL
00997 MiniDequeueWorkItem(
00998     PLOGICAL_ADAPTER    Adapter,
00999     NDIS_WORK_ITEM_TYPE *WorkItemType,
01000     PVOID               *WorkItemContext)
01001 /*
01002  * FUNCTION: Dequeues a work item from the work queue of a logical adapter
01003  * ARGUMENTS:
01004  *     Adapter         = Pointer to the logical adapter object to dequeue work item from
01005  *     AdapterBinding  = Address of buffer for adapter binding for this request
01006  *     WorkItemType    = Address of buffer for work item type
01007  *     WorkItemContext = Address of buffer for pointer to context information
01008  * NOTES:
01009  *     Adapter lock must be held when called
01010  * RETURNS:
01011  *     Status of operation
01012  */
01013 {
01014     PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
01015     PNDIS_PACKET Packet;
01016 
01017     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
01018 
01019     MiniportWorkItem = Adapter->WorkQueueHead;
01020 
01021     if ((Packet = Adapter->NdisMiniportBlock.FirstPendingPacket))
01022     {
01023         Adapter->NdisMiniportBlock.FirstPendingPacket = NULL;
01024 
01025         *WorkItemType = NdisWorkItemSend;
01026         *WorkItemContext = Packet;
01027 
01028         return NDIS_STATUS_SUCCESS;
01029     }
01030     else if (MiniportWorkItem)
01031     {
01032         /* safe due to adapter lock held */
01033         Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)MiniportWorkItem->Link.Next;
01034 
01035         if (MiniportWorkItem == Adapter->WorkQueueTail)
01036             Adapter->WorkQueueTail = NULL;
01037 
01038         *WorkItemType    = MiniportWorkItem->WorkItemType;
01039         *WorkItemContext = MiniportWorkItem->WorkItemContext;
01040 
01041         ExFreePool(MiniportWorkItem);
01042 
01043         return NDIS_STATUS_SUCCESS;
01044     }
01045     else
01046     {
01047         NDIS_DbgPrint(MIN_TRACE, ("No work item to dequeue\n"));
01048 
01049         return NDIS_STATUS_FAILURE;
01050     }
01051 }
01052 
01053 
01054 NDIS_STATUS
01055 MiniDoRequest(
01056     PLOGICAL_ADAPTER Adapter,
01057     PNDIS_REQUEST NdisRequest)
01058 /*
01059  * FUNCTION: Sends a request to a miniport
01060  * ARGUMENTS:
01061  *     AdapterBinding = Pointer to binding used in the request
01062  *     NdisRequest    = Pointer to NDIS request structure describing request
01063  * RETURNS:
01064  *     Status of operation
01065  */
01066 {
01067     NDIS_STATUS Status;
01068     KIRQL OldIrql;
01069     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
01070 
01071     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
01072 
01073     KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
01074     Adapter->NdisMiniportBlock.PendingRequest = NdisRequest;
01075     KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
01076 
01077     if (!Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)
01078     {
01079         switch (NdisRequest->RequestType)
01080         {
01081         case NdisRequestQueryInformation:
01082             Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
01083                 Adapter->NdisMiniportBlock.MiniportAdapterContext,
01084                 NdisRequest->DATA.QUERY_INFORMATION.Oid,
01085                 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
01086                 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
01087                 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
01088                 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
01089             break;
01090 
01091         case NdisRequestSetInformation:
01092             Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SetInformationHandler)(
01093                 Adapter->NdisMiniportBlock.MiniportAdapterContext,
01094                 NdisRequest->DATA.SET_INFORMATION.Oid,
01095                 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
01096                 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
01097                 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
01098                 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
01099             break;
01100 
01101         default:
01102             NDIS_DbgPrint(MIN_TRACE, ("Bad request type\n"));
01103             Status = NDIS_STATUS_FAILURE;
01104         }
01105     }
01106     else
01107     {
01108         Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)(
01109             Adapter->NdisMiniportBlock.MiniportAdapterContext,
01110             NULL, /* FIXME */
01111             NdisRequest);
01112     }
01113 
01114     if (Status != NDIS_STATUS_PENDING) {
01115         KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
01116         Adapter->NdisMiniportBlock.PendingRequest = NULL;
01117         KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
01118     }
01119 
01120     KeLowerIrql(OldIrql);
01121     return Status;
01122 }
01123 
01124 
01125 /*
01126  * @implemented
01127  */
01128 #undef NdisMSetInformationComplete
01129 VOID
01130 EXPORT
01131 NdisMSetInformationComplete(
01132     IN  NDIS_HANDLE MiniportAdapterHandle,
01133     IN  NDIS_STATUS Status)
01134 {
01135   PLOGICAL_ADAPTER Adapter =
01136     (PLOGICAL_ADAPTER)MiniportAdapterHandle;
01137   KIRQL OldIrql;
01138   ASSERT(Adapter);
01139   KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
01140   if (Adapter->NdisMiniportBlock.SetCompleteHandler)
01141      (Adapter->NdisMiniportBlock.SetCompleteHandler)(MiniportAdapterHandle, Status);
01142   KeLowerIrql(OldIrql);
01143 }
01144 
01145 
01146 /*
01147  * @implemented
01148  */
01149 #undef NdisMQueryInformationComplete
01150 VOID
01151 EXPORT
01152 NdisMQueryInformationComplete(
01153     IN  NDIS_HANDLE MiniportAdapterHandle,
01154     IN  NDIS_STATUS Status)
01155 {
01156     PLOGICAL_ADAPTER Adapter =
01157     (PLOGICAL_ADAPTER)MiniportAdapterHandle;
01158     KIRQL OldIrql;
01159     ASSERT(Adapter);
01160     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
01161     if( Adapter->NdisMiniportBlock.QueryCompleteHandler )
01162     (Adapter->NdisMiniportBlock.QueryCompleteHandler)(MiniportAdapterHandle, Status);
01163     KeLowerIrql(OldIrql);
01164 }
01165 
01166 VOID
01167 NTAPI
01168 MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
01169 {
01170   PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
01171   KIRQL OldIrql, RaiseOldIrql;
01172   NDIS_STATUS NdisStatus;
01173   PVOID WorkItemContext;
01174   NDIS_WORK_ITEM_TYPE WorkItemType;
01175   BOOLEAN AddressingReset;
01176 
01177   IoFreeWorkItem((PIO_WORKITEM)Context);
01178 
01179   KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
01180 
01181   NdisStatus =
01182       MiniDequeueWorkItem
01183       (Adapter, &WorkItemType, &WorkItemContext);
01184 
01185   KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
01186 
01187   if (NdisStatus == NDIS_STATUS_SUCCESS)
01188     {
01189       switch (WorkItemType)
01190         {
01191           case NdisWorkItemSend:
01192             /*
01193              * called by ProSend when protocols want to send packets to the miniport
01194              */
01195 
01196             if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
01197               {
01198                 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
01199                 {
01200                     NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
01201                     (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
01202                      Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
01203                     NdisStatus = NDIS_STATUS_PENDING;
01204                 }
01205                 else
01206                 {
01207                     /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
01208                     KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
01209                     {
01210                       NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
01211                       (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
01212                        Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
01213                     }
01214                     KeLowerIrql(RaiseOldIrql);
01215 
01216                     NdisStatus = NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
01217                     if( NdisStatus == NDIS_STATUS_RESOURCES ) {
01218                         MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext, TRUE);
01219                         break;
01220                     }
01221                 }
01222               }
01223             else
01224               {
01225                 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
01226                 {
01227                   NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
01228                   NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
01229                                 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext,
01230                                 ((PNDIS_PACKET)WorkItemContext)->Private.Flags);
01231                   NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
01232                 }
01233                 else
01234                 {
01235                   /* Send is called at DISPATCH_LEVEL for all serialized miniports */
01236                   KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
01237                   NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
01238                   NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
01239                                 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext,
01240                                 ((PNDIS_PACKET)WorkItemContext)->Private.Flags);
01241                   NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
01242                   KeLowerIrql(RaiseOldIrql);
01243                   if( NdisStatus == NDIS_STATUS_RESOURCES ) {
01244                       MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext, TRUE);
01245                       break;
01246                   }
01247                 }
01248               }
01249 
01250         if( NdisStatus != NDIS_STATUS_PENDING ) {
01251         MiniSendComplete
01252             ( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
01253         }
01254             break;
01255 
01256           case NdisWorkItemSendLoopback:
01257             /*
01258              * called by ProSend when protocols want to send loopback packets
01259              */
01260             /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
01261             NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
01262 
01263             if( NdisStatus != NDIS_STATUS_PENDING )
01264                 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
01265             break;
01266 
01267           case NdisWorkItemReturnPackets:
01268             break;
01269 
01270           case NdisWorkItemResetRequested:
01271             NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
01272             NdisMIndicateStatusComplete(Adapter);
01273 
01274             KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
01275             NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
01276                           Adapter->NdisMiniportBlock.MiniportAdapterContext,
01277                           &AddressingReset);
01278 
01279             KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
01280             Adapter->NdisMiniportBlock.ResetStatus = NdisStatus;
01281             KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
01282 
01283             KeLowerIrql(OldIrql);
01284 
01285             if (NdisStatus != NDIS_STATUS_PENDING)
01286                MiniResetComplete(Adapter, NdisStatus, AddressingReset);
01287             break;
01288 
01289           case NdisWorkItemResetInProgress:
01290             break;
01291 
01292           case NdisWorkItemMiniportCallback:
01293             break;
01294 
01295           case NdisWorkItemRequest:
01296             NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
01297 
01298             if (NdisStatus == NDIS_STATUS_PENDING)
01299               break;
01300 
01301             switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
01302               {
01303                 case NdisRequestQueryInformation:
01304           NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
01305                   break;
01306 
01307                 case NdisRequestSetInformation:
01308                   NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
01309                   break;
01310 
01311                 default:
01312                   NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
01313                   break;
01314               }
01315             break;
01316 
01317           default:
01318             NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
01319             break;
01320         }
01321     }
01322 }
01323 
01324 
01325 
01326 VOID
01327 NTAPI
01328 MiniStatus(
01329     IN NDIS_HANDLE  MiniportHandle,
01330     IN NDIS_STATUS  GeneralStatus,
01331     IN PVOID  StatusBuffer,
01332     IN UINT  StatusBufferSize)
01333 {
01334     PLOGICAL_ADAPTER Adapter = MiniportHandle;
01335     PLIST_ENTRY CurrentEntry;
01336     PADAPTER_BINDING AdapterBinding;
01337     KIRQL OldIrql;
01338 
01339     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
01340 
01341     CurrentEntry = Adapter->ProtocolListHead.Flink;
01342 
01343     while (CurrentEntry != &Adapter->ProtocolListHead)
01344     {
01345        AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
01346 
01347        (*AdapterBinding->ProtocolBinding->Chars.StatusHandler)(
01348            AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
01349            GeneralStatus,
01350            StatusBuffer,
01351            StatusBufferSize);
01352 
01353        CurrentEntry = CurrentEntry->Flink;
01354     }
01355 
01356     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
01357 }
01358 
01359 
01360 VOID
01361 NTAPI
01362 MiniStatusComplete(
01363     IN NDIS_HANDLE  MiniportAdapterHandle)
01364 {
01365     PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
01366     PLIST_ENTRY CurrentEntry;
01367     PADAPTER_BINDING AdapterBinding;
01368     KIRQL OldIrql;
01369 
01370     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
01371 
01372     CurrentEntry = Adapter->ProtocolListHead.Flink;
01373 
01374     while (CurrentEntry != &Adapter->ProtocolListHead)
01375     {
01376        AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
01377 
01378        (*AdapterBinding->ProtocolBinding->Chars.StatusCompleteHandler)(
01379            AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
01380 
01381        CurrentEntry = CurrentEntry->Flink;
01382     }
01383 
01384     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
01385 }
01386 
01387 
01388 /*
01389  * @implemented
01390  */
01391 VOID
01392 EXPORT
01393 NdisMCloseLog(
01394     IN  NDIS_HANDLE LogHandle)
01395 {
01396     PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
01397     PNDIS_MINIPORT_BLOCK Miniport = Log->Miniport;
01398     KIRQL OldIrql;
01399 
01400     NDIS_DbgPrint(MAX_TRACE, ("called: LogHandle 0x%x\n", LogHandle));
01401 
01402     KeAcquireSpinLock(&(Miniport)->Lock, &OldIrql);
01403     Miniport->Log = NULL;
01404     KeReleaseSpinLock(&(Miniport)->Lock, OldIrql);
01405 
01406     ExFreePool(Log);
01407 }
01408 
01409 /*
01410  * @implemented
01411  */
01412 NDIS_STATUS
01413 EXPORT
01414 NdisMCreateLog(
01415     IN  NDIS_HANDLE     MiniportAdapterHandle,
01416     IN  UINT            Size,
01417     OUT PNDIS_HANDLE    LogHandle)
01418 {
01419     PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
01420     PNDIS_LOG Log;
01421     KIRQL OldIrql;
01422 
01423     NDIS_DbgPrint(MAX_TRACE, ("called: MiniportAdapterHandle 0x%x, Size %ld\n", MiniportAdapterHandle, Size));
01424 
01425     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
01426 
01427     if (Adapter->NdisMiniportBlock.Log)
01428     {
01429         *LogHandle = NULL;
01430         return NDIS_STATUS_FAILURE;
01431     }
01432 
01433     Log = ExAllocatePool(NonPagedPool, Size + sizeof(NDIS_LOG));
01434     if (!Log)
01435     {
01436         *LogHandle = NULL;
01437         return NDIS_STATUS_RESOURCES;
01438     }
01439 
01440     Adapter->NdisMiniportBlock.Log = Log;
01441 
01442     KeInitializeSpinLock(&Log->LogLock);
01443 
01444     Log->Miniport = &Adapter->NdisMiniportBlock;
01445     Log->TotalSize = Size;
01446     Log->CurrentSize = 0;
01447     Log->OutPtr = 0;
01448     Log->InPtr = 0;
01449     Log->Irp = NULL;
01450 
01451     *LogHandle = Log;
01452 
01453     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
01454 
01455     return NDIS_STATUS_SUCCESS;
01456 }
01457 
01458 /*
01459  * @implemented
01460  */
01461 VOID
01462 EXPORT
01463 NdisMDeregisterAdapterShutdownHandler(
01464     IN  NDIS_HANDLE MiniportHandle)
01465 /*
01466  * FUNCTION: de-registers a shutdown handler
01467  * ARGUMENTS:  MiniportHandle:  Handle passed into MiniportInitialize
01468  */
01469 {
01470   PLOGICAL_ADAPTER  Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
01471 
01472   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
01473 
01474   if(Adapter->BugcheckContext->ShutdownHandler) {
01475     KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
01476     IoUnregisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
01477   }
01478 }
01479 
01480 /*
01481  * @implemented
01482  */
01483 VOID
01484 EXPORT
01485 NdisMFlushLog(
01486     IN  NDIS_HANDLE LogHandle)
01487 {
01488     PNDIS_LOG Log = (PNDIS_LOG) LogHandle;
01489     KIRQL OldIrql;
01490 
01491     NDIS_DbgPrint(MAX_TRACE, ("called: LogHandle 0x%x\n", LogHandle));
01492 
01493     /* Lock object */
01494     KeAcquireSpinLock(&Log->LogLock, &OldIrql);
01495 
01496     /* Set buffers size */
01497     Log->CurrentSize = 0;
01498     Log->OutPtr = 0;
01499     Log->InPtr = 0;
01500 
01501     /* Unlock object */
01502     KeReleaseSpinLock(&Log->LogLock, OldIrql);
01503 }
01504 
01505 /*
01506  * @implemented
01507  */
01508 #undef NdisMIndicateStatus
01509 VOID
01510 EXPORT
01511 NdisMIndicateStatus(
01512     IN  NDIS_HANDLE MiniportAdapterHandle,
01513     IN  NDIS_STATUS GeneralStatus,
01514     IN  PVOID       StatusBuffer,
01515     IN  UINT        StatusBufferSize)
01516 {
01517     MiniStatus(MiniportAdapterHandle, GeneralStatus, StatusBuffer, StatusBufferSize);
01518 }
01519 
01520 /*
01521  * @implemented
01522  */
01523 #undef NdisMIndicateStatusComplete
01524 VOID
01525 EXPORT
01526 NdisMIndicateStatusComplete(
01527     IN  NDIS_HANDLE MiniportAdapterHandle)
01528 {
01529     MiniStatusComplete(MiniportAdapterHandle);
01530 }
01531 
01532 
01533 /*
01534  * @implemented
01535  */
01536 VOID
01537 EXPORT
01538 NdisInitializeWrapper(
01539     OUT PNDIS_HANDLE    NdisWrapperHandle,
01540     IN  PVOID           SystemSpecific1,
01541     IN  PVOID           SystemSpecific2,
01542     IN  PVOID           SystemSpecific3)
01543 /*
01544  * FUNCTION: Notifies the NDIS library that a new miniport is initializing
01545  * ARGUMENTS:
01546  *     NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
01547  *     SystemSpecific1   = Pointer to the driver's driver object
01548  *     SystemSpecific2   = Pointer to the driver's registry path
01549  *     SystemSpecific3   = Always NULL
01550  * NOTES:
01551  *     - SystemSpecific2 goes invalid so we copy it
01552  */
01553 {
01554   PNDIS_M_DRIVER_BLOCK Miniport;
01555   PUNICODE_STRING RegistryPath;
01556   WCHAR *RegistryBuffer;
01557 
01558   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
01559 
01560   ASSERT(NdisWrapperHandle);
01561 
01562   *NdisWrapperHandle = NULL;
01563 
01564 #if BREAK_ON_MINIPORT_INIT
01565   DbgBreakPoint();
01566 #endif
01567 
01568   Miniport = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DRIVER_BLOCK));
01569 
01570   if (!Miniport)
01571     {
01572       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01573       return;
01574     }
01575 
01576   RtlZeroMemory(Miniport, sizeof(NDIS_M_DRIVER_BLOCK));
01577 
01578   KeInitializeSpinLock(&Miniport->Lock);
01579 
01580   Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
01581 
01582   /* set the miniport's driver registry path */
01583   RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
01584   if(!RegistryPath)
01585     {
01586       ExFreePool(Miniport);
01587       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01588       return;
01589     }
01590 
01591   RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
01592   RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR);   /* room for 0-term */
01593 
01594   RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
01595   if(!RegistryBuffer)
01596     {
01597       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01598       ExFreePool(Miniport);
01599       ExFreePool(RegistryPath);
01600       return;
01601     }
01602 
01603   RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
01604   RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
01605 
01606   RegistryPath->Buffer = RegistryBuffer;
01607   Miniport->RegistryPath = RegistryPath;
01608 
01609   InitializeListHead(&Miniport->DeviceList);
01610 
01611   /* Put miniport in global miniport list */
01612   ExInterlockedInsertTailList(&MiniportListHead, &Miniport->ListEntry, &MiniportListLock);
01613 
01614   *NdisWrapperHandle = Miniport;
01615 }
01616 
01617 
01618 VOID NTAPI NdisIBugcheckCallback(
01619     IN PVOID   Buffer,
01620     IN ULONG   Length)
01621 /*
01622  * FUNCTION:  Internal callback for handling bugchecks - calls adapter's shutdown handler
01623  * ARGUMENTS:
01624  *     Buffer:  Pointer to a bugcheck callback context
01625  *     Length:  Unused
01626  */
01627 {
01628   PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
01629   ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
01630 
01631    NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
01632 
01633   if(sh)
01634     sh(Context->DriverContext);
01635 }
01636 
01637 
01638 /*
01639  * @implemented
01640  */
01641 VOID
01642 EXPORT
01643 NdisMRegisterAdapterShutdownHandler(
01644     IN  NDIS_HANDLE                 MiniportHandle,
01645     IN  PVOID                       ShutdownContext,
01646     IN  ADAPTER_SHUTDOWN_HANDLER    ShutdownHandler)
01647 /*
01648  * FUNCTION:  Register a shutdown handler for an adapter
01649  * ARGUMENTS:
01650  *     MiniportHandle:  Handle originally passed into MiniportInitialize
01651  *     ShutdownContext:  Pre-initialized bugcheck context
01652  *     ShutdownHandler:  Function to call to handle the bugcheck
01653  * NOTES:
01654  *     - I'm not sure about ShutdownContext
01655  */
01656 {
01657   PLOGICAL_ADAPTER            Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
01658   PMINIPORT_BUGCHECK_CONTEXT  BugcheckContext;
01659 
01660   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
01661 
01662   BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
01663   if(!BugcheckContext)
01664     {
01665       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01666       return;
01667     }
01668 
01669   BugcheckContext->ShutdownHandler = ShutdownHandler;
01670   BugcheckContext->DriverContext = ShutdownContext;
01671 
01672   BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
01673   if (!BugcheckContext->CallbackRecord) {
01674       ExFreePool(BugcheckContext);
01675       return;
01676   }
01677 
01678   Adapter->BugcheckContext = BugcheckContext;
01679 
01680   KeInitializeCallbackRecord(BugcheckContext->CallbackRecord);
01681 
01682   KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
01683       BugcheckContext, sizeof(*BugcheckContext), (PUCHAR)"Ndis Miniport");
01684 
01685   IoRegisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
01686 }
01687 
01688 
01689 NDIS_STATUS
01690 DoQueries(
01691     PLOGICAL_ADAPTER Adapter,
01692     NDIS_OID AddressOID)
01693 /*
01694  * FUNCTION: Queries miniport for information
01695  * ARGUMENTS:
01696  *     Adapter    = Pointer to logical adapter
01697  *     AddressOID = OID to use to query for current address
01698  * RETURNS:
01699  *     Status of operation
01700  */
01701 {
01702   ULONG BytesWritten;
01703   NDIS_STATUS NdisStatus;
01704 
01705   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
01706 
01707   /* Get MAC options for adapter */
01708   NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, sizeof(UINT),
01709                                     &Adapter->NdisMiniportBlock.MacOptions,
01710                                     &BytesWritten);
01711 
01712   if (NdisStatus != NDIS_STATUS_SUCCESS)
01713     {
01714       NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
01715       return NdisStatus;
01716     }
01717 
01718   NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
01719 
01720   /* Get current hardware address of adapter */
01721   NdisStatus = MiniQueryInformation(Adapter, AddressOID, Adapter->AddressLength,
01722                                     &Adapter->Address, &BytesWritten);
01723 
01724   if (NdisStatus != NDIS_STATUS_SUCCESS)
01725     {
01726       NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
01727       return NdisStatus;
01728     }
01729 
01730 #if DBG
01731     {
01732       /* 802.3 only */
01733 
01734       PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
01735 
01736       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]));
01737     }
01738 #endif /* DBG */
01739 
01740   /* Get maximum lookahead buffer size of adapter */
01741   NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, sizeof(ULONG),
01742                                     &Adapter->NdisMiniportBlock.MaximumLookahead, &BytesWritten);
01743 
01744   if (NdisStatus != NDIS_STATUS_SUCCESS)
01745     {
01746       NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
01747       return NdisStatus;
01748     }
01749 
01750   NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.MaximumLookahead));
01751 
01752   /* Get current lookahead buffer size of adapter */
01753   NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, sizeof(ULONG),
01754                                     &Adapter->NdisMiniportBlock.CurrentLookahead, &BytesWritten);
01755 
01756   if (NdisStatus != NDIS_STATUS_SUCCESS)
01757     {
01758       NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
01759       return NdisStatus;
01760     }
01761 
01762   NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_SEND_PACKETS, sizeof(ULONG),
01763                                     &Adapter->NdisMiniportBlock.MaxSendPackets, &BytesWritten);
01764 
01765   if (NdisStatus != NDIS_STATUS_SUCCESS)
01766     {
01767       NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus));
01768 
01769       /* Set it to 1 if it fails because some drivers don't support this (?)*/
01770       Adapter->NdisMiniportBlock.MaxSendPackets = 1;
01771     }
01772 
01773   NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
01774 
01775   return STATUS_SUCCESS;
01776 }
01777 
01778 
01779 NTSTATUS
01780 NTAPI
01781 NdisIForwardIrpAndWaitCompletionRoutine(
01782     PDEVICE_OBJECT Fdo,
01783     PIRP Irp,
01784     PVOID Context)
01785 {
01786   PKEVENT Event = Context;
01787 
01788   if (Irp->PendingReturned)
01789     KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
01790 
01791   return STATUS_MORE_PROCESSING_REQUIRED;
01792 }
01793 
01794 
01795 NTSTATUS
01796 NTAPI
01797 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter, PIRP Irp)
01798 {
01799   KEVENT Event;
01800   NTSTATUS Status;
01801 
01802   KeInitializeEvent(&Event, NotificationEvent, FALSE);
01803   IoCopyCurrentIrpStackLocationToNext(Irp);
01804   IoSetCompletionRoutine(Irp, NdisIForwardIrpAndWaitCompletionRoutine, &Event,
01805                          TRUE, TRUE, TRUE);
01806   Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
01807   if (Status == STATUS_PENDING)
01808     {
01809       KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
01810       Status = Irp->IoStatus.Status;
01811     }
01812   return Status;
01813 }
01814 
01815 NTSTATUS
01816 NTAPI
01817 NdisICreateClose(
01818     IN PDEVICE_OBJECT DeviceObject,
01819     IN PIRP Irp)
01820 {
01821   Irp->IoStatus.Status = STATUS_SUCCESS;
01822   Irp->IoStatus.Information = 0;
01823 
01824   IoCompleteRequest(Irp, IO_NO_INCREMENT);
01825 
01826   return STATUS_SUCCESS;
01827 }
01828 
01829 
01830 NTSTATUS
01831 NTAPI
01832 NdisIPnPStartDevice(
01833     IN PDEVICE_OBJECT DeviceObject,
01834     PIRP Irp)
01835 /*
01836  * FUNCTION: Handle the PnP start device event
01837  * ARGUMENTS:
01838  *     DeviceObejct = Functional Device Object
01839  *     Irp          = IRP_MN_START_DEVICE I/O request packet
01840  * RETURNS:
01841  *     Status of operation
01842  */
01843 {
01844   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
01845   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
01846   NDIS_WRAPPER_CONTEXT WrapperContext;
01847   NDIS_STATUS NdisStatus;
01848   NDIS_STATUS OpenErrorStatus;
01849   NTSTATUS Status;
01850   UINT SelectedMediumIndex = 0;
01851   NDIS_OID AddressOID;
01852   BOOLEAN Success = FALSE;
01853   ULONG ResourceCount;
01854   ULONG ResourceListSize;
01855   UNICODE_STRING ParamName;
01856   PNDIS_CONFIGURATION_PARAMETER ConfigParam;
01857   NDIS_HANDLE ConfigHandle;
01858   ULONG Size;
01859   LARGE_INTEGER Timeout;
01860   UINT MaxMulticastAddresses;
01861   ULONG BytesWritten;
01862   PLIST_ENTRY CurrentEntry;
01863   PPROTOCOL_BINDING ProtocolBinding;
01864 
01865   /*
01866    * Prepare wrapper context used by HW and configuration routines.
01867    */
01868 
01869   NDIS_DbgPrint(DEBUG_MINIPORT, ("Start Device %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
01870 
01871   NDIS_DbgPrint(MAX_TRACE, ("Inserting adapter 0x%x into adapter list\n", Adapter));
01872 
01873   /* Put adapter in global adapter list */
01874   ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
01875 
01876   Status = IoOpenDeviceRegistryKey(
01877     Adapter->NdisMiniportBlock.PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
01878     KEY_ALL_ACCESS, &WrapperContext.RegistryHandle);
01879   if (!NT_SUCCESS(Status))
01880     {
01881       NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
01882       ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
01883       return Status;
01884     }
01885 
01886   NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
01887 
01888   WrapperContext.DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
01889 
01890   /*
01891    * Store the adapter resources used by HW routines such as
01892    * NdisMQueryAdapterResources.
01893    */
01894 
01895   if (Stack->Parameters.StartDevice.AllocatedResources != NULL)
01896     {
01897       ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
01898                       PartialResourceList.Count;
01899       ResourceListSize =
01900         FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
01901                      PartialDescriptors[ResourceCount]);
01902 
01903       Adapter->NdisMiniportBlock.AllocatedResources =
01904         ExAllocatePool(PagedPool, ResourceListSize);
01905       if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
01906         {
01907           NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
01908       ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
01909           return STATUS_INSUFFICIENT_RESOURCES;
01910         }
01911 
01912       Adapter->NdisMiniportBlock.Resources =
01913         ExAllocatePool(PagedPool, ResourceListSize);
01914       if (!Adapter->NdisMiniportBlock.Resources)
01915       {
01916           NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
01917           ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
01918           ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
01919           return STATUS_INSUFFICIENT_RESOURCES;
01920       }
01921 
01922       RtlCopyMemory(Adapter->NdisMiniportBlock.Resources,
01923                     Stack->Parameters.StartDevice.AllocatedResources,
01924                     ResourceListSize);
01925 
01926       RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
01927                     Stack->Parameters.StartDevice.AllocatedResources,
01928                     ResourceListSize);
01929     }
01930 
01931   if (Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
01932     {
01933       ResourceCount = Stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].
01934                       PartialResourceList.Count;
01935       ResourceListSize =
01936         FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
01937                      PartialDescriptors[ResourceCount]);
01938 
01939       Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
01940         ExAllocatePool(PagedPool, ResourceListSize);
01941       if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
01942         {
01943           NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
01944       ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
01945           return STATUS_INSUFFICIENT_RESOURCES;
01946         }
01947 
01948       RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
01949                     Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
01950                     ResourceListSize);
01951    }
01952 
01953   /*
01954    * Store the Bus Type, Bus Number and Slot information. It's used by
01955    * the hardware routines then.
01956    */
01957 
01958   NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
01959   if (NdisStatus != NDIS_STATUS_SUCCESS)
01960   {
01961       NDIS_DbgPrint(MIN_TRACE, ("Failed to open configuration key\n"));
01962       ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
01963       return NdisStatus;
01964   }
01965 
01966   Size = sizeof(ULONG);
01967   Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
01968                                DevicePropertyLegacyBusType, Size,
01969                                &Adapter->NdisMiniportBlock.BusType, &Size);
01970   if (!NT_SUCCESS(Status) || (INTERFACE_TYPE)Adapter->NdisMiniportBlock.BusType == InterfaceTypeUndefined)
01971     {
01972       NdisInitUnicodeString(&ParamName, L"BusType");
01973       NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
01974                             &ParamName, NdisParameterInteger);
01975       if (NdisStatus == NDIS_STATUS_SUCCESS)
01976         Adapter->NdisMiniportBlock.BusType = ConfigParam->ParameterData.IntegerData;
01977       else
01978         Adapter->NdisMiniportBlock.BusType = Isa;
01979     }
01980 
01981   Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
01982                                DevicePropertyBusNumber, Size,
01983                                &Adapter->NdisMiniportBlock.BusNumber, &Size);
01984   if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusNumber == 0xFFFFFFF0)
01985     {
01986       NdisInitUnicodeString(&ParamName, L"BusNumber");
01987       NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
01988                             &ParamName, NdisParameterInteger);
01989       if (NdisStatus == NDIS_STATUS_SUCCESS)
01990         Adapter->NdisMiniportBlock.BusNumber = ConfigParam->ParameterData.IntegerData;
01991       else
01992         Adapter->NdisMiniportBlock.BusNumber = 0;
01993     }
01994   WrapperContext.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
01995 
01996   Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
01997                                DevicePropertyAddress, Size,
01998                                &Adapter->NdisMiniportBlock.SlotNumber, &Size);
01999   if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.SlotNumber == (NDIS_INTERFACE_TYPE)-1)
02000     {
02001       NdisInitUnicodeString(&ParamName, L"SlotNumber");
02002       NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
02003                             &ParamName, NdisParameterInteger);
02004       if (NdisStatus == NDIS_STATUS_SUCCESS)
02005         Adapter->NdisMiniportBlock.SlotNumber = ConfigParam->ParameterData.IntegerData;
02006       else
02007         Adapter->NdisMiniportBlock.SlotNumber = 0;
02008     }
02009   else
02010     {
02011         /* Convert slotnumber to PCI_SLOT_NUMBER */
02012         ULONG PciSlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
02013         PCI_SLOT_NUMBER SlotNumber;
02014 
02015         SlotNumber.u.AsULONG = 0;
02016         SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF;
02017         SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF;
02018 
02019         Adapter->NdisMiniportBlock.SlotNumber = SlotNumber.u.AsULONG;
02020     }
02021   WrapperContext.SlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
02022 
02023   NdisCloseConfiguration(ConfigHandle);
02024 
02025   /* Set handlers (some NDIS macros require these) */
02026   Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
02027   Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
02028   Adapter->NdisMiniportBlock.SendCompleteHandler  = MiniSendComplete;
02029   Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
02030   Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
02031   Adapter->NdisMiniportBlock.TDCompleteHandler    = MiniTransferDataComplete;
02032   Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
02033   Adapter->NdisMiniportBlock.StatusHandler        = MiniStatus;
02034   Adapter->NdisMiniportBlock.StatusCompleteHandler= MiniStatusComplete;
02035   Adapter->NdisMiniportBlock.SendPacketsHandler   = ProSendPackets;
02036   Adapter->NdisMiniportBlock.QueryCompleteHandler = MiniRequestComplete;
02037   Adapter->NdisMiniportBlock.SetCompleteHandler   = MiniRequestComplete;
02038 
02039   /*
02040    * Call MiniportInitialize.
02041    */
02042 
02043   NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
02044   NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.InitializeHandler)(
02045     &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
02046     MEDIA_ARRAY_SIZE, Adapter, (NDIS_HANDLE)&WrapperContext);
02047 
02048   ZwClose(WrapperContext.RegistryHandle);
02049 
02050   if (NdisStatus != NDIS_STATUS_SUCCESS)
02051     {
02052       NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
02053       ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
02054       if (Adapter->NdisMiniportBlock.Interrupt)
02055       {
02056           KeBugCheckEx(BUGCODE_ID_DRIVER,
02057                        (ULONG_PTR)Adapter,
02058                        (ULONG_PTR)Adapter->NdisMiniportBlock.Interrupt,
02059                        (ULONG_PTR)Adapter->NdisMiniportBlock.TimerQueue,
02060                        1);
02061       }
02062       if (Adapter->NdisMiniportBlock.TimerQueue)
02063       {
02064           KeBugCheckEx(BUGCODE_ID_DRIVER,
02065                        (ULONG_PTR)Adapter,
02066                        (ULONG_PTR)Adapter->NdisMiniportBlock.Interrupt,
02067                        (ULONG_PTR)Adapter->NdisMiniportBlock.TimerQueue,
02068                        1);
02069       }
02070       return NdisStatus;
02071     }
02072 
02073   if (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
02074     {
02075       NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() selected a bad index\n"));
02076       ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
02077       return NDIS_STATUS_UNSUPPORTED_MEDIA;
02078     }
02079 
02080   Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
02081 
02082   switch (Adapter->NdisMiniportBlock.MediaType)
02083     {
02084       case NdisMedium802_3:
02085         Adapter->MediumHeaderSize = 14;       /* XXX figure out what to do about LLC */
02086         AddressOID = OID_802_3_CURRENT_ADDRESS;
02087         Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
02088         NdisStatus = DoQueries(Adapter, AddressOID);
02089         if (NdisStatus == NDIS_STATUS_SUCCESS)
02090           {
02091             NdisStatus = MiniQueryInformation(Adapter, OID_802_3_MAXIMUM_LIST_SIZE, sizeof(UINT),
02092                                     &MaxMulticastAddresses, &BytesWritten);
02093 
02094             if (NdisStatus != NDIS_STATUS_SUCCESS)
02095             {
02096                ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
02097                NDIS_DbgPrint(MIN_TRACE, ("MiniQueryInformation failed (%x)\n", NdisStatus));
02098                return NdisStatus;
02099             }
02100 
02101             Success = EthCreateFilter(MaxMulticastAddresses,
02102                                       Adapter->Address.Type.Medium802_3,
02103                                       &Adapter->NdisMiniportBlock.EthDB);
02104             if (Success)
02105               ((PETHI_FILTER)Adapter->NdisMiniportBlock.EthDB)->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
02106             else
02107               NdisStatus = NDIS_STATUS_RESOURCES;
02108           }
02109         break;
02110 
02111       default:
02112         /* FIXME: Support other types of media */
02113         NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
02114         ASSERT(FALSE);
02115     ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
02116         return STATUS_UNSUCCESSFUL;
02117     }
02118 
02119   if (NdisStatus != NDIS_STATUS_SUCCESS)
02120     {
02121       NDIS_DbgPrint(MIN_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
02122       return NdisStatus;
02123     }
02124 
02125   /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
02126   if (Adapter->NdisMiniportBlock.CheckForHangSeconds == 0)
02127       Adapter->NdisMiniportBlock.CheckForHangSeconds = 2;
02128 
02129   Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
02130   Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
02131 
02132   IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, TRUE);
02133 
02134   Timeout.QuadPart = Int32x32To64(Adapter->NdisMiniportBlock.CheckForHangSeconds, -1000000);
02135   KeSetTimerEx(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer, Timeout,
02136                Adapter->NdisMiniportBlock.CheckForHangSeconds * 1000,
02137                &Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc);
02138 
02139   /* Put adapter in adapter list for this miniport */
02140   ExInterlockedInsertTailList(&Adapter->NdisMiniportBlock.DriverHandle->DeviceList, &Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
02141 
02142   /* Refresh bindings for all protocols */
02143   CurrentEntry = ProtocolListHead.Flink;
02144   while (CurrentEntry != &ProtocolListHead)
02145   {
02146       ProtocolBinding = CONTAINING_RECORD(CurrentEntry, PROTOCOL_BINDING, ListEntry);
02147 
02148       ndisBindMiniportsToProtocol(&NdisStatus, ProtocolBinding);
02149 
02150       CurrentEntry = CurrentEntry->Flink;
02151   }
02152 
02153   return STATUS_SUCCESS;
02154 }
02155 
02156 
02157 NTSTATUS
02158 NTAPI
02159 NdisIPnPStopDevice(
02160     IN PDEVICE_OBJECT DeviceObject,
02161     PIRP Irp)
02162 /*
02163  * FUNCTION: Handle the PnP stop device event
02164  * ARGUMENTS:
02165  *     DeviceObejct = Functional Device Object
02166  *     Irp          = IRP_MN_STOP_DEVICE I/O request packet
02167  * RETURNS:
02168  *     Status of operation
02169  */
02170 {
02171   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
02172 
02173   /* Remove adapter from adapter list for this miniport */
02174   ExInterlockedRemoveEntryList(&Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
02175 
02176   /* Remove adapter from global adapter list */
02177   ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
02178 
02179   KeCancelTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
02180 
02181   (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HaltHandler)(Adapter);
02182 
02183   IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, FALSE);
02184 
02185   if (Adapter->NdisMiniportBlock.AllocatedResources)
02186     {
02187       ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
02188       Adapter->NdisMiniportBlock.AllocatedResources = NULL;
02189     }
02190   if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated)
02191     {
02192       ExFreePool(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated);
02193       Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
02194     }
02195 
02196   if (Adapter->NdisMiniportBlock.Resources)
02197     {
02198       ExFreePool(Adapter->NdisMiniportBlock.Resources);
02199       Adapter->NdisMiniportBlock.Resources = NULL;
02200     }
02201 
02202   if (Adapter->NdisMiniportBlock.EthDB)
02203     {
02204       EthDeleteFilter(Adapter->NdisMiniportBlock.EthDB);
02205       Adapter->NdisMiniportBlock.EthDB = NULL;
02206     }
02207 
02208   Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
02209   Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
02210 
02211   return STATUS_SUCCESS;
02212 }
02213 
02214 NTSTATUS
02215 NTAPI
02216 NdisIShutdown(
02217     IN PDEVICE_OBJECT DeviceObject,
02218     PIRP Irp)
02219 {
02220   PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
02221   PMINIPORT_BUGCHECK_CONTEXT Context = Adapter->BugcheckContext;
02222   ADAPTER_SHUTDOWN_HANDLER ShutdownHandler = Context->ShutdownHandler;
02223 
02224   ASSERT(ShutdownHandler);
02225 
02226   ShutdownHandler(Context->DriverContext);
02227 
02228   Irp->IoStatus.Status = STATUS_SUCCESS;
02229   Irp->IoStatus.Information = 0;
02230 
02231   IoCompleteRequest(Irp, IO_NO_INCREMENT);
02232 
02233   return STATUS_SUCCESS;
02234 }
02235 
02236 NTSTATUS
02237 NTAPI
02238 NdisIDeviceIoControl(
02239     IN PDEVICE_OBJECT DeviceObject,
02240     PIRP Irp)
02241 {
02242   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
02243   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
02244   NDIS_STATUS Status = STATUS_NOT_SUPPORTED;
02245   ULONG Written;
02246 
02247   Irp->IoStatus.Information = 0;
02248 
02249   ASSERT(Adapter);
02250 
02251   switch (Stack->Parameters.DeviceIoControl.IoControlCode)
02252   {
02253     case IOCTL_NDIS_QUERY_GLOBAL_STATS:
02254       Status = MiniQueryInformation(Adapter,
02255                                     *(PNDIS_OID)Irp->AssociatedIrp.SystemBuffer,
02256                                     Stack->Parameters.DeviceIoControl.OutputBufferLength,
02257                                     MmGetSystemAddressForMdl(Irp->MdlAddress),
02258                                     &Written);
02259       Irp->IoStatus.Information = Written;
02260       break;
02261 
02262     default:
02263       ASSERT(FALSE);
02264       break;
02265   }
02266 
02267   if (Status != NDIS_STATUS_PENDING)
02268   {
02269       Irp->IoStatus.Status = Status;
02270       IoCompleteRequest(Irp, IO_NO_INCREMENT);
02271   }
02272   else
02273       IoMarkIrpPending(Irp);
02274 
02275   return Status;
02276 }
02277 
02278 
02279 NTSTATUS
02280 NTAPI
02281 NdisIDispatchPnp(
02282     IN PDEVICE_OBJECT DeviceObject,
02283     PIRP Irp)
02284 {
02285   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
02286   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
02287   NTSTATUS Status;
02288 
02289   switch (Stack->MinorFunction)
02290     {
02291       case IRP_MN_START_DEVICE:
02292         Status = NdisIForwardIrpAndWait(Adapter, Irp);
02293         if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
02294           {
02295           Status = NdisIPnPStartDevice(DeviceObject, Irp);
02296           }
02297           else
02298               NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed device start\n"));
02299         Irp->IoStatus.Status = Status;
02300         IoCompleteRequest(Irp, IO_NO_INCREMENT);
02301         return Status;
02302 
02303       case IRP_MN_STOP_DEVICE:
02304         Status = NdisIPnPStopDevice(DeviceObject, Irp);
02305         if (!NT_SUCCESS(Status))
02306             NDIS_DbgPrint(MIN_TRACE, ("WARNING: Ignoring halt device failure! Passing the IRP down anyway\n"));
02307         Irp->IoStatus.Status = STATUS_SUCCESS;
02308         break;
02309 
02310       case IRP_MN_QUERY_REMOVE_DEVICE:
02311       case IRP_MN_QUERY_STOP_DEVICE:
02312         Status = NdisIPnPQueryStopDevice(DeviceObject, Irp);
02313         Irp->IoStatus.Status = Status;
02314         if (Status != STATUS_SUCCESS)
02315         {
02316             IoCompleteRequest(Irp, IO_NO_INCREMENT);
02317             NDIS_DbgPrint(MIN_TRACE, ("Failing miniport halt request\n"));
02318             return Status;
02319         }
02320         break;
02321 
02322       case IRP_MN_CANCEL_REMOVE_DEVICE:
02323       case IRP_MN_CANCEL_STOP_DEVICE:
02324         Status = NdisIForwardIrpAndWait(Adapter, Irp);
02325         if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
02326         {
02327             Status = NdisIPnPCancelStopDevice(DeviceObject, Irp);
02328         }
02329         else
02330         {
02331             NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed cancel stop/remove request\n"));
02332         }
02333         Irp->IoStatus.Status = Status;
02334         IoCompleteRequest(Irp, IO_NO_INCREMENT);
02335         return Status;
02336 
02337       case IRP_MN_QUERY_PNP_DEVICE_STATE:
02338         Status = NDIS_STATUS_SUCCESS;
02339         Irp->IoStatus.Status = Status;
02340         Irp->IoStatus.Information |= Adapter->NdisMiniportBlock.PnPFlags;
02341         break;
02342 
02343       default:
02344         break;
02345     }
02346 
02347   IoSkipCurrentIrpStackLocation(Irp);
02348   return IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
02349 }
02350 
02351 
02352 NTSTATUS
02353 NTAPI
02354 NdisIAddDevice(
02355     IN PDRIVER_OBJECT DriverObject,
02356     IN PDEVICE_OBJECT PhysicalDeviceObject)
02357 /*
02358  * FUNCTION: Create a device for an adapter found using PnP
02359  * ARGUMENTS:
02360  *     DriverObject         = Pointer to the miniport driver object
02361  *     PhysicalDeviceObject = Pointer to the PDO for our adapter
02362  */
02363 {
02364   static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
02365   static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
02366   PNDIS_M_DRIVER_BLOCK Miniport;
02367   PNDIS_M_DRIVER_BLOCK *MiniportPtr;
02368   WCHAR *LinkageKeyBuffer;
02369   ULONG DriverKeyLength;
02370   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
02371   UNICODE_STRING ExportName;
02372   PDEVICE_OBJECT DeviceObject;
02373   PLOGICAL_ADAPTER Adapter;
02374   NTSTATUS Status;
02375 
02376   /*
02377    * Gain the access to the miniport data structure first.
02378    */
02379 
02380   MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)'NMID');
02381   if (MiniportPtr == NULL)
02382     {
02383       NDIS_DbgPrint(MIN_TRACE, ("Can't get driver object extension.\n"));
02384       return NDIS_STATUS_FAILURE;
02385     }
02386   Miniport = *MiniportPtr;
02387 
02388   /*
02389    * Get name of the Linkage registry key for our adapter. It's located under
02390    * the driver key for our driver and so we have basicly two ways to do it.
02391    * Either we can use IoOpenDriverRegistryKey or compose it using information
02392    * gathered by IoGetDeviceProperty. I choosed the second because
02393    * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
02394    */
02395 
02396   Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
02397                                0, NULL, &DriverKeyLength);
02398   if (Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_SUCCESS)
02399     {
02400       NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key length.\n"));
02401       return Status;
02402     }
02403 
02404   LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
02405                                     sizeof(ClassKeyName) + sizeof(LinkageKeyName));
02406   if (LinkageKeyBuffer == NULL)
02407     {
02408       NDIS_DbgPrint(MIN_TRACE, ("Can't allocate memory for driver key name.\n"));
02409       return STATUS_INSUFFICIENT_RESOURCES;
02410     }
02411 
02412   Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
02413                                DriverKeyLength, LinkageKeyBuffer +
02414                                (sizeof(ClassKeyName) / sizeof(WCHAR)),
02415                                &DriverKeyLength);
02416   if (!NT_SUCCESS(Status))
02417     {
02418       NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key.\n"));
02419       ExFreePool(LinkageKeyBuffer);
02420       return Status;
02421     }
02422 
02423   /* Compose the linkage key name. */
02424   RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
02425   RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
02426                 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
02427 
02428   NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
02429 
02430   /*
02431    * Now open the linkage key and read the "Export" and "RootDevice" values
02432    * which contains device name and root service respectively.
02433    */
02434 
02435   RtlZeroMemory(QueryTable, sizeof(QueryTable));
02436   RtlInitUnicodeString(&ExportName, NULL);
02437   QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
02438   QueryTable[0].Name = L"Export";
02439   QueryTable[0].EntryContext = &ExportName;
02440 
02441   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
02442                                   QueryTable, NULL, NULL);
02443   ExFreePool(LinkageKeyBuffer);
02444   if (!NT_SUCCESS(Status))
02445     {
02446       NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport device name. (%x)\n", Status));
02447       return Status;
02448     }
02449 
02450   /*
02451    * Create the device object.
02452    */
02453 
02454   NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", &ExportName));
02455 
02456   Status = IoCreateDevice(Miniport->DriverObject, sizeof(LOGICAL_ADAPTER),
02457     &ExportName, FILE_DEVICE_PHYSICAL_NETCARD,
02458     0, FALSE, &DeviceObject);
02459   if (!NT_SUCCESS(Status))
02460     {
02461       NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
02462       RtlFreeUnicodeString(&ExportName);
02463       return Status;
02464     }
02465 
02466   /*
02467    * Initialize the adapter structure.
02468    */
02469 
02470   Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
02471   KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
02472   InitializeListHead(&Adapter->ProtocolListHead);
02473 
02474   Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
02475                                      &GUID_DEVINTERFACE_NET,
02476                                      NULL,
02477                                      &Adapter->NdisMiniportBlock.SymbolicLinkName);
02478 
02479   if (!NT_SUCCESS(Status))
02480   {
02481       NDIS_DbgPrint(MIN_TRACE, ("Could not create device interface.\n"));
02482       IoDeleteDevice(DeviceObject);
02483       RtlFreeUnicodeString(&ExportName);
02484       return Status;
02485   }
02486 
02487   Adapter->NdisMiniportBlock.DriverHandle = Miniport;
02488   Adapter->NdisMiniportBlock.MiniportName = ExportName;
02489   Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
02490   Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
02491   Adapter->NdisMiniportBlock.NextDeviceObject =
02492     IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
02493                                 PhysicalDeviceObject);
02494 
02495   Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
02496   Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
02497 
02498   KeInitializeTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
02499   KeInitializeDpc(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc, MiniportHangDpc, Adapter);
02500 
02501   DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
02502 
02503   return STATUS_SUCCESS;
02504 }
02505 
02506 
02507 /*
02508  * @implemented
02509  */
02510 NDIS_STATUS
02511 EXPORT
02512 NdisMRegisterMiniport(
02513     IN  NDIS_HANDLE                     NdisWrapperHandle,
02514     IN  PNDIS_MINIPORT_CHARACTERISTICS  MiniportCharacteristics,
02515     IN  UINT                            CharacteristicsLength)
02516 /*
02517  * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
02518  * ARGUMENTS:
02519  *     NdisWrapperHandle       = Pointer to handle returned by NdisMInitializeWrapper
02520  *     MiniportCharacteristics = Pointer to a buffer with miniport characteristics
02521  *     CharacteristicsLength   = Number of bytes in characteristics buffer
02522  * RETURNS:
02523  *     Status of operation
02524  */
02525 {
02526   UINT MinSize;
02527   PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
02528   PNDIS_M_DRIVER_BLOCK *MiniportPtr;
02529   NTSTATUS Status;
02530 
02531   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
02532 
02533   switch (MiniportCharacteristics->MajorNdisVersion)
02534     {
02535       case 0x03:
02536         MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
02537         break;
02538 
02539       case 0x04:
02540         MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
02541         break;
02542 
02543       case 0x05:
02544         switch (MiniportCharacteristics->MinorNdisVersion)
02545         {
02546             case 0x00:
02547                 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
02548                 break;
02549                 
02550             case 0x01:
02551                 MinSize = sizeof(NDIS51_MINIPORT_CHARACTERISTICS);
02552                 break;
02553                 
02554             default:
02555                 NDIS_DbgPrint(MIN_TRACE, ("Bad 5.x minor characteristics version.\n"));
02556                 return NDIS_STATUS_BAD_VERSION;
02557         }
02558         break;
02559 
02560       default:
02561         NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics version.\n"));
02562         return NDIS_STATUS_BAD_VERSION;
02563     }
02564 
02565    NDIS_DbgPrint(MIN_TRACE, ("Initializing an NDIS %u.%u miniport\n", 
02566                               MiniportCharacteristics->MajorNdisVersion,
02567                               MiniportCharacteristics->MinorNdisVersion));
02568 
02569   if (CharacteristicsLength < MinSize)
02570     {
02571         NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics length.\n"));
02572         return NDIS_STATUS_BAD_CHARACTERISTICS;
02573     }
02574 
02575   /* Check if mandatory MiniportXxx functions are specified */
02576   if ((!MiniportCharacteristics->HaltHandler) ||
02577        (!MiniportCharacteristics->InitializeHandler)||
02578        (!MiniportCharacteristics->ResetHandler))
02579     {
02580       NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics.\n"));
02581       return NDIS_STATUS_BAD_CHARACTERISTICS;
02582     }
02583 
02584   if (MiniportCharacteristics->MajorNdisVersion < 0x05)
02585   {
02586       if ((!MiniportCharacteristics->QueryInformationHandler) ||
02587           (!MiniportCharacteristics->SetInformationHandler))
02588       {
02589            NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
02590            return NDIS_STATUS_BAD_CHARACTERISTICS;
02591       }
02592   }
02593   else
02594   {
02595       if (((!MiniportCharacteristics->QueryInformationHandler) ||
02596            (!MiniportCharacteristics->SetInformationHandler)) &&
02597            (!MiniportCharacteristics->CoRequestHandler))
02598       {
02599            NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
02600            return NDIS_STATUS_BAD_CHARACTERISTICS;
02601       }
02602   }
02603 
02604   if (MiniportCharacteristics->MajorNdisVersion == 0x03)
02605     {
02606       if (!MiniportCharacteristics->SendHandler)
02607         {
02608           NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 3.0)\n"));
02609           return NDIS_STATUS_BAD_CHARACTERISTICS;
02610         }
02611     }
02612   else if (MiniportCharacteristics->MajorNdisVersion == 0x04)
02613     {
02614       /* NDIS 4.0 */
02615       if ((!MiniportCharacteristics->SendHandler) &&
02616           (!MiniportCharacteristics->SendPacketsHandler))
02617         {
02618           NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 4.0)\n"));
02619           return NDIS_STATUS_BAD_CHARACTERISTICS;
02620         }
02621     }
02622   else if (MiniportCharacteristics->MajorNdisVersion == 0x05)
02623     {
02624       /* TODO: Add more checks here */
02625 
02626       if ((!MiniportCharacteristics->SendHandler) &&
02627           (!MiniportCharacteristics->SendPacketsHandler) &&
02628           (!MiniportCharacteristics->CoSendPacketsHandler))
02629         {
02630           NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 5.0)\n"));
02631           return NDIS_STATUS_BAD_CHARACTERISTICS;
02632         }
02633     }
02634 
02635   RtlCopyMemory(&Miniport->MiniportCharacteristics, MiniportCharacteristics, MinSize);
02636 
02637   /*
02638    * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
02639    * structure in the driver extension or what?
02640    */
02641 
02642   Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)'NMID',
02643                                            sizeof(PNDIS_M_DRIVER_BLOCK), (PVOID*)&MiniportPtr);
02644   if (!NT_SUCCESS(Status))
02645     {
02646       NDIS_DbgPrint(MIN_TRACE, ("Can't allocate driver object extension.\n"));
02647       return NDIS_STATUS_RESOURCES;
02648     }
02649 
02650   *MiniportPtr = Miniport;
02651 
02652   Miniport->DriverObject->MajorFunction[IRP_MJ_CREATE] = NdisICreateClose;
02653   Miniport->DriverObject->MajorFunction[IRP_MJ_CLOSE] = NdisICreateClose;
02654   Miniport->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
02655   Miniport->DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = NdisIShutdown;
02656   Miniport->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisIDeviceIoControl;
02657   Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
02658 
02659   return NDIS_STATUS_SUCCESS;
02660 }
02661 
02662 
02663 /*
02664  * @implemented
02665  */
02666 #undef NdisMResetComplete
02667 VOID
02668 EXPORT
02669 NdisMResetComplete(
02670     IN NDIS_HANDLE MiniportAdapterHandle,
02671     IN NDIS_STATUS Status,
02672     IN BOOLEAN     AddressingReset)
02673 {
02674   MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
02675 }
02676 
02677 
02678 /*
02679  * @implemented
02680  */
02681 #undef NdisMSendComplete
02682 VOID
02683 EXPORT
02684 NdisMSendComplete(
02685     IN  NDIS_HANDLE     MiniportAdapterHandle,
02686     IN  PNDIS_PACKET    Packet,
02687     IN  NDIS_STATUS     Status)
02688 /*
02689  * FUNCTION: Forwards a message to the initiating protocol saying
02690  *           that a packet was handled
02691  * ARGUMENTS:
02692  *     NdisAdapterHandle = Handle input to MiniportInitialize
02693  *     Packet            = Pointer to NDIS packet that was sent
02694  *     Status            = Status of send operation
02695  */
02696 {
02697   MiniSendComplete(MiniportAdapterHandle, Packet, Status);
02698 }
02699 
02700 
02701 /*
02702  * @implemented
02703  */
02704 #undef NdisMSendResourcesAvailable
02705 VOID
02706 EXPORT
02707 NdisMSendResourcesAvailable(
02708     IN  NDIS_HANDLE MiniportAdapterHandle)
02709 {
02710   MiniSendResourcesAvailable(MiniportAdapterHandle);
02711 }
02712 
02713 
02714 /*
02715  * @implemented
02716  */
02717 #undef NdisMTransferDataComplete
02718 VOID
02719 EXPORT
02720 NdisMTransferDataComplete(
02721     IN  NDIS_HANDLE     MiniportAdapterHandle,
02722     IN  PNDIS_PACKET    Packet,
02723     IN  NDIS_STATUS     Status,
02724     IN  UINT            BytesTransferred)
02725 {
02726   MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
02727 }
02728 
02729 
02730 /*
02731  * @implemented
02732  */
02733 #undef NdisMSetAttributes
02734 VOID
02735 EXPORT
02736 NdisMSetAttributes(
02737     IN  NDIS_HANDLE         MiniportAdapterHandle,
02738     IN  NDIS_HANDLE         MiniportAdapterContext,
02739     IN  BOOLEAN             BusMaster,
02740     IN  NDIS_INTERFACE_TYPE AdapterType)
02741 /*
02742  * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
02743  * ARGUMENTS:
02744  *     MiniportAdapterHandle  = Handle input to MiniportInitialize
02745  *     MiniportAdapterContext = Pointer to context information
02746  *     BusMaster              = Specifies TRUE if the caller's NIC is a busmaster DMA device
02747  *     AdapterType            = Specifies the I/O bus interface of the caller's NIC
02748  */
02749 {
02750   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
02751   NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0,
02752                        BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
02753                        AdapterType);
02754 }
02755 
02756 
02757 /*
02758  * @implemented
02759  */
02760 VOID
02761 EXPORT
02762 NdisMSetAttributesEx(
02763     IN  NDIS_HANDLE         MiniportAdapterHandle,
02764     IN  NDIS_HANDLE         MiniportAdapterContext,
02765     IN  UINT                CheckForHangTimeInSeconds   OPTIONAL,
02766     IN  ULONG               AttributeFlags,
02767     IN  NDIS_INTERFACE_TYPE AdapterType)
02768 /*
02769  * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
02770  * ARGUMENTS:
02771  *     MiniportAdapterHandle     = Handle input to MiniportInitialize
02772  *     MiniportAdapterContext    = Pointer to context information
02773  *     CheckForHangTimeInSeconds = Specifies interval in seconds at which
02774  *                                 MiniportCheckForHang should be called
02775  *     AttributeFlags            = Bitmask that indicates specific attributes
02776  *     AdapterType               = Specifies the I/O bus interface of the caller's NIC
02777  */
02778 {
02779   PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
02780 
02781   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
02782 
02783   Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
02784   Adapter->NdisMiniportBlock.Flags = AttributeFlags;
02785   Adapter->NdisMiniportBlock.AdapterType = AdapterType;
02786   if (CheckForHangTimeInSeconds > 0)
02787       Adapter->NdisMiniportBlock.CheckForHangSeconds = CheckForHangTimeInSeconds;
02788   if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
02789     NDIS_DbgPrint(MIN_TRACE, ("Intermediate drivers not supported yet.\n"));
02790 
02791   NDIS_DbgPrint(MIN_TRACE, ("Miniport attribute flags: 0x%x\n", AttributeFlags));
02792 
02793   if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler)
02794   {
02795       NDIS_DbgPrint(MAX_TRACE, ("Miniport set AdapterShutdownHandler in MiniportCharacteristics\n"));
02796       NdisMRegisterAdapterShutdownHandler(Adapter,
02797                       Adapter->NdisMiniportBlock.MiniportAdapterContext,
02798                       Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler);
02799   }
02800 }
02801 
02802 
02803 /*
02804  * @implemented
02805  */
02806 VOID
02807 EXPORT
02808 NdisMSleep(
02809     IN  ULONG   MicrosecondsToSleep)
02810 /*
02811  * FUNCTION: delay the thread's execution for MicrosecondsToSleep
02812  * ARGUMENTS:
02813  *     MicrosecondsToSleep: duh...
02814  * NOTES:
02815  *     - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
02816  */
02817 {
02818   KTIMER Timer;
02819   LARGE_INTEGER DueTime;
02820 
02821   PAGED_CODE();
02822 
02823   DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
02824 
02825   KeInitializeTimer(&Timer);
02826   KeSetTimer(&Timer, DueTime, 0);
02827   KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
02828 }
02829 
02830 
02831 /*
02832  * @implemented
02833  */
02834 BOOLEAN
02835 EXPORT
02836 NdisMSynchronizeWithInterrupt(
02837     IN  PNDIS_MINIPORT_INTERRUPT    Interrupt,
02838     IN  PVOID                       SynchronizeFunction,
02839     IN  PVOID                       SynchronizeContext)
02840 {
02841   return(KeSynchronizeExecution(Interrupt->InterruptObject,
02842                 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
02843                 SynchronizeContext));
02844 }
02845 
02846 
02847 /*
02848  * @unimplemented
02849  */
02850 NDIS_STATUS
02851 EXPORT
02852 NdisMWriteLogData(
02853     IN  NDIS_HANDLE LogHandle,
02854     IN  PVOID       LogBuffer,
02855     IN  UINT        LogBufferSize)
02856 {
02857     PUCHAR Buffer = LogBuffer;
02858     UINT i, j, idx;
02859 
02860     UNIMPLEMENTED;
02861     for (i = 0; i < LogBufferSize; i += 16)
02862     {
02863         DbgPrint("%08x |", i);
02864         for (j = 0; j < 16; j++)
02865         {
02866             idx = i + j;
02867             if (idx < LogBufferSize)
02868                 DbgPrint(" %02x", Buffer[idx]);
02869             else
02870                 DbgPrint("   ");
02871         }
02872         DbgPrint(" | ");
02873         for (j = 0; j < 16; j++)
02874         {
02875             idx = i + j;
02876             if (idx == LogBufferSize)
02877                 break;
02878             if (Buffer[idx] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
02879                 DbgPrint("%c", Buffer[idx]);
02880             else
02881                 DbgPrint(".");
02882         }
02883         DbgPrint("\n");
02884     }
02885 
02886     return NDIS_STATUS_FAILURE;
02887 }
02888 
02889 
02890 /*
02891  * @implemented
02892  */
02893 VOID
02894 EXPORT
02895 NdisTerminateWrapper(
02896     IN  NDIS_HANDLE NdisWrapperHandle,
02897     IN  PVOID       SystemSpecific)
02898 /*
02899  * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
02900  * ARGUMENTS:
02901  *     NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
02902  *     SystemSpecific    = Always NULL
02903  */
02904 {
02905   PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
02906 
02907   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
02908 
02909   ExFreePool(Miniport->RegistryPath->Buffer);
02910   ExFreePool(Miniport->RegistryPath);
02911   ExInterlockedRemoveEntryList(&Miniport->ListEntry, &MiniportListLock);
02912   ExFreePool(Miniport);
02913 }
02914 
02915 
02916 /*
02917  * @implemented
02918  */
02919 NDIS_STATUS
02920 EXPORT
02921 NdisMQueryAdapterInstanceName(
02922     OUT PNDIS_STRING    AdapterInstanceName,
02923     IN  NDIS_HANDLE     MiniportAdapterHandle)
02924 /*
02925  * FUNCTION:
02926  * ARGUMENTS:
02927  * NOTES:
02928  *    NDIS 5.0
02929  */
02930 {
02931     PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
02932     UNICODE_STRING AdapterName;
02933 
02934     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
02935 
02936     AdapterName.Length = 0;
02937     AdapterName.MaximumLength = Adapter->NdisMiniportBlock.MiniportName.MaximumLength;
02938     AdapterName.Buffer = ExAllocatePool(PagedPool, AdapterName.MaximumLength);
02939     if (!AdapterName.Buffer) {
02940         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
02941         return NDIS_STATUS_RESOURCES;
02942     }
02943 
02944     RtlCopyUnicodeString(&AdapterName, &Adapter->NdisMiniportBlock.MiniportName);
02945 
02946     *AdapterInstanceName = AdapterName;
02947 
02948     return NDIS_STATUS_SUCCESS;
02949 }
02950 
02951 /*
02952  * @implemented
02953  */
02954 VOID
02955 EXPORT
02956 NdisDeregisterAdapterShutdownHandler(
02957     IN  NDIS_HANDLE NdisAdapterHandle)
02958 /*
02959  * FUNCTION:
02960  * ARGUMENTS:
02961  * NOTES:
02962  *    NDIS 4.0
02963  */
02964 {
02965     NdisMDeregisterAdapterShutdownHandler(NdisAdapterHandle);
02966 }
02967 
02968 
02969 /*
02970  * @implemented
02971  */
02972 VOID
02973 EXPORT
02974 NdisRegisterAdapterShutdownHandler(
02975     IN  NDIS_HANDLE                 NdisAdapterHandle,
02976     IN  PVOID                       ShutdownContext,
02977     IN  ADAPTER_SHUTDOWN_HANDLER    ShutdownHandler)
02978 /*
02979  * FUNCTION:
02980  * ARGUMENTS:
02981  * NOTES:
02982  *    NDIS 4.0
02983  */
02984 {
02985     NdisMRegisterAdapterShutdownHandler(NdisAdapterHandle,
02986                                         ShutdownContext,
02987                                         ShutdownHandler);
02988 }
02989 
02990 /*
02991  * @implemented
02992  */
02993 VOID
02994 EXPORT
02995 NdisMGetDeviceProperty(
02996     IN      NDIS_HANDLE         MiniportAdapterHandle,
02997     IN OUT  PDEVICE_OBJECT      *PhysicalDeviceObject           OPTIONAL,
02998     IN OUT  PDEVICE_OBJECT      *FunctionalDeviceObject         OPTIONAL,
02999     IN OUT  PDEVICE_OBJECT      *NextDeviceObject               OPTIONAL,
03000     IN OUT  PCM_RESOURCE_LIST   *AllocatedResources             OPTIONAL,
03001     IN OUT  PCM_RESOURCE_LIST   *AllocatedResourcesTranslated   OPTIONAL)
03002 /*
03003  * FUNCTION:
03004  * ARGUMENTS:
03005  * NOTES:
03006  *    NDIS 5.0
03007  */
03008 {
03009     PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
03010 
03011     NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
03012 
03013     if (PhysicalDeviceObject != NULL)
03014         *PhysicalDeviceObject = Adapter->NdisMiniportBlock.PhysicalDeviceObject;
03015 
03016     if (FunctionalDeviceObject != NULL)
03017         *FunctionalDeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
03018 
03019     if (NextDeviceObject != NULL)
03020         *NextDeviceObject = Adapter->NdisMiniportBlock.NextDeviceObject;
03021 
03022     if (AllocatedResources != NULL)
03023         *AllocatedResources = Adapter->NdisMiniportBlock.AllocatedResources;
03024 
03025     if (AllocatedResourcesTranslated != NULL)
03026         *AllocatedResourcesTranslated = Adapter->NdisMiniportBlock.AllocatedResourcesTranslated;
03027 }
03028 
03029 /*
03030  * @implemented
03031  */
03032 VOID
03033 EXPORT
03034 NdisMRegisterUnloadHandler(
03035     IN  NDIS_HANDLE     NdisWrapperHandle,
03036     IN  PDRIVER_UNLOAD  UnloadHandler)
03037 /*
03038  * FUNCTION:
03039  * ARGUMENTS:
03040  * NOTES:
03041  *    NDIS 5.0
03042  */
03043 {
03044     PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
03045 
03046     NDIS_DbgPrint(MAX_TRACE, ("Miniport registered unload handler\n"));
03047 
03048     DriverBlock->DriverObject->DriverUnload = UnloadHandler;
03049 }
03050 
03051 /*
03052  * @implemented
03053  */
03054 NDIS_STATUS
03055 EXPORT
03056 NdisMRegisterDevice(
03057     IN  NDIS_HANDLE         NdisWrapperHandle,
03058     IN  PNDIS_STRING        DeviceName,
03059     IN  PNDIS_STRING        SymbolicName,
03060     IN  PDRIVER_DISPATCH    MajorFunctions[],
03061     OUT PDEVICE_OBJECT      *pDeviceObject,
03062     OUT NDIS_HANDLE         *NdisDeviceHandle)
03063 /*
03064  * FUNCTION:
03065  * ARGUMENTS:
03066  * NOTES:
03067  *    NDIS 5.0
03068  */
03069 {
03070     PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
03071     PNDIS_M_DEVICE_BLOCK DeviceBlock;
03072     PDEVICE_OBJECT DeviceObject;
03073     NDIS_STATUS Status;
03074     UINT i;
03075 
03076     NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
03077 
03078     Status = IoCreateDevice(DriverBlock->DriverObject,
03079                             0, /* This space is reserved for us. Should we use it? */
03080                             DeviceName,
03081                             FILE_DEVICE_NETWORK,
03082                             0,
03083                             FALSE,
03084                             &DeviceObject);
03085 
03086     if (!NT_SUCCESS(Status))
03087     {
03088         NDIS_DbgPrint(MIN_TRACE, ("IoCreateDevice failed (%x)\n", Status));
03089         return Status;
03090     }
03091     
03092     Status = IoCreateSymbolicLink(SymbolicName, DeviceName);
03093 
03094     if (!NT_SUCCESS(Status))
03095     {
03096         NDIS_DbgPrint(MIN_TRACE, ("IoCreateSymbolicLink failed (%x)\n", Status));
03097         IoDeleteDevice(DeviceObject);
03098         return Status;
03099     }
03100 
03101     DeviceBlock = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DEVICE_BLOCK));
03102 
03103     if (!DeviceBlock)
03104     {
03105         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
03106         IoDeleteDevice(DeviceObject);
03107         IoDeleteSymbolicLink(SymbolicName);
03108         return NDIS_STATUS_RESOURCES;
03109     }
03110 
03111     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
03112          DriverBlock->DriverObject->MajorFunction[i] = MajorFunctions[i];
03113 
03114     DriverBlock->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
03115 
03116     if (!DriverBlock->DriverObject->MajorFunction[IRP_MJ_CREATE])
03117         DriverBlock->DriverObject->MajorFunction[IRP_MJ_CREATE] = NdisICreateClose;
03118 
03119     if (!DriverBlock->DriverObject->MajorFunction[IRP_MJ_CLOSE])
03120         DriverBlock->DriverObject->MajorFunction[IRP_MJ_CLOSE] = NdisICreateClose;
03121 
03122     DeviceBlock->DeviceObject = DeviceObject;
03123     DeviceBlock->SymbolicName = SymbolicName;
03124 
03125     *pDeviceObject = DeviceObject;
03126     *NdisDeviceHandle = DeviceBlock;
03127 
03128     return NDIS_STATUS_SUCCESS;
03129 }
03130 
03131 /*
03132  * @implemented
03133  */
03134 NDIS_STATUS
03135 EXPORT
03136 NdisMDeregisterDevice(
03137     IN  NDIS_HANDLE NdisDeviceHandle)
03138 /*
03139  * FUNCTION:
03140  * ARGUMENTS:
03141  * NOTES:
03142  *    NDIS 5.0
03143  */
03144 {
03145     PNDIS_M_DEVICE_BLOCK DeviceBlock = NdisDeviceHandle;
03146 
03147     IoDeleteDevice(DeviceBlock->DeviceObject);
03148 
03149     IoDeleteSymbolicLink(DeviceBlock->SymbolicName);
03150 
03151     ExFreePool(DeviceBlock);
03152 
03153     return NDIS_STATUS_SUCCESS;
03154 }
03155 
03156 /*
03157  * @implemented
03158  */
03159 NDIS_STATUS
03160 EXPORT
03161 NdisQueryAdapterInstanceName(
03162     OUT PNDIS_STRING    AdapterInstanceName,
03163     IN  NDIS_HANDLE     NdisBindingHandle)
03164 /*
03165  * FUNCTION:
03166  * ARGUMENTS:
03167  * NOTES:
03168  *    NDIS 5.0
03169  */
03170 {
03171     PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
03172     PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
03173 
03174     return NdisMQueryAdapterInstanceName(AdapterInstanceName,
03175                                          Adapter);
03176 }
03177 
03178 /*
03179  * @implemented
03180  */
03181 VOID
03182 EXPORT
03183 NdisCompletePnPEvent(
03184     IN  NDIS_STATUS     Status,
03185     IN  NDIS_HANDLE     NdisBindingHandle,
03186     IN  PNET_PNP_EVENT  NetPnPEvent)
03187 /*
03188  * FUNCTION:
03189  * ARGUMENTS:
03190  * NOTES:
03191  *    NDIS 5.0
03192  */
03193 {
03194   PIRP Irp = (PIRP)NetPnPEvent->NdisReserved[0];
03195   PLIST_ENTRY CurrentEntry = (PLIST_ENTRY)NetPnPEvent->NdisReserved[1];
03196   PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
03197   PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
03198   NDIS_STATUS NdisStatus;
03199 
03200   if (Status != NDIS_STATUS_SUCCESS)
03201   {
03202       if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
03203       ExFreePool(NetPnPEvent);
03204       Irp->IoStatus.Status = Status;
03205       IoCompleteRequest(Irp, IO_NO_INCREMENT);
03206       return;
03207   }
03208 
03209   while (CurrentEntry != &Adapter->ProtocolListHead)
03210   {
03211      AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
03212 
03213      NdisStatus = (*AdapterBinding->ProtocolBinding->Chars.PnPEventHandler)(
03214       AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
03215       NetPnPEvent);
03216 
03217      if (NdisStatus == NDIS_STATUS_PENDING)
03218      {
03219          NetPnPEvent->NdisReserved[1] = (ULONG_PTR)CurrentEntry->Flink;
03220          return;
03221      }
03222      else if (NdisStatus != NDIS_STATUS_SUCCESS)
03223      {
03224          if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
03225          ExFreePool(NetPnPEvent);
03226          Irp->IoStatus.Status = NdisStatus;
03227          IoCompleteRequest(Irp, IO_NO_INCREMENT);
03228          return;
03229      }
03230 
03231      CurrentEntry = CurrentEntry->Flink;
03232   }
03233 
03234   if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
03235   ExFreePool(NetPnPEvent);
03236 
03237   Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
03238   IoCompleteRequest(Irp, IO_NO_INCREMENT);
03239 }
03240 
03241 /*
03242  * @implemented
03243  */
03244 VOID
03245 EXPORT
03246 NdisCancelSendPackets(
03247     IN NDIS_HANDLE  NdisBindingHandle,
03248     IN PVOID  CancelId)
03249 {
03250     PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
03251     PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
03252 
03253     NDIS_DbgPrint(MAX_TRACE, ("Called for ID %x.\n", CancelId));
03254 
03255     if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)
03256     {
03257         (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)(
03258           Adapter->NdisMiniportBlock.MiniportAdapterContext,
03259           CancelId);
03260     }
03261 }
03262 
03263 
03264 /*
03265  * @implemented
03266  */
03267 NDIS_HANDLE
03268 EXPORT
03269 NdisIMGetBindingContext(
03270     IN  NDIS_HANDLE NdisBindingHandle)
03271 /*
03272  * FUNCTION:
03273  * ARGUMENTS:
03274  * NOTES:
03275  *    NDIS 5.0
03276  */
03277 {
03278     PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
03279     PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
03280 
03281     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
03282 
03283     return Adapter->NdisMiniportBlock.DeviceContext;
03284 }
03285 
03286 
03287 /*
03288  * @implemented
03289  */
03290 NDIS_HANDLE
03291 EXPORT
03292 NdisIMGetDeviceContext(
03293     IN  NDIS_HANDLE MiniportAdapterHandle)
03294 /*
03295  * FUNCTION:
03296  * ARGUMENTS:
03297  * NOTES:
03298  *    NDIS 5.0
03299  */
03300 {
03301     PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
03302 
03303     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
03304 
03305     return Adapter->NdisMiniportBlock.DeviceContext;
03306 }
03307 
03308 /* EOF */
03309 

Generated on Sun May 27 2012 04:28:06 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.