2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
5 * PURPOSE: Local Area Network media routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
19 NDIS_HANDLE NdisProtocolHandle
= (NDIS_HANDLE
)NULL
;
20 BOOLEAN ProtocolRegistered
= FALSE
;
21 PLAN_ADAPTER Adapters
= NULL
;
26 NDIS_REQUEST_TYPE Type
,
31 * FUNCTION: Send a request to NDIS
33 * Adapter = Pointer to a LAN_ADAPTER structure
34 * Type = Type of request (Set or Query)
35 * OID = Value to be set/queried for
36 * Buffer = Pointer to a buffer to use
37 * Length = Number of bytes in Buffer
43 NDIS_STATUS NdisStatus
;
45 Request
.RequestType
= Type
;
46 if (Type
== NdisRequestSetInformation
) {
47 Request
.DATA
.SET_INFORMATION
.Oid
= OID
;
48 Request
.DATA
.SET_INFORMATION
.InformationBuffer
= Buffer
;
49 Request
.DATA
.SET_INFORMATION
.InformationBufferLength
= Length
;
51 Request
.DATA
.QUERY_INFORMATION
.Oid
= OID
;
52 Request
.DATA
.QUERY_INFORMATION
.InformationBuffer
= Buffer
;
53 Request
.DATA
.QUERY_INFORMATION
.InformationBufferLength
= Length
;
56 if (Adapter
->State
!= LAN_STATE_RESETTING
) {
57 NdisRequest(&NdisStatus
, Adapter
->NdisHandle
, &Request
);
59 NdisStatus
= NDIS_STATUS_NOT_ACCEPTED
;
61 /* Wait for NDIS to complete the request */
62 if (NdisStatus
== NDIS_STATUS_PENDING
) {
63 KeWaitForSingleObject(&Adapter
->Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
64 NdisStatus
= Adapter
->NdisStatus
;
71 PNDIS_PACKET
AllocateTDPacket(
74 * FUNCTION: Allocates an NDIS packet for NdisTransferData
76 * Adapter = Pointer to LAN_ADAPTER structure
78 * Pointer to NDIS packet or NULL if there was not enough free
82 NDIS_STATUS NdisStatus
;
83 PNDIS_PACKET NdisPacket
;
87 NdisAllocatePacket(&NdisStatus
, &NdisPacket
, GlobalPacketPool
);
88 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
91 Data
= ExAllocatePool(NonPagedPool
, Adapter
->MTU
);
93 NdisFreePacket(NdisPacket
);
97 NdisAllocateBuffer(&NdisStatus
, &Buffer
, GlobalBufferPool
, Data
, Adapter
->MTU
);
98 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
99 NdisFreePacket(NdisPacket
);
104 NdisChainBufferAtFront(NdisPacket
, Buffer
);
106 PC(NdisPacket
)->Context
= NULL
; /* End of list */
113 PLAN_ADAPTER Adapter
)
115 * FUNCTION: Frees transfer data packets
117 * Adapter = Pointer to LAN_ADAPTER structure
120 PNDIS_PACKET NdisPacket
, Next
;
122 /* Release transfer data packets */
123 NdisPacket
= Adapter
->TDPackets
;
125 Next
= PC(NdisPacket
)->Context
;
126 FreeNdisPacket(NdisPacket
);
129 Adapter
->TDPackets
= NULL
;
134 PLAN_ADAPTER Adapter
)
136 * FUNCTION: Frees memory for a LAN_ADAPTER structure
138 * Adapter = Pointer to LAN_ADAPTER structure to free
141 FreeTDPackets(Adapter
);
146 VOID
ProtocolOpenAdapterComplete(
147 NDIS_HANDLE BindingContext
,
149 NDIS_STATUS OpenErrorStatus
)
151 * FUNCTION: Called by NDIS to complete opening of an adapter
153 * BindingContext = Pointer to a device context (LAN_ADAPTER)
154 * Status = Status of the operation
155 * OpenErrorStatus = Additional status information
158 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
160 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
162 KeSetEvent(&Adapter
->Event
, 0, FALSE
);
166 VOID
ProtocolCloseAdapterComplete(
167 NDIS_HANDLE BindingContext
,
170 * FUNCTION: Called by NDIS to complete closing an adapter
172 * BindingContext = Pointer to a device context (LAN_ADAPTER)
173 * Status = Status of the operation
176 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
178 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
180 Adapter
->NdisStatus
= Status
;
182 KeSetEvent(&Adapter
->Event
, 0, FALSE
);
186 VOID
ProtocolResetComplete(
187 NDIS_HANDLE BindingContext
,
190 * FUNCTION: Called by NDIS to complete resetting an adapter
192 * BindingContext = Pointer to a device context (LAN_ADAPTER)
193 * Status = Status of the operation
196 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
200 VOID
ProtocolRequestComplete(
201 NDIS_HANDLE BindingContext
,
202 PNDIS_REQUEST NdisRequest
,
205 * FUNCTION: Called by NDIS to complete a request
207 * BindingContext = Pointer to a device context (LAN_ADAPTER)
208 * NdisRequest = Pointer to an object describing the request
209 * Status = Status of the operation
212 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
214 /* Save status of request and signal an event */
215 Adapter
->NdisStatus
= Status
;
217 KeSetEvent(&Adapter
->Event
, 0, FALSE
);
221 VOID
ProtocolSendComplete(
222 NDIS_HANDLE BindingContext
,
226 * FUNCTION: Called by NDIS to complete sending process
228 * BindingContext = Pointer to a device context (LAN_ADAPTER)
229 * Packet = Pointer to a packet descriptor
230 * Status = Status of the operation
233 PLAN_ADAPTER Adapter
= BindingContext
;
235 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
237 AdjustPacket(Packet
, Adapter
->HeaderSize
, PC(Packet
)->DLOffset
);
239 (*PC(Packet
)->DLComplete
)(Adapter
->Context
, Packet
, Status
);
243 VOID
ProtocolTransferDataComplete(
244 NDIS_HANDLE BindingContext
,
247 UINT BytesTransferred
)
249 * FUNCTION: Called by NDIS to complete reception of data
251 * BindingContext = Pointer to a device context (LAN_ADAPTER)
252 * Packet = Pointer to a packet descriptor
253 * Status = Status of the operation
254 * BytesTransferred = Number of bytes transferred
256 * If the packet was successfully received, determine the protocol
257 * type and pass it to the correct receive handler
261 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
263 if (Status
== NDIS_STATUS_SUCCESS
) {
264 PNDIS_BUFFER NdisBuffer
;
267 NdisGetFirstBufferFromPacket(
268 Packet
, &NdisBuffer
, &IPPacket
.Header
,
269 &IPPacket
.ContigSize
, &IPPacket
.TotalSize
);
271 /* Determine which upper layer protocol that should receive
272 this packet and pass it to the correct receive handler */
273 PacketType
= ((PETH_HEADER
)IPPacket
.Header
)->EType
;
274 switch (PacketType
) {
277 IPReceive(Adapter
->Context
, &IPPacket
);
280 ARPReceive(Adapter
->Context
, &IPPacket
);
286 /* Release the packet descriptor */
287 KeAcquireSpinLockAtDpcLevel(&Adapter
->Lock
);
289 PC(Packet
)->Context
= Adapter
->TDPackets
;
290 Adapter
->TDPackets
= Packet
;
292 KeReleaseSpinLockFromDpcLevel(&Adapter
->Lock
);
296 NDIS_STATUS
ProtocolReceive(
297 NDIS_HANDLE BindingContext
,
298 NDIS_HANDLE MacReceiveContext
,
300 UINT HeaderBufferSize
,
301 PVOID LookaheadBuffer
,
302 UINT LookaheadBufferSize
,
305 * FUNCTION: Called by NDIS when a packet has been received on the physical link
307 * BindingContext = Pointer to a device context (LAN_ADAPTER)
308 * MacReceiveContext = Handle used by underlying NIC driver
309 * HeaderBuffer = Pointer to a buffer containing the packet header
310 * HeaderBufferSize = Number of bytes in HeaderBuffer
311 * LookaheadBuffer = Pointer to a buffer containing buffered packet data
312 * LookaheadBufferSize = Size of LookaheadBuffer. May be less than asked for
313 * PacketSize = Overall size of the packet (not including header)
315 * Status of operation
321 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
322 PETH_HEADER EHeader
= (PETH_HEADER
)HeaderBuffer
;
324 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
326 if ((Adapter
->State
!= LAN_STATE_STARTED
) ||
327 HeaderBufferSize
< Adapter
->HeaderSize
)
328 /* Adapter is not started or the header was too small */
329 return NDIS_STATUS_NOT_ACCEPTED
;
331 if (Adapter
->Media
== NdisMedium802_3
) {
332 /* Ethernet and IEEE 802.3 frames can be destinguished by
333 looking at the IEEE 802.3 length field. This field is
334 less than or equal to 1500 for a valid IEEE 802.3 frame
335 and larger than 1500 is it's a valid Ether-Type value.
336 See RFC 1122, section 2.3.3 for more information */
337 if (((EType
= EHeader
->EType
) != ETYPE_IPv4
) && (EType
!= ETYPE_ARP
))
338 return NDIS_STATUS_NOT_ACCEPTED
;
339 /* We use Ether-Type constants to destinguish packets */
342 /* FIXME: Support other medias */
343 return NDIS_STATUS_NOT_ACCEPTED
;
345 if (LookaheadBufferSize
< PacketSize
) {
346 NDIS_STATUS NdisStatus
;
347 PNDIS_PACKET NdisPacket
;
348 UINT BytesTransferred
;
350 /* Get transfer data packet */
352 KeAcquireSpinLockAtDpcLevel(&Adapter
->Lock
);
354 NdisPacket
= Adapter
->TDPackets
;
355 if (NdisPacket
== (PNDIS_PACKET
)NULL
) {
356 /* We don't have a free packet descriptor. Drop the packet */
357 KeReleaseSpinLockFromDpcLevel(&Adapter
->Lock
);
358 return NDIS_STATUS_SUCCESS
;
360 Adapter
->TDPackets
= PC(NdisPacket
)->Context
;
362 KeReleaseSpinLockFromDpcLevel(&Adapter
->Lock
);
365 NdisTransferData(&NdisStatus
, Adapter
->NdisHandle
,
366 MacReceiveContext
, 0, PacketSize
,
367 NdisPacket
, &BytesTransferred
);
368 if (NdisStatus
!= NDIS_STATUS_PENDING
)
369 ProtocolTransferDataComplete(BindingContext
,
370 NdisPacket
, NdisStatus
, BytesTransferred
);
372 return NDIS_STATUS_SUCCESS
;
375 /* We got all the data in the lookahead buffer */
376 RtlZeroMemory(&IPPacket
, sizeof(IPPacket
));
377 IPPacket
.Header
= LookaheadBuffer
;
378 IPPacket
.TotalSize
= PacketSize
;
380 switch (PacketType
) {
383 IPReceive(Adapter
->Context
, &IPPacket
);
386 ARPReceive(Adapter
->Context
, &IPPacket
);
392 return NDIS_STATUS_SUCCESS
;
396 VOID
ProtocolReceiveComplete(
397 NDIS_HANDLE BindingContext
)
399 * FUNCTION: Called by NDIS when we're done receiving data
401 * BindingContext = Pointer to a device context (LAN_ADAPTER)
404 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
409 NDIS_HANDLE BindingContext
,
410 NDIS_STATUS GenerelStatus
,
412 UINT StatusBufferSize
)
414 * FUNCTION: Called by NDIS when the underlying driver has changed state
416 * BindingContext = Pointer to a device context (LAN_ADAPTER)
417 * GenerelStatus = A generel status code
418 * StatusBuffer = Pointer to a buffer with medium-specific data
419 * StatusBufferSize = Number of bytes in StatusBuffer
422 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
426 VOID
ProtocolStatusComplete(
427 NDIS_HANDLE NdisBindingContext
)
429 * FUNCTION: Called by NDIS when a status-change has occurred
431 * BindingContext = Pointer to a device context (LAN_ADAPTER)
434 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
440 PNDIS_PACKET NdisPacket
,
445 * FUNCTION: Transmits a packet
447 * Context = Pointer to context information (LAN_ADAPTER)
448 * NdisPacket = Pointer to NDIS packet to send
449 * Offset = Offset in packet where data starts
450 * LinkAddress = Pointer to link address of destination (NULL = broadcast)
451 * Type = LAN protocol type (LAN_PROTO_*)
454 NDIS_STATUS NdisStatus
;
457 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)Context
;
459 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
461 /* NDIS send routines don't have an offset argument so we
462 must offset the data in upper layers and adjust the
463 packet here. We save the offset in the packet context
464 area so it can be undone before we release the packet */
465 Data
= AdjustPacket(NdisPacket
, Offset
, Adapter
->HeaderSize
);
466 PC(NdisPacket
)->DLOffset
= Offset
;
468 if (Adapter
->State
== LAN_STATE_STARTED
) {
469 switch (Adapter
->Media
) {
470 case NdisMedium802_3
:
471 EHeader
= (PETH_HEADER
)Data
;
474 /* Unicast address */
475 RtlCopyMemory(EHeader
->DstAddr
, LinkAddress
, IEEE_802_ADDR_LENGTH
);
477 /* Broadcast address */
478 RtlFillMemory(EHeader
->DstAddr
, IEEE_802_ADDR_LENGTH
, 0xFF);
480 RtlCopyMemory(EHeader
->SrcAddr
, Adapter
->HWAddress
, IEEE_802_ADDR_LENGTH
);
484 EHeader
->EType
= ETYPE_IPv4
;
487 EHeader
->EType
= ETYPE_ARP
;
490 EHeader
->EType
= ETYPE_IPv6
;
494 /* Should not happen */
495 TI_DbgPrint(MIN_TRACE
, ("Unknown LAN protocol.\n"));
497 ProtocolSendComplete((NDIS_HANDLE
)Context
, NdisPacket
, NDIS_STATUS_FAILURE
);
504 /* FIXME: Support other medias */
508 NdisSend(&NdisStatus
, Adapter
->NdisHandle
, NdisPacket
);
509 if (NdisStatus
!= NDIS_STATUS_PENDING
)
510 ProtocolSendComplete((NDIS_HANDLE
)Context
, NdisPacket
, NdisStatus
);
512 ProtocolSendComplete((NDIS_HANDLE
)Context
, NdisPacket
, NDIS_STATUS_CLOSED
);
517 PLAN_ADAPTER Adapter
)
519 * FUNCTION: Binds a LAN adapter to IP layer
521 * Adapter = Pointer to LAN_ADAPTER structure
523 * We set the lookahead buffer size, set the packet filter and
524 * bind the adapter to IP layer
531 NDIS_STATUS NdisStatus
;
532 LLIP_BIND_INFO BindInfo
;
533 ULONG Lookahead
= LOOKAHEAD_SIZE
;
535 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
537 Adapter
->State
= LAN_STATE_OPENING
;
539 NdisStatus
= NDISCall(Adapter
, NdisRequestSetInformation
,
540 OID_GEN_CURRENT_LOOKAHEAD
, &Lookahead
, sizeof(ULONG
));
541 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
542 TI_DbgPrint(MID_TRACE
, ("Could not set lookahead buffer size (0x%X).\n", NdisStatus
));
546 /* Allocate packets for NdisTransferData */
547 /* FIXME: How many should we allocate? */
548 Adapter
->TDPackets
= NULL
;
549 for (i
= 0; i
< 2; i
++) {
550 Packet
= AllocateTDPacket(Adapter
);
551 PC(Packet
)->Context
= Adapter
->TDPackets
;
552 Adapter
->TDPackets
= Packet
;
554 TI_DbgPrint(MID_TRACE
, ("Could not allocate transfer data packet (out of resources).\n"));
555 FreeTDPackets(Adapter
);
560 /* Bind the adapter to IP layer */
561 BindInfo
.Context
= Adapter
;
562 BindInfo
.HeaderSize
= Adapter
->HeaderSize
;
563 BindInfo
.MinFrameSize
= Adapter
->MinFrameSize
;
564 BindInfo
.MTU
= Adapter
->MTU
;
565 BindInfo
.Address
= (PUCHAR
)&Adapter
->HWAddress
;
566 BindInfo
.AddressLength
= Adapter
->HWAddressLength
;
567 BindInfo
.Transmit
= LANTransmit
;
569 IF
= IPCreateInterface(&BindInfo
);
571 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
572 FreeTDPackets(Adapter
);
576 /* FIXME: Get address from registry.
577 For now just use a private address, eg. 10.0.0.10 */
578 Address
= AddrBuildIPv4(0x0A00000A);
580 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
581 FreeTDPackets(Adapter
);
582 IPDestroyInterface(Adapter
->Context
);
585 /* Create a net table entry for this interface */
586 if (!IPCreateNTE(IF
, Address
, 8)) {
587 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
588 FreeTDPackets(Adapter
);
589 IPDestroyInterface(IF
);
593 /* Reference the interface for the NTE. The reference for
594 the address is just passed on to the NTE */
597 /* Register interface with IP layer */
598 IPRegisterInterface(IF
);
600 /* Set packet filter so we can send and receive packets */
601 NdisStatus
= NDISCall(Adapter
, NdisRequestSetInformation
,
602 OID_GEN_CURRENT_PACKET_FILTER
, &Adapter
->PacketFilter
, sizeof(UINT
));
603 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
604 TI_DbgPrint(MID_TRACE
, ("Could not set packet filter (0x%X).\n", NdisStatus
));
605 FreeTDPackets(Adapter
);
606 IPDestroyInterface(IF
);
610 Adapter
->Context
= IF
;
612 Adapter
->State
= LAN_STATE_STARTED
;
617 PLAN_ADAPTER Adapter
)
619 * FUNCTION: Unbinds a LAN adapter from IP layer
621 * Adapter = Pointer to LAN_ADAPTER structure
624 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
626 if (Adapter
->State
== LAN_STATE_STARTED
) {
627 PIP_INTERFACE IF
= Adapter
->Context
;
629 IPUnregisterInterface(IF
);
631 IPDestroyInterface(IF
);
633 /* Free transfer data packets */
634 FreeTDPackets(Adapter
);
639 NDIS_STATUS
LANRegisterAdapter(
640 PNDIS_STRING AdapterName
,
641 PLAN_ADAPTER
*Adapter
)
643 * FUNCTION: Registers protocol with an NDIS adapter
645 * AdapterName = Pointer to string with name of adapter to register
646 * Adapter = Address of pointer to a LAN_ADAPTER structure
648 * Status of operation
652 NDIS_STATUS NdisStatus
;
653 NDIS_STATUS OpenStatus
;
655 NDIS_MEDIUM MediaArray
[MAX_MEDIA
];
659 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
661 IF
= ExAllocatePool(NonPagedPool
, sizeof(LAN_ADAPTER
));
663 return NDIS_STATUS_RESOURCES
;
665 RtlZeroMemory(IF
, sizeof(LAN_ADAPTER
));
667 /* Put adapter in stopped state */
668 IF
->State
= LAN_STATE_STOPPED
;
670 /* Initialize protecting spin lock */
671 KeInitializeSpinLock(&IF
->Lock
);
673 KeInitializeEvent(&IF
->Event
, SynchronizationEvent
, FALSE
);
675 /* Initialize array with media IDs we support */
676 MediaArray
[MEDIA_ETH
] = NdisMedium802_3
;
678 /* Open the adapter. */
679 NdisOpenAdapter(&NdisStatus
, &OpenStatus
, &IF
->NdisHandle
, &MediaIndex
,
680 MediaArray
, MAX_MEDIA
, NdisProtocolHandle
, IF
, AdapterName
, 0, NULL
);
682 /* Wait until the adapter is opened */
683 if (NdisStatus
== NDIS_STATUS_PENDING
)
684 KeWaitForSingleObject(&IF
->Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
685 else if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
690 IF
->Media
= MediaArray
[MediaIndex
];
692 /* Fill LAN_ADAPTER structure with some adapter specific information */
694 case NdisMedium802_3
:
695 IF
->HWAddressLength
= IEEE_802_ADDR_LENGTH
;
696 IF
->BCastMask
= BCAST_ETH_MASK
;
697 IF
->BCastCheck
= BCAST_ETH_CHECK
;
698 IF
->BCastOffset
= BCAST_ETH_OFFSET
;
699 IF
->HeaderSize
= sizeof(ETH_HEADER
);
700 IF
->MinFrameSize
= 60;
701 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
703 NDIS_PACKET_TYPE_BROADCAST
|
704 NDIS_PACKET_TYPE_DIRECTED
|
705 NDIS_PACKET_TYPE_MULTICAST
;
709 /* Unsupported media */
710 TI_DbgPrint(MIN_TRACE
, ("Unsupported media.\n"));
712 return NDIS_STATUS_NOT_SUPPORTED
;
715 /* Get maximum frame size */
716 NdisStatus
= NDISCall(IF
, NdisRequestQueryInformation
,
717 OID_GEN_MAXIMUM_FRAME_SIZE
, &IF
->MTU
, sizeof(UINT
));
718 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
723 /* Get maximum packet size */
724 NdisStatus
= NDISCall(IF
, NdisRequestQueryInformation
,
725 OID_GEN_MAXIMUM_TOTAL_SIZE
, &IF
->MaxPacketSize
, sizeof(UINT
));
726 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
727 TI_DbgPrint(MIN_TRACE
, ("Query for maximum packet size failed.\n"));
732 /* Get maximum number of packets we can pass to NdisSend(Packets) at one time */
733 NdisStatus
= NDISCall(IF
, NdisRequestQueryInformation
,
734 OID_GEN_MAXIMUM_SEND_PACKETS
, &IF
->MaxSendPackets
, sizeof(UINT
));
735 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
736 /* Legacy NIC drivers may not support this query, if it fails we
737 assume it can send at least one packet per call to NdisSend(Packets) */
738 IF
->MaxSendPackets
= 1;
740 /* Get current hardware address */
741 NdisStatus
= NDISCall(IF
, NdisRequestQueryInformation
, AddressOID
,
742 IF
->HWAddress
, IF
->HWAddressLength
);
743 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
744 TI_DbgPrint(MIN_TRACE
, ("Query for current hardware address failed.\n"));
749 /* Get maximum link speed */
750 NdisStatus
= NDISCall(IF
, NdisRequestQueryInformation
,
751 OID_GEN_LINK_SPEED
, &Speed
, sizeof(UINT
));
752 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
753 TI_DbgPrint(MIN_TRACE
, ("Query for maximum link speed failed.\n"));
758 /* Convert returned link speed to bps (it is in 100bps increments) */
759 IF
->Speed
= Speed
* 100L;
763 /* Add adapter to the adapter list */
767 /* Bind adapter to IP layer */
770 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
772 return NDIS_STATUS_SUCCESS
;
776 NDIS_STATUS
LANUnregisterAdapter(
777 PLAN_ADAPTER Adapter
)
779 * FUNCTION: Unregisters protocol with NDIS adapter
781 * Adapter = Pointer to a LAN_ADAPTER structure
783 * Status of operation
787 NDIS_HANDLE NdisHandle
;
788 PLAN_ADAPTER IF
, PrevIF
;
789 BOOLEAN Found
= FALSE
;
790 NDIS_STATUS NdisStatus
= NDIS_STATUS_SUCCESS
;
792 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
794 /* Search the adapter list for the specified adapter and remove it */
797 if (Adapter
!= Adapters
) {
799 while ((IF
) && (!Found
)) {
801 /* We've found the adapter, now remove it from the list */
802 PrevIF
->Next
= IF
->Next
;
814 TI_DbgPrint(MIN_TRACE
, ("Leaving (adapter was not in list).\n"));
815 return NDIS_STATUS_ADAPTER_NOT_FOUND
;
818 /* Unbind adapter from IP layer */
819 UnbindAdapter(Adapter
);
821 KeAcquireSpinLock(&Adapter
->Lock
, &OldIrql
);
822 NdisHandle
= Adapter
->NdisHandle
;
824 Adapter
->NdisHandle
= NULL
;
825 KeReleaseSpinLock(&Adapter
->Lock
, OldIrql
);
827 NdisCloseAdapter(&NdisStatus
, NdisHandle
);
828 if (NdisStatus
== NDIS_STATUS_PENDING
) {
829 KeWaitForSingleObject(&Adapter
->Event
,
830 UserRequest
, KernelMode
, FALSE
, NULL
);
831 NdisStatus
= Adapter
->NdisStatus
;
834 KeReleaseSpinLock(&Adapter
->Lock
, OldIrql
);
836 FreeAdapter(Adapter
);
838 return NDIS_STATUS_SUCCESS
;
842 NTSTATUS
LANRegisterProtocol(
845 * FUNCTION: Registers this protocol driver with NDIS
847 * Name = Name of this protocol driver
849 * Status of operation
852 NDIS_STATUS NdisStatus
;
853 NDIS_PROTOCOL_CHARACTERISTICS ProtChars
;
855 /* Set up protocol characteristics */
856 RtlZeroMemory(&ProtChars
, sizeof(NDIS_PROTOCOL_CHARACTERISTICS
));
857 ProtChars
.MajorNdisVersion
= NDIS_VERSION_MAJOR
;
858 ProtChars
.MinorNdisVersion
= NDIS_VERSION_MINOR
;
859 ProtChars
.Name
.Length
= Name
->Length
;
860 ProtChars
.Name
.Buffer
= (PVOID
)Name
->Buffer
;
861 ProtChars
.OpenAdapterCompleteHandler
= ProtocolOpenAdapterComplete
;
862 ProtChars
.CloseAdapterCompleteHandler
= ProtocolCloseAdapterComplete
;
863 ProtChars
.ResetCompleteHandler
= ProtocolResetComplete
;
864 ProtChars
.RequestCompleteHandler
= ProtocolRequestComplete
;
865 ProtChars
.SendCompleteHandler
= ProtocolSendComplete
;
866 ProtChars
.TransferDataCompleteHandler
= ProtocolTransferDataComplete
;
867 ProtChars
.ReceiveHandler
= ProtocolReceive
;
868 ProtChars
.ReceiveCompleteHandler
= ProtocolReceiveComplete
;
869 ProtChars
.StatusHandler
= ProtocolStatus
;
870 ProtChars
.StatusCompleteHandler
= ProtocolStatusComplete
;
872 /* Try to register protocol */
873 NdisRegisterProtocol(
874 &NdisStatus
, &NdisProtocolHandle
, &ProtChars
,
875 sizeof(NDIS_PROTOCOL_CHARACTERISTICS
) + Name
->Length
);
876 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
877 return (NTSTATUS
)NdisStatus
;
879 ProtocolRegistered
= TRUE
;
881 return STATUS_SUCCESS
;
885 VOID
LANUnregisterProtocol(
888 * FUNCTION: Unregisters this protocol driver with NDIS
889 * NOTES: Does not care wether we are already registered
892 if (ProtocolRegistered
) {
893 NDIS_STATUS NdisStatus
;
896 NdisStatus
= LANUnregisterAdapter(Adapters
);
898 NdisDeregisterProtocol(&NdisStatus
, NdisProtocolHandle
);
899 ProtocolRegistered
= FALSE
;