Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenminiport.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
1.7.6.1
|