Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlan.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS TCP/IP protocol driver 00004 * FILE: datalink/lan.c 00005 * PURPOSE: Local Area Network media routines 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * REVISIONS: 00008 * CSH 01/08-2000 Created 00009 * arty -- Separate service 09/2004 00010 */ 00011 00012 #include "precomp.h" 00013 00014 ULONG DebugTraceLevel = 0x7ffffff; 00015 PDEVICE_OBJECT LanDeviceObject = NULL; 00016 00017 NDIS_STATUS NDISCall( 00018 PLAN_ADAPTER Adapter, 00019 NDIS_REQUEST_TYPE Type, 00020 NDIS_OID OID, 00021 PVOID Buffer, 00022 UINT Length) 00023 /* 00024 * FUNCTION: Send a request to NDIS 00025 * ARGUMENTS: 00026 * Adapter = Pointer to a LAN_ADAPTER structure 00027 * Type = Type of request (Set or Query) 00028 * OID = Value to be set/queried for 00029 * Buffer = Pointer to a buffer to use 00030 * Length = Number of bytes in Buffer 00031 * RETURNS: 00032 * Status of operation 00033 */ 00034 { 00035 NDIS_REQUEST Request; 00036 NDIS_STATUS NdisStatus; 00037 00038 Request.RequestType = Type; 00039 if (Type == NdisRequestSetInformation) { 00040 Request.DATA.SET_INFORMATION.Oid = OID; 00041 Request.DATA.SET_INFORMATION.InformationBuffer = Buffer; 00042 Request.DATA.SET_INFORMATION.InformationBufferLength = Length; 00043 } else { 00044 Request.DATA.QUERY_INFORMATION.Oid = OID; 00045 Request.DATA.QUERY_INFORMATION.InformationBuffer = Buffer; 00046 Request.DATA.QUERY_INFORMATION.InformationBufferLength = Length; 00047 } 00048 00049 if (Adapter->State != LAN_STATE_RESETTING) { 00050 NdisRequest(&NdisStatus, Adapter->NdisHandle, &Request); 00051 } else { 00052 NdisStatus = NDIS_STATUS_NOT_ACCEPTED; 00053 } 00054 00055 /* Wait for NDIS to complete the request */ 00056 if (NdisStatus == NDIS_STATUS_PENDING) { 00057 KeWaitForSingleObject(&Adapter->Event, 00058 UserRequest, 00059 KernelMode, 00060 FALSE, 00061 NULL); 00062 NdisStatus = Adapter->NdisStatus; 00063 } 00064 00065 return NdisStatus; 00066 } 00067 00068 00069 VOID FreeAdapter( 00070 PLAN_ADAPTER Adapter) 00071 /* 00072 * FUNCTION: Frees memory for a LAN_ADAPTER structure 00073 * ARGUMENTS: 00074 * Adapter = Pointer to LAN_ADAPTER structure to free 00075 */ 00076 { 00077 exFreePool(Adapter); 00078 } 00079 00080 00081 VOID NTAPI ProtocolOpenAdapterComplete( 00082 NDIS_HANDLE BindingContext, 00083 NDIS_STATUS Status, 00084 NDIS_STATUS OpenErrorStatus) 00085 /* 00086 * FUNCTION: Called by NDIS to complete opening of an adapter 00087 * ARGUMENTS: 00088 * BindingContext = Pointer to a device context (LAN_ADAPTER) 00089 * Status = Status of the operation 00090 * OpenErrorStatus = Additional status information 00091 */ 00092 { 00093 PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; 00094 00095 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00096 00097 KeSetEvent(&Adapter->Event, 0, FALSE); 00098 } 00099 00100 00101 VOID NTAPI ProtocolCloseAdapterComplete( 00102 NDIS_HANDLE BindingContext, 00103 NDIS_STATUS Status) 00104 /* 00105 * FUNCTION: Called by NDIS to complete closing an adapter 00106 * ARGUMENTS: 00107 * BindingContext = Pointer to a device context (LAN_ADAPTER) 00108 * Status = Status of the operation 00109 */ 00110 { 00111 PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; 00112 00113 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00114 00115 Adapter->NdisStatus = Status; 00116 00117 KeSetEvent(&Adapter->Event, 0, FALSE); 00118 } 00119 00120 00121 VOID NTAPI ProtocolResetComplete( 00122 NDIS_HANDLE BindingContext, 00123 NDIS_STATUS Status) 00124 /* 00125 * FUNCTION: Called by NDIS to complete resetting an adapter 00126 * ARGUMENTS: 00127 * BindingContext = Pointer to a device context (LAN_ADAPTER) 00128 * Status = Status of the operation 00129 */ 00130 { 00131 LA_DbgPrint(MID_TRACE, ("Called.\n")); 00132 } 00133 00134 00135 VOID NTAPI ProtocolRequestComplete( 00136 NDIS_HANDLE BindingContext, 00137 PNDIS_REQUEST NdisRequest, 00138 NDIS_STATUS Status) 00139 /* 00140 * FUNCTION: Called by NDIS to complete a request 00141 * ARGUMENTS: 00142 * BindingContext = Pointer to a device context (LAN_ADAPTER) 00143 * NdisRequest = Pointer to an object describing the request 00144 * Status = Status of the operation 00145 */ 00146 { 00147 PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; 00148 00149 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00150 00151 /* Save status of request and signal an event */ 00152 Adapter->NdisStatus = Status; 00153 00154 KeSetEvent(&Adapter->Event, 0, FALSE); 00155 } 00156 00157 00158 VOID NTAPI ProtocolSendComplete( 00159 NDIS_HANDLE BindingContext, 00160 PNDIS_PACKET Packet, 00161 NDIS_STATUS Status) 00162 /* 00163 * FUNCTION: Called by NDIS to complete sending process 00164 * ARGUMENTS: 00165 * BindingContext = Pointer to a device context (LAN_ADAPTER) 00166 * Packet = Pointer to a packet descriptor 00167 * Status = Status of the operation 00168 */ 00169 { 00170 /*PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;*/ 00171 00172 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00173 /*(*PC(Packet)->DLComplete)(Adapter->Context, Packet, Status);*/ 00174 LA_DbgPrint(DEBUG_DATALINK, ("Finished\n")); 00175 } 00176 00177 00178 VOID NTAPI ProtocolTransferDataComplete( 00179 NDIS_HANDLE BindingContext, 00180 PNDIS_PACKET Packet, 00181 NDIS_STATUS Status, 00182 UINT BytesTransferred) 00183 /* 00184 * FUNCTION: Called by NDIS to complete reception of data 00185 * ARGUMENTS: 00186 * BindingContext = Pointer to a device context (LAN_ADAPTER) 00187 * Packet = Pointer to a packet descriptor 00188 * Status = Status of the operation 00189 * BytesTransferred = Number of bytes transferred 00190 * NOTES: 00191 * If the packet was successfully received, determine the protocol 00192 * type and pass it to the correct receive handler 00193 */ 00194 { 00195 PLIST_ENTRY ListEntry, ReadListEntry; 00196 PLAN_PROTOCOL Proto; 00197 PLAN_PACKET_HEADER Header; 00198 PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension; 00199 UINT i; 00200 UINT PacketType; 00201 UINT ContigSize; 00202 PIRP ReadIrp; 00203 KIRQL OldIrql; 00204 LAN_PACKET LPPacket; 00205 PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; 00206 00207 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00208 00209 KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); 00210 00211 if (Status == NDIS_STATUS_SUCCESS) { 00212 PNDIS_BUFFER NdisBuffer; 00213 00214 NdisGetFirstBufferFromPacket(Packet, 00215 &NdisBuffer, 00216 &LPPacket.EthHeader, 00217 &ContigSize, 00218 &LPPacket.TotalSize); 00219 00220 LPPacket.TotalSize = BytesTransferred; 00221 00222 /* Determine which upper layer protocol that should receive 00223 this packet and pass it to the correct receive handler */ 00224 00225 /*OskitDumpBuffer( IPPacket.Header, BytesTransferred );*/ 00226 00227 PacketType = LPPacket.EthHeader->EType; 00228 00229 LA_DbgPrint 00230 (DEBUG_DATALINK, 00231 ("Ether Type = %x Total = %d Packet %x Payload %x\n", 00232 PacketType, LPPacket.TotalSize, LPPacket.EthHeader, 00233 LPPacket.EthHeader + 1)); 00234 00235 NdisBuffer->Next = NULL; 00236 00237 for( ListEntry = DeviceExt->ProtocolListHead.Flink; 00238 ListEntry != &DeviceExt->ProtocolListHead; 00239 ListEntry = ListEntry->Flink ) { 00240 Proto = CONTAINING_RECORD(ListEntry, LAN_PROTOCOL, ListEntry); 00241 LA_DbgPrint(MID_TRACE,("Examining protocol %x\n", Proto)); 00242 for( i = 0; i < Proto->NumEtherTypes; i++ ) { 00243 LA_DbgPrint(MID_TRACE,(".Accepts proto %x\n", 00244 Proto->EtherType[i])); 00245 if( Proto->EtherType[i] == PacketType && 00246 !IsListEmpty( &Proto->ReadIrpListHead ) ) { 00247 ReadListEntry = RemoveHeadList( &Proto->ReadIrpListHead ); 00248 ReadIrp = CONTAINING_RECORD(ReadListEntry, IRP, 00249 Tail.Overlay.ListEntry ); 00250 LA_DbgPrint(MID_TRACE,("..Irp %x\n", ReadIrp)); 00251 _SEH2_TRY { 00252 Header = ReadIrp->AssociatedIrp.SystemBuffer; 00253 LA_DbgPrint 00254 (MID_TRACE, 00255 ("Writing packet at %x\n", Header)); 00256 Header->Fixed.Adapter = Adapter->Index; 00257 Header->Fixed.AddressType = Adapter->Media; 00258 Header->Fixed.AddressLen = IEEE_802_ADDR_LENGTH; 00259 Header->Fixed.PacketType = PacketType; 00260 RtlCopyMemory( Header->Address, 00261 LPPacket.EthHeader->SrcAddr, 00262 IEEE_802_ADDR_LENGTH ); 00263 if( Proto->Buffered ) { 00264 LA_DbgPrint(MID_TRACE,("Buffered copy\n")); 00265 RtlCopyMemory 00266 ( Header->Address + 00267 IEEE_802_ADDR_LENGTH, 00268 LPPacket.EthHeader + 1, 00269 LPPacket.TotalSize - 00270 sizeof(*LPPacket.EthHeader) ); 00271 Header->Fixed.Mdl = NULL; 00272 } else 00273 Header->Fixed.Mdl = NdisBuffer; 00274 00275 ReadIrp->IoStatus.Status = 0; 00276 ReadIrp->IoStatus.Information = 00277 (Header->Address + IEEE_802_ADDR_LENGTH + 00278 LPPacket.TotalSize - 00279 sizeof(*LPPacket.EthHeader)) - 00280 (PCHAR)Header; 00281 00282 LA_DbgPrint(MID_TRACE,("Bytes returned %d\n", 00283 ReadIrp->IoStatus.Information)); 00284 00285 IoCompleteRequest( ReadIrp, IO_NETWORK_INCREMENT ); 00286 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 00287 LA_DbgPrint 00288 (MIN_TRACE, 00289 ("Failed write to packet in client\n")); 00290 ReadIrp->IoStatus.Status = STATUS_ACCESS_VIOLATION; 00291 ReadIrp->IoStatus.Information = 0; 00292 IoCompleteRequest( ReadIrp, IO_NETWORK_INCREMENT ); 00293 } _SEH2_END; 00294 break; 00295 } 00296 } 00297 } 00298 } 00299 00300 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 00301 00302 FreeNdisPacket( Packet ); 00303 } 00304 00305 00306 NDIS_STATUS NTAPI ProtocolReceive( 00307 NDIS_HANDLE BindingContext, 00308 NDIS_HANDLE MacReceiveContext, 00309 PVOID HeaderBuffer, 00310 UINT HeaderBufferSize, 00311 PVOID LookaheadBuffer, 00312 UINT LookaheadBufferSize, 00313 UINT PacketSize) 00314 /* 00315 * FUNCTION: Called by NDIS when a packet has been received on the physical link 00316 * ARGUMENTS: 00317 * BindingContext = Pointer to a device context (LAN_ADAPTER) 00318 * MacReceiveContext = Handle used by underlying NIC driver 00319 * HeaderBuffer = Pointer to a buffer containing the packet header 00320 * HeaderBufferSize = Number of bytes in HeaderBuffer 00321 * LookaheadBuffer = Pointer to a buffer containing buffered packet data 00322 * LookaheadBufferSize = Size of LookaheadBuffer. May be less than asked for 00323 * PacketSize = Overall size of the packet (not including header) 00324 * RETURNS: 00325 * Status of operation 00326 */ 00327 { 00328 USHORT EType; 00329 UINT PacketType, BytesTransferred; 00330 PCHAR BufferData; 00331 NDIS_STATUS NdisStatus; 00332 PNDIS_PACKET NdisPacket; 00333 PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; 00334 00335 LA_DbgPrint(DEBUG_DATALINK, ("Called. (packetsize %d)\n",PacketSize)); 00336 00337 if (Adapter->State != LAN_STATE_STARTED) { 00338 LA_DbgPrint(DEBUG_DATALINK, ("Adapter is stopped.\n")); 00339 return NDIS_STATUS_NOT_ACCEPTED; 00340 } 00341 00342 if (HeaderBufferSize < Adapter->HeaderSize) { 00343 LA_DbgPrint(DEBUG_DATALINK, ("Runt frame received.\n")); 00344 return NDIS_STATUS_NOT_ACCEPTED; 00345 } 00346 00347 PacketType = EType; 00348 00349 /* Get a transfer data packet */ 00350 KeAcquireSpinLockAtDpcLevel(&Adapter->Lock); 00351 NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Adapter->MTU ); 00352 if( NdisStatus != NDIS_STATUS_SUCCESS ) { 00353 KeReleaseSpinLockFromDpcLevel(&Adapter->Lock); 00354 return NDIS_STATUS_NOT_ACCEPTED; 00355 } 00356 LA_DbgPrint(DEBUG_DATALINK, ("pretransfer LookaheadBufferSize %d packsize %d\n",LookaheadBufferSize,PacketSize)); 00357 { 00358 UINT temp; 00359 temp = PacketSize; 00360 GetDataPtr( NdisPacket, 0, &BufferData, &temp ); 00361 } 00362 00363 LA_DbgPrint(DEBUG_DATALINK, ("pretransfer LookaheadBufferSize %d HeaderBufferSize %d packsize %d\n",LookaheadBufferSize,HeaderBufferSize,PacketSize)); 00364 /* Get the data */ 00365 NdisTransferData(&NdisStatus, 00366 Adapter->NdisHandle, 00367 MacReceiveContext, 00368 0, 00369 PacketSize + HeaderBufferSize, 00370 NdisPacket, 00371 &BytesTransferred); 00372 00373 LA_DbgPrint(DEBUG_DATALINK, ("Calling complete\n")); 00374 00375 if (NdisStatus != NDIS_STATUS_PENDING) 00376 ProtocolTransferDataComplete(BindingContext, 00377 NdisPacket, 00378 NdisStatus, 00379 PacketSize + HeaderBufferSize); 00380 00381 /* Release the packet descriptor */ 00382 KeReleaseSpinLockFromDpcLevel(&Adapter->Lock); 00383 LA_DbgPrint(DEBUG_DATALINK, ("leaving\n")); 00384 00385 return NDIS_STATUS_SUCCESS; 00386 } 00387 00388 00389 VOID NTAPI ProtocolReceiveComplete( 00390 NDIS_HANDLE BindingContext) 00391 /* 00392 * FUNCTION: Called by NDIS when we're done receiving data 00393 * ARGUMENTS: 00394 * BindingContext = Pointer to a device context (LAN_ADAPTER) 00395 */ 00396 { 00397 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00398 } 00399 00400 00401 VOID NTAPI ProtocolStatus( 00402 NDIS_HANDLE BindingContext, 00403 NDIS_STATUS GenerelStatus, 00404 PVOID StatusBuffer, 00405 UINT StatusBufferSize) 00406 /* 00407 * FUNCTION: Called by NDIS when the underlying driver has changed state 00408 * ARGUMENTS: 00409 * BindingContext = Pointer to a device context (LAN_ADAPTER) 00410 * GenerelStatus = A generel status code 00411 * StatusBuffer = Pointer to a buffer with medium-specific data 00412 * StatusBufferSize = Number of bytes in StatusBuffer 00413 */ 00414 { 00415 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00416 } 00417 00418 00419 VOID NTAPI ProtocolStatusComplete( 00420 NDIS_HANDLE NdisBindingContext) 00421 /* 00422 * FUNCTION: Called by NDIS when a status-change has occurred 00423 * ARGUMENTS: 00424 * BindingContext = Pointer to a device context (LAN_ADAPTER) 00425 */ 00426 { 00427 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00428 } 00429 00430 VOID NTAPI ProtocolBindAdapter( 00431 OUT PNDIS_STATUS Status, 00432 IN NDIS_HANDLE BindContext, 00433 IN PNDIS_STRING DeviceName, 00434 IN PVOID SystemSpecific1, 00435 IN PVOID SystemSpecific2) 00436 /* 00437 * FUNCTION: Called by NDIS during NdisRegisterProtocol to set up initial 00438 * bindings, and periodically thereafer as new adapters come online 00439 * ARGUMENTS: 00440 * Status: Return value to NDIS 00441 * BindContext: Handle provided by NDIS to track pending binding operations 00442 * DeviceName: Name of the miniport device to bind to 00443 * SystemSpecific1: Pointer to a registry path with protocol-specific configuration information 00444 * SystemSpecific2: Unused & must not be touched 00445 */ 00446 { 00447 /* XXX confirm that this is still true, or re-word the following comment */ 00448 /* we get to ignore BindContext because we will never pend an operation with NDIS */ 00449 LA_DbgPrint(DEBUG_DATALINK, ("Called with registry path %wZ\n", SystemSpecific1)); 00450 *Status = LANRegisterAdapter(DeviceName, SystemSpecific1); 00451 } 00452 00453 00454 VOID LANTransmit( 00455 PLAN_ADAPTER Adapter, 00456 PNDIS_PACKET NdisPacket, 00457 PVOID LinkAddress, 00458 USHORT Type) 00459 /* 00460 * FUNCTION: Transmits a packet 00461 * ARGUMENTS: 00462 * Context = Pointer to context information (LAN_ADAPTER) 00463 * NdisPacket = Pointer to NDIS packet to send 00464 * LinkAddress = Pointer to link address of destination (NULL = broadcast) 00465 * Type = LAN protocol type (LAN_PROTO_*) 00466 */ 00467 { 00468 NDIS_STATUS NdisStatus; 00469 00470 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00471 00472 if (Adapter->State == LAN_STATE_STARTED) { 00473 NdisSend(&NdisStatus, Adapter->NdisHandle, NdisPacket); 00474 if (NdisStatus != NDIS_STATUS_PENDING) 00475 ProtocolSendComplete((NDIS_HANDLE)Adapter, NdisPacket, NdisStatus); 00476 } else { 00477 ProtocolSendComplete((NDIS_HANDLE)Adapter, NdisPacket, NDIS_STATUS_CLOSED); 00478 } 00479 } 00480 00481 /* For use internally */ 00482 UINT LANTransmitInternal(PLAN_PACKET_HEADER ToWrite, UINT OverallLength) { 00483 NDIS_STATUS NdisStatus; 00484 PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension; 00485 PLAN_ADAPTER Adapter; 00486 PETH_HEADER EthHeader; 00487 KIRQL OldIrql; 00488 PNDIS_PACKET NdisPacket; 00489 UINT Size, PayloadSize = OverallLength - 00490 ((ToWrite->Address + ToWrite->Fixed.AddressLen) - (PCHAR)ToWrite); 00491 00492 NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, 00493 PayloadSize + sizeof(ETH_HEADER) ); 00494 00495 KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); 00496 00497 if( !NT_SUCCESS(NdisStatus) ) goto end; 00498 00499 Adapter = FindAdapterByIndex( DeviceExt, ToWrite->Fixed.Adapter ); 00500 00501 if( !Adapter ) goto end; 00502 00503 GetDataPtr( NdisPacket, 0, (PCHAR *)&EthHeader, &Size ); 00504 if( !EthHeader ) goto end; 00505 00506 LA_DbgPrint(MID_TRACE,("Writing %d bytes of Dst\n", 00507 ToWrite->Fixed.AddressLen)); 00508 00509 /* Handle broadcast for other media types here */ 00510 if( ToWrite->Fixed.AddressLen ) 00511 RtlCopyMemory( EthHeader->DstAddr, 00512 ToWrite->Address, 00513 ToWrite->Fixed.AddressLen ); 00514 else 00515 memset( EthHeader->DstAddr, -1, sizeof(EthHeader->DstAddr) ); 00516 00517 LA_DbgPrint(MID_TRACE,("Writing %d bytes of Src\n", Adapter->HWAddressLength)); 00518 RtlCopyMemory( EthHeader->SrcAddr, 00519 Adapter->HWAddress, 00520 Adapter->HWAddressLength ); 00521 LA_DbgPrint(MID_TRACE,("Writing %d bytes of payload\n", PayloadSize)); 00522 EthHeader->EType = ToWrite->Fixed.PacketType; 00523 RtlCopyMemory( EthHeader + 1, 00524 ToWrite->Address + ToWrite->Fixed.AddressLen, 00525 PayloadSize ); 00526 00527 LANTransmit( Adapter, NdisPacket, ToWrite->Address, 00528 ToWrite->Fixed.PacketType ); 00529 00530 end: 00531 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 00532 00533 return OverallLength; 00534 } 00535 00536 VOID BindAdapter(PLAN_ADAPTER Adapter, PNDIS_STRING RegistryPath) 00537 /* 00538 * FUNCTION: Binds a LAN adapter to IP layer 00539 * ARGUMENTS: 00540 * Adapter = Pointer to LAN_ADAPTER structure 00541 * NOTES: 00542 * We set the lookahead buffer size, set the packet filter and 00543 * bind the adapter to IP layer 00544 */ 00545 { 00546 /*NDIS_STATUS NdisStatus;*/ 00547 /*ULONG Lookahead = LOOKAHEAD_SIZE;*/ 00548 /*NTSTATUS Status;*/ 00549 /*HANDLE RegHandle = 0;*/ 00550 00551 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00552 00553 } 00554 00555 NDIS_STATUS LANRegisterAdapter( PNDIS_STRING AdapterName, 00556 PNDIS_STRING RegistryPath) 00557 /* 00558 * FUNCTION: Registers protocol with an NDIS adapter 00559 * ARGUMENTS: 00560 * AdapterName = Pointer to string with name of adapter to register 00561 * Adapter = Address of pointer to a LAN_ADAPTER structure 00562 * RETURNS: 00563 * Status of operation 00564 */ 00565 { 00566 PLAN_ADAPTER Adapter; 00567 NDIS_MEDIUM MediaArray[MAX_MEDIA]; 00568 NDIS_STATUS NdisStatus; 00569 NDIS_STATUS OpenStatus; 00570 UINT MediaIndex; 00571 UINT AddressOID; 00572 UINT Speed; 00573 PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension; 00574 00575 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00576 00577 Adapter = exAllocatePool(NonPagedPool, sizeof(LAN_ADAPTER)); 00578 if (!Adapter) { 00579 LA_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); 00580 return NDIS_STATUS_RESOURCES; 00581 } 00582 00583 RtlZeroMemory(Adapter, sizeof(LAN_ADAPTER)); 00584 00585 /* Put adapter in stopped state */ 00586 Adapter->State = LAN_STATE_STOPPED; 00587 Adapter->Index = DeviceExt->AdapterId++; 00588 00589 InitializeListHead( &Adapter->AddressList ); 00590 InitializeListHead( &Adapter->ForeignList ); 00591 00592 /* Initialize protecting spin lock */ 00593 KeInitializeSpinLock(&Adapter->Lock); 00594 00595 KeInitializeEvent(&Adapter->Event, SynchronizationEvent, FALSE); 00596 00597 /* Initialize array with media IDs we support */ 00598 MediaArray[MEDIA_ETH] = NdisMedium802_3; 00599 00600 LA_DbgPrint(DEBUG_DATALINK,("opening adapter %wZ\n", AdapterName)); 00601 /* Open the adapter. */ 00602 NdisOpenAdapter(&NdisStatus, 00603 &OpenStatus, 00604 &Adapter->NdisHandle, 00605 &MediaIndex, 00606 MediaArray, 00607 MAX_MEDIA, 00608 DeviceExt->NdisProtocolHandle, 00609 Adapter, 00610 AdapterName, 00611 0, 00612 NULL); 00613 00614 /* Wait until the adapter is opened */ 00615 if (NdisStatus == NDIS_STATUS_PENDING) 00616 KeWaitForSingleObject(&Adapter->Event, UserRequest, KernelMode, FALSE, NULL); 00617 else if (NdisStatus != NDIS_STATUS_SUCCESS) { 00618 exFreePool(Adapter); 00619 return NdisStatus; 00620 } 00621 00622 Adapter->Media = MediaArray[MediaIndex]; 00623 00624 /* Fill LAN_ADAPTER structure with some adapter specific information */ 00625 switch (Adapter->Media) { 00626 case NdisMedium802_3: 00627 Adapter->HWAddressLength = IEEE_802_ADDR_LENGTH; 00628 Adapter->BCastMask = BCAST_ETH_MASK; 00629 Adapter->BCastCheck = BCAST_ETH_CHECK; 00630 Adapter->BCastOffset = BCAST_ETH_OFFSET; 00631 Adapter->HeaderSize = sizeof(ETH_HEADER); 00632 Adapter->MinFrameSize = 60; 00633 AddressOID = OID_802_3_CURRENT_ADDRESS; 00634 Adapter->PacketFilter = 00635 NDIS_PACKET_TYPE_BROADCAST | 00636 NDIS_PACKET_TYPE_DIRECTED | 00637 NDIS_PACKET_TYPE_MULTICAST; 00638 break; 00639 00640 default: 00641 /* Unsupported media */ 00642 LA_DbgPrint(MIN_TRACE, ("Unsupported media.\n")); 00643 exFreePool(Adapter); 00644 return NDIS_STATUS_NOT_SUPPORTED; 00645 } 00646 00647 /* Get maximum frame size */ 00648 NdisStatus = NDISCall(Adapter, 00649 NdisRequestQueryInformation, 00650 OID_GEN_MAXIMUM_FRAME_SIZE, 00651 &Adapter->MTU, 00652 sizeof(UINT)); 00653 if (NdisStatus != NDIS_STATUS_SUCCESS) { 00654 exFreePool(Adapter); 00655 return NdisStatus; 00656 } 00657 00658 /* Get maximum packet size */ 00659 NdisStatus = NDISCall(Adapter, 00660 NdisRequestQueryInformation, 00661 OID_GEN_MAXIMUM_TOTAL_SIZE, 00662 &Adapter->MaxPacketSize, 00663 sizeof(UINT)); 00664 if (NdisStatus != NDIS_STATUS_SUCCESS) { 00665 LA_DbgPrint(MIN_TRACE, ("Query for maximum packet size failed.\n")); 00666 exFreePool(Adapter); 00667 return NdisStatus; 00668 } 00669 00670 /* Get maximum number of packets we can pass to NdisSend(Packets) at one time */ 00671 NdisStatus = NDISCall(Adapter, 00672 NdisRequestQueryInformation, 00673 OID_GEN_MAXIMUM_SEND_PACKETS, 00674 &Adapter->MaxSendPackets, 00675 sizeof(UINT)); 00676 if (NdisStatus != NDIS_STATUS_SUCCESS) 00677 /* Legacy NIC drivers may not support this query, if it fails we 00678 assume it can send at least one packet per call to NdisSend(Packets) */ 00679 Adapter->MaxSendPackets = 1; 00680 00681 /* Get current hardware address */ 00682 NdisStatus = NDISCall(Adapter, 00683 NdisRequestQueryInformation, 00684 AddressOID, 00685 Adapter->HWAddress, 00686 Adapter->HWAddressLength); 00687 if (NdisStatus != NDIS_STATUS_SUCCESS) { 00688 LA_DbgPrint(MIN_TRACE, ("Query for current hardware address failed.\n")); 00689 exFreePool(Adapter); 00690 return NdisStatus; 00691 } 00692 00693 /* Get maximum link speed */ 00694 NdisStatus = NDISCall(Adapter, 00695 NdisRequestQueryInformation, 00696 OID_GEN_LINK_SPEED, 00697 &Speed, 00698 sizeof(UINT)); 00699 if (NdisStatus != NDIS_STATUS_SUCCESS) { 00700 LA_DbgPrint(MIN_TRACE, ("Query for maximum link speed failed.\n")); 00701 exFreePool(Adapter); 00702 return NdisStatus; 00703 } 00704 00705 /* Convert returned link speed to bps (it is in 100bps increments) */ 00706 Adapter->Speed = Speed * 100L; 00707 00708 /* Add adapter to the adapter list */ 00709 ExInterlockedInsertTailList(&DeviceExt->AdapterListHead, 00710 &Adapter->ListEntry, 00711 &DeviceExt->Lock); 00712 00713 Adapter->RegistryPath.Buffer = 00714 ExAllocatePool( NonPagedPool, RegistryPath->MaximumLength ); 00715 if( !Adapter->RegistryPath.Buffer ) 00716 return NDIS_STATUS_RESOURCES; 00717 00718 RtlCopyUnicodeString( &Adapter->RegistryPath, 00719 RegistryPath ); 00720 00721 NdisStatus = NDISCall(Adapter, 00722 NdisRequestSetInformation, 00723 OID_GEN_CURRENT_LOOKAHEAD, 00724 &Adapter->Lookahead, 00725 sizeof(ULONG)); 00726 if (NdisStatus != NDIS_STATUS_SUCCESS) { 00727 LA_DbgPrint(MID_TRACE, 00728 ("Could not set lookahead buffer size (0x%X).\n", 00729 NdisStatus)); 00730 return NdisStatus; 00731 } 00732 00733 /* Set packet filter so we can send and receive packets */ 00734 NdisStatus = NDISCall(Adapter, 00735 NdisRequestSetInformation, 00736 OID_GEN_CURRENT_PACKET_FILTER, 00737 &Adapter->PacketFilter, 00738 sizeof(UINT)); 00739 if (NdisStatus != NDIS_STATUS_SUCCESS) { 00740 LA_DbgPrint(MID_TRACE, ("Could not set packet filter (0x%X).\n", 00741 NdisStatus)); 00742 return NdisStatus; 00743 } 00744 00745 Adapter->State = LAN_STATE_STARTED; 00746 00747 LA_DbgPrint(DEBUG_DATALINK, ("Leaving.\n")); 00748 00749 return NDIS_STATUS_SUCCESS; 00750 } 00751 00752 00753 NDIS_STATUS LANUnregisterAdapter( 00754 PLAN_ADAPTER Adapter) 00755 /* 00756 * FUNCTION: Unregisters protocol with NDIS adapter 00757 * ARGUMENTS: 00758 * Adapter = Pointer to a LAN_ADAPTER structure 00759 * RETURNS: 00760 * Status of operation 00761 */ 00762 { 00763 KIRQL OldIrql; 00764 NDIS_HANDLE NdisHandle; 00765 NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; 00766 00767 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00768 00769 /* Unlink the adapter from the list */ 00770 RemoveEntryList(&Adapter->ListEntry); 00771 00772 KeAcquireSpinLock(&Adapter->Lock, &OldIrql); 00773 NdisHandle = Adapter->NdisHandle; 00774 if (NdisHandle) { 00775 Adapter->NdisHandle = NULL; 00776 KeReleaseSpinLock(&Adapter->Lock, OldIrql); 00777 00778 NdisCloseAdapter(&NdisStatus, NdisHandle); 00779 if (NdisStatus == NDIS_STATUS_PENDING) { 00780 KeWaitForSingleObject(&Adapter->Event, 00781 UserRequest, 00782 KernelMode, 00783 FALSE, 00784 NULL); 00785 NdisStatus = Adapter->NdisStatus; 00786 } 00787 } else 00788 KeReleaseSpinLock(&Adapter->Lock, OldIrql); 00789 00790 FreeAdapter(Adapter); 00791 00792 return NDIS_STATUS_SUCCESS; 00793 } 00794 00795 NTSTATUS LANRegisterProtocol(PNDIS_STRING Name) 00796 /* 00797 * FUNCTION: Registers this protocol driver with NDIS 00798 * ARGUMENTS: 00799 * Name = Name of this protocol driver 00800 * RETURNS: 00801 * Status of operation 00802 */ 00803 { 00804 NDIS_STATUS NdisStatus; 00805 NDIS_PROTOCOL_CHARACTERISTICS ProtChars; 00806 PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension; 00807 00808 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00809 00810 InitializeListHead(&DeviceExt->AdapterListHead); 00811 InitializeListHead(&DeviceExt->ProtocolListHead); 00812 00813 /* Set up protocol characteristics */ 00814 RtlZeroMemory(&ProtChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); 00815 ProtChars.MajorNdisVersion = NDIS_VERSION_MAJOR; 00816 ProtChars.MinorNdisVersion = NDIS_VERSION_MINOR; 00817 ProtChars.Name.Length = Name->Length; 00818 ProtChars.Name.Buffer = Name->Buffer; 00819 ProtChars.Name.MaximumLength = Name->MaximumLength; 00820 ProtChars.OpenAdapterCompleteHandler = ProtocolOpenAdapterComplete; 00821 ProtChars.CloseAdapterCompleteHandler = ProtocolCloseAdapterComplete; 00822 ProtChars.ResetCompleteHandler = ProtocolResetComplete; 00823 ProtChars.RequestCompleteHandler = ProtocolRequestComplete; 00824 ProtChars.SendCompleteHandler = ProtocolSendComplete; 00825 ProtChars.TransferDataCompleteHandler = ProtocolTransferDataComplete; 00826 ProtChars.ReceiveHandler = ProtocolReceive; 00827 ProtChars.ReceiveCompleteHandler = ProtocolReceiveComplete; 00828 ProtChars.StatusHandler = ProtocolStatus; 00829 ProtChars.StatusCompleteHandler = ProtocolStatusComplete; 00830 ProtChars.BindAdapterHandler = ProtocolBindAdapter; 00831 00832 /* Try to register protocol */ 00833 NdisRegisterProtocol(&NdisStatus, 00834 &DeviceExt->NdisProtocolHandle, 00835 &ProtChars, 00836 sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); 00837 if (NdisStatus != NDIS_STATUS_SUCCESS) 00838 { 00839 LA_DbgPrint(MID_TRACE, ("NdisRegisterProtocol failed, status 0x%x\n", NdisStatus)); 00840 return (NTSTATUS)NdisStatus; 00841 } 00842 00843 return STATUS_SUCCESS; 00844 } 00845 00846 00847 VOID LANUnregisterProtocol(VOID) 00848 /* 00849 * FUNCTION: Unregisters this protocol driver with NDIS 00850 * NOTES: Does not care wether we are already registered 00851 */ 00852 { 00853 PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension; 00854 00855 LA_DbgPrint(DEBUG_DATALINK, ("Called.\n")); 00856 00857 NDIS_STATUS NdisStatus; 00858 PLIST_ENTRY CurrentEntry; 00859 PLIST_ENTRY NextEntry; 00860 PLAN_ADAPTER Current; 00861 KIRQL OldIrql; 00862 00863 KeAcquireSpinLock(&DeviceExt->Lock, &OldIrql); 00864 00865 /* Search the list and remove every adapter we find */ 00866 CurrentEntry = DeviceExt->AdapterListHead.Flink; 00867 while (CurrentEntry != &DeviceExt->AdapterListHead) { 00868 NextEntry = CurrentEntry->Flink; 00869 Current = CONTAINING_RECORD(CurrentEntry, LAN_ADAPTER, ListEntry); 00870 /* Unregister it */ 00871 LANUnregisterAdapter(Current); 00872 CurrentEntry = NextEntry; 00873 } 00874 00875 NdisDeregisterProtocol(&NdisStatus, DeviceExt->NdisProtocolHandle); 00876 } 00877 00878 NTSTATUS NTAPI 00879 LanCreateProtocol( PDEVICE_OBJECT DeviceObject, PIRP Irp, 00880 PIO_STACK_LOCATION IrpSp ) { 00881 PLAN_PROTOCOL Proto; 00882 PFILE_FULL_EA_INFORMATION EaInfo; 00883 PLAN_DEVICE_EXT DeviceExt = 00884 (PLAN_DEVICE_EXT)DeviceObject->DeviceExtension; 00885 PFILE_OBJECT FileObject = IrpSp->FileObject; 00886 PCHAR ProtoNumbersToMatch; 00887 UINT Size = sizeof( *Proto ); 00888 NTSTATUS Status = STATUS_SUCCESS; 00889 00890 EaInfo = Irp->AssociatedIrp.SystemBuffer; 00891 Size += EaInfo->EaValueLength; 00892 Proto = ExAllocatePool( NonPagedPool, Size ); 00893 00894 if( !Proto ) { 00895 Status = Irp->IoStatus.Status = STATUS_NO_MEMORY; 00896 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); 00897 return Status; 00898 } 00899 00900 RtlZeroMemory( Proto, Size ); 00901 00902 Proto->Id = DeviceExt->ProtoId++; 00903 Proto->NumEtherTypes = EaInfo->EaValueLength / sizeof(USHORT); 00904 ProtoNumbersToMatch = EaInfo->EaName + EaInfo->EaNameLength + 1; 00905 00906 LA_DbgPrint(MID_TRACE,("NumEtherTypes: %d\n", Proto->NumEtherTypes)); 00907 00908 RtlCopyMemory( Proto->EtherType, 00909 ProtoNumbersToMatch, 00910 sizeof(USHORT) * Proto->NumEtherTypes ); 00911 00912 InitializeListHead( &Proto->ReadIrpListHead ); 00913 00914 FileObject->FsContext = Proto; 00915 00916 LA_DbgPrint(MID_TRACE,("DeviceExt: %x, Proto %x\n", DeviceExt, Proto)); 00917 00918 ExInterlockedInsertTailList( &DeviceExt->ProtocolListHead, 00919 &Proto->ListEntry, 00920 &DeviceExt->Lock ); 00921 00922 Irp->IoStatus.Information = 0; 00923 Irp->IoStatus.Status = STATUS_SUCCESS; 00924 00925 LA_DbgPrint(MID_TRACE,("Status %x\n", Irp->IoStatus.Status)); 00926 00927 IoCompleteRequest( Irp, IO_NO_INCREMENT ); 00928 return STATUS_SUCCESS; 00929 } 00930 00931 NTSTATUS NTAPI 00932 LanCloseProtocol( PDEVICE_OBJECT DeviceObject, PIRP Irp, 00933 PIO_STACK_LOCATION IrpSp ) { 00934 PLAN_DEVICE_EXT DeviceExt = 00935 (PLAN_DEVICE_EXT)DeviceObject->DeviceExtension; 00936 PFILE_OBJECT FileObject = IrpSp->FileObject; 00937 PLAN_PROTOCOL Proto = FileObject->FsContext; 00938 KIRQL OldIrql; 00939 PLIST_ENTRY ReadIrpListEntry; 00940 PIRP ReadIrp; 00941 NTSTATUS Status; 00942 00943 LA_DbgPrint(MID_TRACE,("Called\n")); 00944 00945 KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); 00946 00947 while( !IsListEmpty( &Proto->ReadIrpListHead ) ) { 00948 ReadIrpListEntry = RemoveHeadList( &Proto->ReadIrpListHead ); 00949 00950 ReadIrp = CONTAINING_RECORD( ReadIrpListEntry, IRP, 00951 Tail.Overlay.ListEntry ); 00952 ReadIrp->IoStatus.Information = 0; 00953 ReadIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; 00954 IoCompleteRequest( ReadIrp, IO_NO_INCREMENT ); 00955 } 00956 00957 RemoveEntryList( &Proto->ListEntry ); 00958 00959 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 00960 00961 LA_DbgPrint(MID_TRACE,("Deleting %x\n")); 00962 00963 ExFreePool( Proto ); 00964 00965 Status = Irp->IoStatus.Status = STATUS_SUCCESS; 00966 IoCompleteRequest( Irp, IO_NO_INCREMENT ); 00967 return Status; 00968 } 00969 00970 PLAN_ADAPTER FindAdapterByIndex( PLAN_DEVICE_EXT DeviceExt, UINT Index ) { 00971 PLIST_ENTRY ListEntry; 00972 PLAN_ADAPTER Current, Target = NULL; 00973 00974 for( ListEntry = DeviceExt->AdapterListHead.Flink; 00975 ListEntry != &DeviceExt->AdapterListHead; 00976 ListEntry = ListEntry->Flink ) { 00977 Current = CONTAINING_RECORD(ListEntry, LAN_ADAPTER, ListEntry); 00978 if( Current->Index == Index ) { 00979 Target = Current; 00980 break; 00981 } 00982 } 00983 00984 return Target; 00985 } 00986 00987 /* Write data to an adapter: 00988 * |<- 16 >| |<-- variable ... -->| 00989 * [indx] [addrtype] [addrlen ] [ptype] [packet-data ...] 00990 */ 00991 NTSTATUS NTAPI 00992 LanWriteData( PDEVICE_OBJECT DeviceObject, PIRP Irp, 00993 PIO_STACK_LOCATION IrpSp ) { 00994 PLAN_PACKET_HEADER ToWrite = Irp->AssociatedIrp.SystemBuffer; 00995 NTSTATUS Status = STATUS_SUCCESS; 00996 00997 LA_DbgPrint(MID_TRACE,("Called\n")); 00998 00999 Irp->IoStatus.Information = 01000 LANTransmitInternal( ToWrite, IrpSp->Parameters.Write.Length ); 01001 Irp->IoStatus.Status = Status; 01002 01003 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); 01004 return Status; 01005 } 01006 01007 NTSTATUS NTAPI 01008 LanReadData( PDEVICE_OBJECT DeviceObject, PIRP Irp, 01009 PIO_STACK_LOCATION IrpSp ) { 01010 PLAN_DEVICE_EXT DeviceExt = 01011 (PLAN_DEVICE_EXT)DeviceObject->DeviceExtension; 01012 PFILE_OBJECT FileObject = IrpSp->FileObject; 01013 PLAN_PROTOCOL Proto = FileObject->FsContext; 01014 01015 LA_DbgPrint(MID_TRACE,("Called on %x (%x)\n", Proto, Irp)); 01016 01017 ExInterlockedInsertTailList( &Proto->ReadIrpListHead, 01018 &Irp->Tail.Overlay.ListEntry, 01019 &DeviceExt->Lock ); 01020 01021 LA_DbgPrint(MID_TRACE,("List: %x %x\n", 01022 Proto->ReadIrpListHead.Flink, 01023 Irp->Tail.Overlay.ListEntry.Flink)); 01024 01025 IoMarkIrpPending( Irp ); 01026 return STATUS_PENDING; 01027 } 01028 01029 NTSTATUS NTAPI 01030 LanEnumAdapters( PDEVICE_OBJECT DeviceObject, PIRP Irp, 01031 PIO_STACK_LOCATION IrpSp ) { 01032 PLIST_ENTRY ListEntry; 01033 PLAN_DEVICE_EXT DeviceExt = 01034 (PLAN_DEVICE_EXT)DeviceObject->DeviceExtension; 01035 NTSTATUS Status = STATUS_SUCCESS; 01036 PLAN_ADAPTER Adapter; 01037 UINT AdapterCount = 0; 01038 PUINT Output = Irp->AssociatedIrp.SystemBuffer; 01039 KIRQL OldIrql; 01040 01041 LA_DbgPrint(MID_TRACE,("Called\n")); 01042 01043 KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); 01044 01045 for( ListEntry = DeviceExt->AdapterListHead.Flink; 01046 ListEntry != &DeviceExt->AdapterListHead; 01047 ListEntry = ListEntry->Flink ) AdapterCount++; 01048 01049 if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= 01050 AdapterCount * sizeof(UINT) ) { 01051 for( ListEntry = DeviceExt->AdapterListHead.Flink; 01052 ListEntry != &DeviceExt->AdapterListHead; 01053 ListEntry = ListEntry->Flink ) { 01054 Adapter = CONTAINING_RECORD(ListEntry, LAN_ADAPTER, ListEntry); 01055 *Output++ = Adapter->Index; 01056 } 01057 } else Status = STATUS_BUFFER_TOO_SMALL; 01058 01059 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 01060 01061 LA_DbgPrint(MID_TRACE,("Ending\n")); 01062 01063 Irp->IoStatus.Status = Status; 01064 Irp->IoStatus.Information = (PCHAR)Output - 01065 (PCHAR)Irp->AssociatedIrp.SystemBuffer; 01066 01067 IoCompleteRequest( Irp, IO_NO_INCREMENT ); 01068 01069 return Status; 01070 } 01071 01072 NTSTATUS NTAPI 01073 LanAdapterInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp, 01074 PIO_STACK_LOCATION IrpSp ) { 01075 PLAN_DEVICE_EXT DeviceExt = 01076 (PLAN_DEVICE_EXT)DeviceObject->DeviceExtension; 01077 PLAN_ADAPTER Adapter; 01078 PLAN_ADDRESS_C Address; 01079 PUINT AdapterIndexPtr = Irp->AssociatedIrp.SystemBuffer; 01080 PLIST_ENTRY ListEntry; 01081 UINT BytesNeeded = sizeof( LAN_ADAPTER_INFO ), AddrSize; 01082 NTSTATUS Status = STATUS_SUCCESS; 01083 PCHAR Writing = Irp->AssociatedIrp.SystemBuffer; 01084 PLAN_ADAPTER_INFO_S Info; 01085 KIRQL OldIrql; 01086 01087 LA_DbgPrint(MID_TRACE,("Called\n")); 01088 01089 KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); 01090 01091 if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < 01092 sizeof(*AdapterIndexPtr) ) 01093 Adapter = NULL; 01094 else 01095 Adapter = FindAdapterByIndex( DeviceExt, *AdapterIndexPtr ); 01096 01097 if( Adapter ) { 01098 /* Local Addresses */ 01099 for( ListEntry = Adapter->AddressList.Flink; 01100 ListEntry != &Adapter->AddressList; 01101 ListEntry = ListEntry->Flink ) { 01102 Address = CONTAINING_RECORD(ListEntry, LAN_ADDRESS_C, ListEntry); 01103 BytesNeeded += LAN_ADDR_SIZE(Address->ClientPart.AddressLen, 01104 Address->ClientPart.HWAddressLen); 01105 } 01106 01107 /* Foreign Addresses */ 01108 for( ListEntry = Adapter->ForeignList.Flink; 01109 ListEntry != &Adapter->ForeignList; 01110 ListEntry = ListEntry->Flink ) { 01111 Address = CONTAINING_RECORD(ListEntry, LAN_ADDRESS_C, ListEntry); 01112 BytesNeeded += LAN_ADDR_SIZE(Address->ClientPart.AddressLen, 01113 Address->ClientPart.HWAddressLen); 01114 } 01115 BytesNeeded += Adapter->RegistryPath.Length; 01116 01117 if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= 01118 BytesNeeded ) { 01119 /* Write common info */ 01120 Info = (PLAN_ADAPTER_INFO_S)Writing; 01121 Info->Index = Adapter->Index; 01122 Info->Media = Adapter->Media; 01123 Info->Speed = Adapter->Speed; 01124 /* Ethernet specific XXX */ 01125 Info->AddressLen = IEEE_802_ADDR_LENGTH; 01126 Info->Overhead = Adapter->HeaderSize; 01127 Info->MTU = Adapter->MTU; 01128 Info->RegKeySize = Adapter->RegistryPath.Length; 01129 01130 /* Copy the name */ 01131 Writing += sizeof(*Info); 01132 RtlCopyMemory( Adapter->RegistryPath.Buffer, 01133 Writing, 01134 Adapter->RegistryPath.Length ); 01135 01136 /* Write the address info */ 01137 Writing += Adapter->RegistryPath.Length; 01138 01139 for( ListEntry = Adapter->AddressList.Flink; 01140 ListEntry != &Adapter->AddressList; 01141 ListEntry = ListEntry->Flink ) { 01142 Address = CONTAINING_RECORD(ListEntry, LAN_ADDRESS_C, 01143 ListEntry); 01144 AddrSize = LAN_ADDR_SIZE(Address->ClientPart.AddressLen, 01145 Address->ClientPart.HWAddressLen); 01146 RtlCopyMemory( Writing, &Address->ClientPart, AddrSize ); 01147 Writing += AddrSize; 01148 } 01149 01150 for( ListEntry = Adapter->ForeignList.Flink; 01151 ListEntry != &Adapter->ForeignList; 01152 ListEntry = ListEntry->Flink ) { 01153 Address = CONTAINING_RECORD(ListEntry, LAN_ADDRESS_C, 01154 ListEntry); 01155 AddrSize = LAN_ADDR_SIZE(Address->ClientPart.AddressLen, 01156 Address->ClientPart.HWAddressLen); 01157 RtlCopyMemory( Writing, &Address->ClientPart, AddrSize ); 01158 Writing += AddrSize; 01159 } 01160 01161 ASSERT( BytesNeeded == Writing - Irp->AssociatedIrp.SystemBuffer ); 01162 } else Status = STATUS_BUFFER_TOO_SMALL; 01163 } else Status = STATUS_NO_SUCH_DEVICE; 01164 01165 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 01166 01167 LA_DbgPrint(MID_TRACE,("Ending (%d bytes)\n", BytesNeeded)); 01168 01169 Irp->IoStatus.Status = Status; 01170 Irp->IoStatus.Information = BytesNeeded; 01171 01172 IoCompleteRequest( Irp, IO_NO_INCREMENT ); 01173 01174 return Status; 01175 } 01176 01177 NTSTATUS NTAPI 01178 LanSetBufferedMode( PDEVICE_OBJECT DeviceObject, PIRP Irp, 01179 PIO_STACK_LOCATION IrpSp ) { 01180 PLAN_DEVICE_EXT DeviceExt = 01181 (PLAN_DEVICE_EXT)DeviceObject->DeviceExtension; 01182 PFILE_OBJECT FileObject = IrpSp->FileObject; 01183 PLAN_PROTOCOL Proto = FileObject->FsContext; 01184 NTSTATUS Status = STATUS_SUCCESS; 01185 KIRQL OldIrql; 01186 01187 LA_DbgPrint(MID_TRACE,("Called %x\n", Proto)); 01188 01189 KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); 01190 01191 if( IrpSp->Parameters.DeviceIoControl.InputBufferLength >= 01192 sizeof(Proto->Buffered) ) 01193 RtlCopyMemory( &Proto->Buffered, Irp->AssociatedIrp.SystemBuffer, 01194 sizeof(Proto->Buffered) ); 01195 else 01196 Status = STATUS_INVALID_PARAMETER; 01197 01198 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 01199 01200 LA_DbgPrint(MID_TRACE,("Set buffered for %x to %d\n", Proto->Buffered)); 01201 01202 Status = Irp->IoStatus.Status = Status; 01203 Irp->IoStatus.Information = 0; 01204 01205 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); 01206 return Status; 01207 } 01208 01209 NTSTATUS NTAPI 01210 LanDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) 01211 { 01212 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); 01213 NTSTATUS Status = STATUS_SUCCESS; 01214 01215 LA_DbgPrint(MID_TRACE,("LanDispatch: %d\n", IrpSp->MajorFunction)); 01216 if( IrpSp->MajorFunction != IRP_MJ_CREATE) { 01217 LA_DbgPrint(MID_TRACE,("FO %x, IrpSp->FO %x\n", 01218 FileObject, IrpSp->FileObject)); 01219 ASSERT(FileObject == IrpSp->FileObject); 01220 } 01221 01222 switch(IrpSp->MajorFunction) 01223 { 01224 /* opening and closing handles to the device */ 01225 case IRP_MJ_CREATE: 01226 /* Mostly borrowed from the named pipe file system */ 01227 return LanCreateProtocol(DeviceObject, Irp, IrpSp); 01228 01229 case IRP_MJ_CLOSE: 01230 /* Ditto the borrowing */ 01231 return LanCloseProtocol(DeviceObject, Irp, IrpSp); 01232 01233 /* write data */ 01234 case IRP_MJ_WRITE: 01235 return LanWriteData( DeviceObject, Irp, IrpSp ); 01236 01237 /* read data */ 01238 case IRP_MJ_READ: 01239 return LanReadData( DeviceObject, Irp, IrpSp ); 01240 01241 case IRP_MJ_DEVICE_CONTROL: 01242 { 01243 LA_DbgPrint(MID_TRACE,("DeviceIoControl: %x\n", 01244 IrpSp->Parameters.DeviceIoControl. 01245 IoControlCode)); 01246 switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) { 01247 case IOCTL_IF_ENUM_ADAPTERS: 01248 return LanEnumAdapters( DeviceObject, Irp, IrpSp ); 01249 01250 case IOCTL_IF_BUFFERED_MODE: 01251 return LanSetBufferedMode( DeviceObject, Irp, IrpSp ); 01252 01253 case IOCTL_IF_ADAPTER_INFO: 01254 return LanAdapterInfo( DeviceObject, Irp, IrpSp ); 01255 01256 default: 01257 Status = STATUS_NOT_IMPLEMENTED; 01258 Irp->IoStatus.Information = 0; 01259 LA_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%x)\n", 01260 IrpSp->Parameters.DeviceIoControl. 01261 IoControlCode)); 01262 break; 01263 } 01264 break; 01265 } 01266 01267 /* unsupported operations */ 01268 default: 01269 { 01270 Status = STATUS_NOT_IMPLEMENTED; 01271 LA_DbgPrint(MIN_TRACE, 01272 ("Irp: Unknown Major code was %x\n", 01273 IrpSp->MajorFunction)); 01274 break; 01275 } 01276 } 01277 01278 LA_DbgPrint(MID_TRACE, ("Returning %x\n", Status)); 01279 Irp->IoStatus.Status = Status; 01280 IoCompleteRequest(Irp, IO_NO_INCREMENT); 01281 01282 return (Status); 01283 } 01284 01285 /* Do i need a global here? I think i need to do this a different way XXX */ 01286 VOID NTAPI LanUnload(PDRIVER_OBJECT DriverObject) { 01287 LANUnregisterProtocol(); 01288 CloseNdisPools(); 01289 } 01290 01291 NTSTATUS NTAPI DriverEntry( PDRIVER_OBJECT DriverObject, 01292 PUNICODE_STRING RegsitryPath ) { 01293 PDEVICE_OBJECT DeviceObject; 01294 PLAN_DEVICE_EXT DeviceExt; 01295 UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Lan"); 01296 UNICODE_STRING LanString = RTL_CONSTANT_STRING(L"LAN"); 01297 NTSTATUS Status; 01298 01299 InitNdisPools(); 01300 01301 /* register driver routines */ 01302 DriverObject->MajorFunction[IRP_MJ_CLOSE] = LanDispatch; 01303 DriverObject->MajorFunction[IRP_MJ_CREATE] = LanDispatch; 01304 DriverObject->MajorFunction[IRP_MJ_WRITE] = LanDispatch; 01305 DriverObject->MajorFunction[IRP_MJ_READ] = LanDispatch; 01306 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = LanDispatch; 01307 DriverObject->DriverUnload = LanUnload; 01308 01309 /* create lan device */ 01310 Status = IoCreateDevice 01311 ( DriverObject, 01312 sizeof(LAN_DEVICE_EXT), 01313 &wstrDeviceName, 01314 FILE_DEVICE_NAMED_PIPE, 01315 0, 01316 FALSE, 01317 &DeviceObject ); 01318 01319 /* failure */ 01320 if(!NT_SUCCESS(Status)) 01321 { 01322 return (Status); 01323 } 01324 01325 LanDeviceObject = DeviceObject; 01326 DeviceExt = DeviceObject->DeviceExtension; 01327 RtlZeroMemory( DeviceExt, sizeof(*DeviceExt) ); 01328 InitializeListHead( &DeviceExt->AdapterListHead ); 01329 InitializeListHead( &DeviceExt->ProtocolListHead ); 01330 KeInitializeSpinLock( &DeviceExt->Lock ); 01331 01332 LANRegisterProtocol( &LanString ); 01333 01334 DeviceObject->Flags |= DO_BUFFERED_IO; 01335 01336 LA_DbgPrint(MID_TRACE,("Device created: object %x ext %x\n", 01337 DeviceObject, DeviceExt)); 01338 01339 return (Status); 01340 } 01341 01342 /* EOF */ Generated on Sun May 27 2012 04:28:04 for ReactOS by
1.7.6.1
|