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 LIST_ENTRY AdapterListHead
;
22 KSPIN_LOCK AdapterListLock
;
27 NDIS_REQUEST_TYPE Type
,
32 * FUNCTION: Send a request to NDIS
34 * Adapter = Pointer to a LAN_ADAPTER structure
35 * Type = Type of request (Set or Query)
36 * OID = Value to be set/queried for
37 * Buffer = Pointer to a buffer to use
38 * Length = Number of bytes in Buffer
44 NDIS_STATUS NdisStatus
;
46 Request
.RequestType
= Type
;
47 if (Type
== NdisRequestSetInformation
) {
48 Request
.DATA
.SET_INFORMATION
.Oid
= OID
;
49 Request
.DATA
.SET_INFORMATION
.InformationBuffer
= Buffer
;
50 Request
.DATA
.SET_INFORMATION
.InformationBufferLength
= Length
;
52 Request
.DATA
.QUERY_INFORMATION
.Oid
= OID
;
53 Request
.DATA
.QUERY_INFORMATION
.InformationBuffer
= Buffer
;
54 Request
.DATA
.QUERY_INFORMATION
.InformationBufferLength
= Length
;
57 if (Adapter
->State
!= LAN_STATE_RESETTING
) {
58 NdisRequest(&NdisStatus
, Adapter
->NdisHandle
, &Request
);
60 NdisStatus
= NDIS_STATUS_NOT_ACCEPTED
;
63 /* Wait for NDIS to complete the request */
64 if (NdisStatus
== NDIS_STATUS_PENDING
) {
65 KeWaitForSingleObject(&Adapter
->Event
,
70 NdisStatus
= Adapter
->NdisStatus
;
77 PNDIS_PACKET
AllocateTDPacket(
80 * FUNCTION: Allocates an NDIS packet for NdisTransferData
82 * Adapter = Pointer to LAN_ADAPTER structure
84 * Pointer to NDIS packet or NULL if there was not enough free
88 NDIS_STATUS NdisStatus
;
89 PNDIS_PACKET NdisPacket
;
93 NdisAllocatePacket(&NdisStatus
, &NdisPacket
, GlobalPacketPool
);
94 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
97 Data
= ExAllocatePool(NonPagedPool
, Adapter
->MTU
);
99 NdisFreePacket(NdisPacket
);
103 NdisAllocateBuffer(&NdisStatus
,
108 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
109 NdisFreePacket(NdisPacket
);
114 NdisChainBufferAtFront(NdisPacket
, Buffer
);
116 PC(NdisPacket
)->Context
= NULL
; /* End of list */
123 PLAN_ADAPTER Adapter
)
125 * FUNCTION: Frees transfer data packets
127 * Adapter = Pointer to LAN_ADAPTER structure
130 PNDIS_PACKET NdisPacket
, Next
;
132 /* Release transfer data packets */
133 NdisPacket
= Adapter
->TDPackets
;
135 Next
= PC(NdisPacket
)->Context
;
136 FreeNdisPacket(NdisPacket
);
139 Adapter
->TDPackets
= NULL
;
144 PLAN_ADAPTER Adapter
)
146 * FUNCTION: Frees memory for a LAN_ADAPTER structure
148 * Adapter = Pointer to LAN_ADAPTER structure to free
151 FreeTDPackets(Adapter
);
156 VOID
ProtocolOpenAdapterComplete(
157 NDIS_HANDLE BindingContext
,
159 NDIS_STATUS OpenErrorStatus
)
161 * FUNCTION: Called by NDIS to complete opening of an adapter
163 * BindingContext = Pointer to a device context (LAN_ADAPTER)
164 * Status = Status of the operation
165 * OpenErrorStatus = Additional status information
168 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
170 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
172 KeSetEvent(&Adapter
->Event
, 0, FALSE
);
176 VOID
ProtocolCloseAdapterComplete(
177 NDIS_HANDLE BindingContext
,
180 * FUNCTION: Called by NDIS to complete closing an adapter
182 * BindingContext = Pointer to a device context (LAN_ADAPTER)
183 * Status = Status of the operation
186 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
188 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
190 Adapter
->NdisStatus
= Status
;
192 KeSetEvent(&Adapter
->Event
, 0, FALSE
);
196 VOID
ProtocolResetComplete(
197 NDIS_HANDLE BindingContext
,
200 * FUNCTION: Called by NDIS to complete resetting an adapter
202 * BindingContext = Pointer to a device context (LAN_ADAPTER)
203 * Status = Status of the operation
206 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
210 VOID
ProtocolRequestComplete(
211 NDIS_HANDLE BindingContext
,
212 PNDIS_REQUEST NdisRequest
,
215 * FUNCTION: Called by NDIS to complete a request
217 * BindingContext = Pointer to a device context (LAN_ADAPTER)
218 * NdisRequest = Pointer to an object describing the request
219 * Status = Status of the operation
222 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
224 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
226 /* Save status of request and signal an event */
227 Adapter
->NdisStatus
= Status
;
229 KeSetEvent(&Adapter
->Event
, 0, FALSE
);
233 VOID
ProtocolSendComplete(
234 NDIS_HANDLE BindingContext
,
238 * FUNCTION: Called by NDIS to complete sending process
240 * BindingContext = Pointer to a device context (LAN_ADAPTER)
241 * Packet = Pointer to a packet descriptor
242 * Status = Status of the operation
245 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
247 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
249 AdjustPacket(Packet
, Adapter
->HeaderSize
, PC(Packet
)->DLOffset
);
251 (*PC(Packet
)->DLComplete
)(Adapter
->Context
, Packet
, Status
);
255 VOID
ProtocolTransferDataComplete(
256 NDIS_HANDLE BindingContext
,
259 UINT BytesTransferred
)
261 * FUNCTION: Called by NDIS to complete reception of data
263 * BindingContext = Pointer to a device context (LAN_ADAPTER)
264 * Packet = Pointer to a packet descriptor
265 * Status = Status of the operation
266 * BytesTransferred = Number of bytes transferred
268 * If the packet was successfully received, determine the protocol
269 * type and pass it to the correct receive handler
273 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
275 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
277 if (Status
== NDIS_STATUS_SUCCESS
) {
278 PNDIS_BUFFER NdisBuffer
;
281 IPPacket
.NdisPacket
= Packet
;
283 NdisGetFirstBufferFromPacket(Packet
,
286 &IPPacket
.ContigSize
,
287 &IPPacket
.TotalSize
);
289 /* Determine which upper layer protocol that should receive
290 this packet and pass it to the correct receive handler */
291 PacketType
= ((PETH_HEADER
)IPPacket
.Header
)->EType
;
292 switch (PacketType
) {
295 IPReceive(Adapter
->Context
, &IPPacket
);
298 ARPReceive(Adapter
->Context
, &IPPacket
);
304 /* Release the packet descriptor */
305 KeAcquireSpinLockAtDpcLevel(&Adapter
->Lock
);
307 PC(Packet
)->Context
= Adapter
->TDPackets
;
308 Adapter
->TDPackets
= Packet
;
310 KeReleaseSpinLockFromDpcLevel(&Adapter
->Lock
);
314 NDIS_STATUS
ProtocolReceive(
315 NDIS_HANDLE BindingContext
,
316 NDIS_HANDLE MacReceiveContext
,
318 UINT HeaderBufferSize
,
319 PVOID LookaheadBuffer
,
320 UINT LookaheadBufferSize
,
323 * FUNCTION: Called by NDIS when a packet has been received on the physical link
325 * BindingContext = Pointer to a device context (LAN_ADAPTER)
326 * MacReceiveContext = Handle used by underlying NIC driver
327 * HeaderBuffer = Pointer to a buffer containing the packet header
328 * HeaderBufferSize = Number of bytes in HeaderBuffer
329 * LookaheadBuffer = Pointer to a buffer containing buffered packet data
330 * LookaheadBufferSize = Size of LookaheadBuffer. May be less than asked for
331 * PacketSize = Overall size of the packet (not including header)
333 * Status of operation
339 PNDIS_PACKET NdisPacket
;
340 PNDIS_BUFFER NdisBuffer
;
341 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
342 PETH_HEADER EHeader
= (PETH_HEADER
)HeaderBuffer
;
344 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
346 if (Adapter
->State
!= LAN_STATE_STARTED
) {
347 TI_DbgPrint(DEBUG_DATALINK
, ("Adapter is stopped.\n"));
348 return NDIS_STATUS_NOT_ACCEPTED
;
351 if (HeaderBufferSize
< Adapter
->HeaderSize
) {
352 TI_DbgPrint(DEBUG_DATALINK
, ("Runt frame received.\n"));
353 return NDIS_STATUS_NOT_ACCEPTED
;
356 if (Adapter
->Media
== NdisMedium802_3
) {
357 /* Ethernet and IEEE 802.3 frames can be destinguished by
358 looking at the IEEE 802.3 length field. This field is
359 less than or equal to 1500 for a valid IEEE 802.3 frame
360 and larger than 1500 is it's a valid EtherType value.
361 See RFC 1122, section 2.3.3 for more information */
362 /* FIXME: Test for Ethernet and IEEE 802.3 frame */
363 if (((EType
= EHeader
->EType
) != ETYPE_IPv4
) && (EType
!= ETYPE_ARP
)) {
364 TI_DbgPrint(DEBUG_DATALINK
, ("Not IP or ARP frame. EtherType (0x%X).\n", EType
));
365 return NDIS_STATUS_NOT_ACCEPTED
;
367 /* We use EtherType constants to destinguish packet types */
370 TI_DbgPrint(MIN_TRACE
, ("Unsupported media.\n"));
371 /* FIXME: Support other medias */
372 return NDIS_STATUS_NOT_ACCEPTED
;
375 /* Get a transfer data packet */
377 KeAcquireSpinLockAtDpcLevel(&Adapter
->Lock
);
379 NdisPacket
= Adapter
->TDPackets
;
380 if (NdisPacket
== (PNDIS_PACKET
)NULL
) {
381 TI_DbgPrint(DEBUG_DATALINK
, ("No available packet descriptors.\n"));
382 /* We don't have a free packet descriptor. Drop the packet */
383 KeReleaseSpinLockFromDpcLevel(&Adapter
->Lock
);
384 return NDIS_STATUS_SUCCESS
;
386 Adapter
->TDPackets
= PC(NdisPacket
)->Context
;
388 KeReleaseSpinLockFromDpcLevel(&Adapter
->Lock
);
390 if (LookaheadBufferSize
< PacketSize
) {
391 NDIS_STATUS NdisStatus
;
392 UINT BytesTransferred
;
395 NdisTransferData(&NdisStatus
,
402 if (NdisStatus
!= NDIS_STATUS_PENDING
)
403 ProtocolTransferDataComplete(BindingContext
,
408 return NDIS_STATUS_SUCCESS
;
411 /* We got all the data in the lookahead buffer */
413 IPPacket
.NdisPacket
= NdisPacket
;
415 NdisGetFirstBufferFromPacket(NdisPacket
,
418 &IPPacket
.ContigSize
,
419 &IPPacket
.TotalSize
);
421 RtlCopyMemory(IPPacket
.Header
, LookaheadBuffer
, PacketSize
);
423 switch (PacketType
) {
426 IPReceive(Adapter
->Context
, &IPPacket
);
429 ARPReceive(Adapter
->Context
, &IPPacket
);
435 /* Release the packet descriptor */
436 KeAcquireSpinLockAtDpcLevel(&Adapter
->Lock
);
438 PC(NdisPacket
)->Context
= Adapter
->TDPackets
;
439 Adapter
->TDPackets
= NdisPacket
;
441 KeReleaseSpinLockFromDpcLevel(&Adapter
->Lock
);
443 return NDIS_STATUS_SUCCESS
;
447 VOID
ProtocolReceiveComplete(
448 NDIS_HANDLE BindingContext
)
450 * FUNCTION: Called by NDIS when we're done receiving data
452 * BindingContext = Pointer to a device context (LAN_ADAPTER)
455 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
460 NDIS_HANDLE BindingContext
,
461 NDIS_STATUS GenerelStatus
,
463 UINT StatusBufferSize
)
465 * FUNCTION: Called by NDIS when the underlying driver has changed state
467 * BindingContext = Pointer to a device context (LAN_ADAPTER)
468 * GenerelStatus = A generel status code
469 * StatusBuffer = Pointer to a buffer with medium-specific data
470 * StatusBufferSize = Number of bytes in StatusBuffer
473 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
477 VOID
ProtocolStatusComplete(
478 NDIS_HANDLE NdisBindingContext
)
480 * FUNCTION: Called by NDIS when a status-change has occurred
482 * BindingContext = Pointer to a device context (LAN_ADAPTER)
485 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
488 VOID
ProtocolBindAdapter(
489 OUT PNDIS_STATUS Status
,
490 IN NDIS_HANDLE BindContext
,
491 IN PNDIS_STRING DeviceName
,
492 IN PVOID SystemSpecific1
,
493 IN PVOID SystemSpecific2
)
495 * FUNCTION: Called by NDIS during NdisRegisterProtocol to set up initial
496 * bindings, and periodically thereafer as new adapters come online
498 * Status: Return value to NDIS
499 * BindContext: Handle provided by NDIS to track pending binding operations
500 * DeviceName: Name of the miniport device to bind to
501 * SystemSpecific1: Pointer to a registry path with protocol-specific configuration information
502 * SystemSpecific2: Unused
505 /* we get to ignore BindContext because we will never pend an operation with NDIS */
506 DbgPrint(("tcpip!ProtocolBindAdapter called\n"));
507 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
508 *Status
= LANRegisterAdapter(DeviceName
);
514 PNDIS_PACKET NdisPacket
,
519 * FUNCTION: Transmits a packet
521 * Context = Pointer to context information (LAN_ADAPTER)
522 * NdisPacket = Pointer to NDIS packet to send
523 * Offset = Offset in packet where data starts
524 * LinkAddress = Pointer to link address of destination (NULL = broadcast)
525 * Type = LAN protocol type (LAN_PROTO_*)
528 NDIS_STATUS NdisStatus
;
531 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)Context
;
533 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
535 /* NDIS send routines don't have an offset argument so we
536 must offset the data in upper layers and adjust the
537 packet here. We save the offset in the packet context
538 area so it can be undone before we release the packet */
539 Data
= AdjustPacket(NdisPacket
, Offset
, Adapter
->HeaderSize
);
540 PC(NdisPacket
)->DLOffset
= Offset
;
542 if (Adapter
->State
== LAN_STATE_STARTED
) {
543 switch (Adapter
->Media
) {
544 case NdisMedium802_3
:
545 EHeader
= (PETH_HEADER
)Data
;
548 /* Unicast address */
549 RtlCopyMemory(EHeader
->DstAddr
, LinkAddress
, IEEE_802_ADDR_LENGTH
);
551 /* Broadcast address */
552 RtlFillMemory(EHeader
->DstAddr
, IEEE_802_ADDR_LENGTH
, 0xFF);
555 RtlCopyMemory(EHeader
->SrcAddr
, Adapter
->HWAddress
, IEEE_802_ADDR_LENGTH
);
559 EHeader
->EType
= ETYPE_IPv4
;
562 EHeader
->EType
= ETYPE_ARP
;
565 EHeader
->EType
= ETYPE_IPv6
;
569 /* Should not happen */
570 TI_DbgPrint(MIN_TRACE
, ("Unknown LAN protocol.\n"));
572 ProtocolSendComplete((NDIS_HANDLE
)Context
,
574 NDIS_STATUS_FAILURE
);
581 /* FIXME: Support other medias */
585 NdisSend(&NdisStatus
, Adapter
->NdisHandle
, NdisPacket
);
586 if (NdisStatus
!= NDIS_STATUS_PENDING
)
587 ProtocolSendComplete((NDIS_HANDLE
)Context
, NdisPacket
, NdisStatus
);
589 ProtocolSendComplete((NDIS_HANDLE
)Context
, NdisPacket
, NDIS_STATUS_CLOSED
);
595 PLAN_ADAPTER Adapter
)
597 * FUNCTION: Binds a LAN adapter to IP layer
599 * Adapter = Pointer to LAN_ADAPTER structure
601 * We set the lookahead buffer size, set the packet filter and
602 * bind the adapter to IP layer
609 NDIS_STATUS NdisStatus
;
610 LLIP_BIND_INFO BindInfo
;
611 ULONG Lookahead
= LOOKAHEAD_SIZE
;
613 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
615 Adapter
->State
= LAN_STATE_OPENING
;
617 NdisStatus
= NDISCall(Adapter
,
618 NdisRequestSetInformation
,
619 OID_GEN_CURRENT_LOOKAHEAD
,
622 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
623 TI_DbgPrint(MID_TRACE
, ("Could not set lookahead buffer size (0x%X).\n", NdisStatus
));
627 /* Allocate packets for NdisTransferData */
628 /* FIXME: How many should we allocate? */
629 Adapter
->TDPackets
= NULL
;
630 for (i
= 0; i
< 2; i
++) {
631 Packet
= AllocateTDPacket(Adapter
);
632 PC(Packet
)->Context
= Adapter
->TDPackets
;
633 Adapter
->TDPackets
= Packet
;
635 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
636 FreeTDPackets(Adapter
);
641 /* Bind the adapter to IP layer */
642 BindInfo
.Context
= Adapter
;
643 BindInfo
.HeaderSize
= Adapter
->HeaderSize
;
644 BindInfo
.MinFrameSize
= Adapter
->MinFrameSize
;
645 BindInfo
.MTU
= Adapter
->MTU
;
646 BindInfo
.Address
= (PUCHAR
)&Adapter
->HWAddress
;
647 BindInfo
.AddressLength
= Adapter
->HWAddressLength
;
648 BindInfo
.Transmit
= LANTransmit
;
650 IF
= IPCreateInterface(&BindInfo
);
652 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
653 FreeTDPackets(Adapter
);
657 /* FIXME: Get address from registry.
658 For now just use a private address, eg. 10.0.0.100 */
659 Address
= AddrBuildIPv4(0x6400000A);
660 // Address = AddrBuildIPv4(0x6048F2D1); // 209.242.72.96
662 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
663 FreeTDPackets(Adapter
);
664 IPDestroyInterface(Adapter
->Context
);
667 /* Create a net table entry for this interface */
668 if (!IPCreateNTE(IF
, Address
, 8)) {
669 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
670 FreeTDPackets(Adapter
);
671 IPDestroyInterface(IF
);
675 /* Reference the interface for the NTE. The reference
676 for the address is just passed on to the NTE */
679 /* Register interface with IP layer */
680 IPRegisterInterface(IF
);
682 /* Set packet filter so we can send and receive packets */
683 NdisStatus
= NDISCall(Adapter
,
684 NdisRequestSetInformation
,
685 OID_GEN_CURRENT_PACKET_FILTER
,
686 &Adapter
->PacketFilter
,
688 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
689 TI_DbgPrint(MID_TRACE
, ("Could not set packet filter (0x%X).\n", NdisStatus
));
690 FreeTDPackets(Adapter
);
691 IPDestroyInterface(IF
);
695 Adapter
->Context
= IF
;
697 Adapter
->State
= LAN_STATE_STARTED
;
702 PLAN_ADAPTER Adapter
)
704 * FUNCTION: Unbinds a LAN adapter from IP layer
706 * Adapter = Pointer to LAN_ADAPTER structure
709 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
711 if (Adapter
->State
== LAN_STATE_STARTED
) {
712 PIP_INTERFACE IF
= Adapter
->Context
;
714 IPUnregisterInterface(IF
);
716 IPDestroyInterface(IF
);
718 /* Free transfer data packets */
719 FreeTDPackets(Adapter
);
724 NDIS_STATUS
LANRegisterAdapter(
725 PNDIS_STRING AdapterName
)
727 * FUNCTION: Registers protocol with an NDIS adapter
729 * AdapterName = Pointer to string with name of adapter to register
730 * Adapter = Address of pointer to a LAN_ADAPTER structure
732 * Status of operation
736 NDIS_STATUS NdisStatus
;
737 NDIS_STATUS OpenStatus
;
739 NDIS_MEDIUM MediaArray
[MAX_MEDIA
];
743 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
745 IF
= ExAllocatePool(NonPagedPool
, sizeof(LAN_ADAPTER
));
747 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
748 return NDIS_STATUS_RESOURCES
;
751 RtlZeroMemory(IF
, sizeof(LAN_ADAPTER
));
753 /* Put adapter in stopped state */
754 IF
->State
= LAN_STATE_STOPPED
;
756 /* Initialize protecting spin lock */
757 KeInitializeSpinLock(&IF
->Lock
);
759 KeInitializeEvent(&IF
->Event
, SynchronizationEvent
, FALSE
);
761 /* Initialize array with media IDs we support */
762 MediaArray
[MEDIA_ETH
] = NdisMedium802_3
;
764 /* Open the adapter. */
765 NdisOpenAdapter(&NdisStatus
,
777 /* Wait until the adapter is opened */
778 if (NdisStatus
== NDIS_STATUS_PENDING
)
779 KeWaitForSingleObject(&IF
->Event
, UserRequest
, KernelMode
, FALSE
, NULL
);
780 else if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
785 IF
->Media
= MediaArray
[MediaIndex
];
787 /* Fill LAN_ADAPTER structure with some adapter specific information */
789 case NdisMedium802_3
:
790 IF
->HWAddressLength
= IEEE_802_ADDR_LENGTH
;
791 IF
->BCastMask
= BCAST_ETH_MASK
;
792 IF
->BCastCheck
= BCAST_ETH_CHECK
;
793 IF
->BCastOffset
= BCAST_ETH_OFFSET
;
794 IF
->HeaderSize
= sizeof(ETH_HEADER
);
795 IF
->MinFrameSize
= 60;
796 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
798 NDIS_PACKET_TYPE_BROADCAST
|
799 NDIS_PACKET_TYPE_DIRECTED
|
800 NDIS_PACKET_TYPE_MULTICAST
;
804 /* Unsupported media */
805 TI_DbgPrint(MIN_TRACE
, ("Unsupported media.\n"));
807 return NDIS_STATUS_NOT_SUPPORTED
;
810 /* Get maximum frame size */
811 NdisStatus
= NDISCall(IF
,
812 NdisRequestQueryInformation
,
813 OID_GEN_MAXIMUM_FRAME_SIZE
,
816 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
821 /* Get maximum packet size */
822 NdisStatus
= NDISCall(IF
,
823 NdisRequestQueryInformation
,
824 OID_GEN_MAXIMUM_TOTAL_SIZE
,
827 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
828 TI_DbgPrint(MIN_TRACE
, ("Query for maximum packet size failed.\n"));
833 /* Get maximum number of packets we can pass to NdisSend(Packets) at one time */
834 NdisStatus
= NDISCall(IF
,
835 NdisRequestQueryInformation
,
836 OID_GEN_MAXIMUM_SEND_PACKETS
,
839 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
840 /* Legacy NIC drivers may not support this query, if it fails we
841 assume it can send at least one packet per call to NdisSend(Packets) */
842 IF
->MaxSendPackets
= 1;
844 /* Get current hardware address */
845 NdisStatus
= NDISCall(IF
,
846 NdisRequestQueryInformation
,
849 IF
->HWAddressLength
);
850 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
851 TI_DbgPrint(MIN_TRACE
, ("Query for current hardware address failed.\n"));
856 /* Get maximum link speed */
857 NdisStatus
= NDISCall(IF
,
858 NdisRequestQueryInformation
,
862 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
863 TI_DbgPrint(MIN_TRACE
, ("Query for maximum link speed failed.\n"));
868 /* Convert returned link speed to bps (it is in 100bps increments) */
869 IF
->Speed
= Speed
* 100L;
871 /* Add adapter to the adapter list */
872 ExInterlockedInsertTailList(&AdapterListHead
,
876 /* Bind adapter to IP layer */
879 TI_DbgPrint(DEBUG_DATALINK
, ("Leaving.\n"));
881 return NDIS_STATUS_SUCCESS
;
885 NDIS_STATUS
LANUnregisterAdapter(
886 PLAN_ADAPTER Adapter
)
888 * FUNCTION: Unregisters protocol with NDIS adapter
890 * Adapter = Pointer to a LAN_ADAPTER structure
892 * Status of operation
896 NDIS_HANDLE NdisHandle
;
897 NDIS_STATUS NdisStatus
= NDIS_STATUS_SUCCESS
;
899 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
901 /* Unlink the adapter from the list */
902 RemoveEntryList(&Adapter
->ListEntry
);
904 /* Unbind adapter from IP layer */
905 UnbindAdapter(Adapter
);
907 KeAcquireSpinLock(&Adapter
->Lock
, &OldIrql
);
908 NdisHandle
= Adapter
->NdisHandle
;
910 Adapter
->NdisHandle
= NULL
;
911 KeReleaseSpinLock(&Adapter
->Lock
, OldIrql
);
913 NdisCloseAdapter(&NdisStatus
, NdisHandle
);
914 if (NdisStatus
== NDIS_STATUS_PENDING
) {
915 KeWaitForSingleObject(&Adapter
->Event
,
920 NdisStatus
= Adapter
->NdisStatus
;
923 KeReleaseSpinLock(&Adapter
->Lock
, OldIrql
);
925 FreeAdapter(Adapter
);
927 return NDIS_STATUS_SUCCESS
;
931 NTSTATUS
LANRegisterProtocol(
934 * FUNCTION: Registers this protocol driver with NDIS
936 * Name = Name of this protocol driver
938 * Status of operation
941 NDIS_STATUS NdisStatus
;
942 NDIS_PROTOCOL_CHARACTERISTICS ProtChars
;
944 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
946 InitializeListHead(&AdapterListHead
);
947 KeInitializeSpinLock(&AdapterListLock
);
949 /* Set up protocol characteristics */
950 RtlZeroMemory(&ProtChars
, sizeof(NDIS_PROTOCOL_CHARACTERISTICS
));
951 ProtChars
.MajorNdisVersion
= NDIS_VERSION_MAJOR
;
952 ProtChars
.MinorNdisVersion
= NDIS_VERSION_MINOR
;
953 ProtChars
.Name
.Length
= Name
->Length
;
954 ProtChars
.Name
.Buffer
= Name
->Buffer
;
955 ProtChars
.Name
.MaximumLength
= Name
->MaximumLength
;
956 ProtChars
.OpenAdapterCompleteHandler
= ProtocolOpenAdapterComplete
;
957 ProtChars
.CloseAdapterCompleteHandler
= ProtocolCloseAdapterComplete
;
958 ProtChars
.ResetCompleteHandler
= ProtocolResetComplete
;
959 ProtChars
.RequestCompleteHandler
= ProtocolRequestComplete
;
960 ProtChars
.u2
.SendCompleteHandler
= ProtocolSendComplete
;
961 ProtChars
.u3
.TransferDataCompleteHandler
= ProtocolTransferDataComplete
;
962 ProtChars
.u4
.ReceiveHandler
= ProtocolReceive
;
963 ProtChars
.ReceiveCompleteHandler
= ProtocolReceiveComplete
;
964 ProtChars
.StatusHandler
= ProtocolStatus
;
965 ProtChars
.StatusCompleteHandler
= ProtocolStatusComplete
;
966 ProtChars
.BindAdapterHandler
= ProtocolBindAdapter
;
968 /* Try to register protocol */
969 NdisRegisterProtocol(&NdisStatus
,
972 sizeof(NDIS_PROTOCOL_CHARACTERISTICS
));
973 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
975 TI_DbgPrint(MID_TRACE
, ("NdisRegisterProtocol failed, status 0x%x\n", NdisStatus
));
976 return (NTSTATUS
)NdisStatus
;
979 ProtocolRegistered
= TRUE
;
981 return STATUS_SUCCESS
;
985 VOID
LANUnregisterProtocol(
988 * FUNCTION: Unregisters this protocol driver with NDIS
989 * NOTES: Does not care wether we are already registered
992 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
994 if (ProtocolRegistered
) {
995 NDIS_STATUS NdisStatus
;
996 PLIST_ENTRY CurrentEntry
;
997 PLIST_ENTRY NextEntry
;
998 PLAN_ADAPTER Current
;
1001 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1003 /* Search the list and remove every adapter we find */
1004 CurrentEntry
= AdapterListHead
.Flink
;
1005 while (CurrentEntry
!= &AdapterListHead
) {
1006 NextEntry
= CurrentEntry
->Flink
;
1007 Current
= CONTAINING_RECORD(CurrentEntry
, LAN_ADAPTER
, ListEntry
);
1009 LANUnregisterAdapter(Current
);
1010 CurrentEntry
= NextEntry
;
1013 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1015 NdisDeregisterProtocol(&NdisStatus
, NdisProtocolHandle
);
1016 ProtocolRegistered
= FALSE
;