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

Information | Donate

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

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

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

ReactOS Development > Doxygen

lan.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 doxygen 1.7.6.1

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