From d788739c0e41dcb728952d552444f3ea29f159dc Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 17 Oct 2004 01:55:54 +0000 Subject: [PATCH] - Compile with W32API headers. - Add multicast support. - Add media state detection support. - Protect the adapter context with spinlock and move code talking to card to inside NdisMSynchronizeWithInterrupt calls where necessary. svn path=/trunk/; revision=11301 --- reactos/drivers/net/dd/pcnet/Makefile | 6 +- reactos/drivers/net/dd/pcnet/pcnet.c | 252 ++++++++++++++++++------ reactos/drivers/net/dd/pcnet/pcnet.h | 32 +-- reactos/drivers/net/dd/pcnet/requests.c | 82 ++++---- 4 files changed, 263 insertions(+), 109 deletions(-) diff --git a/reactos/drivers/net/dd/pcnet/Makefile b/reactos/drivers/net/dd/pcnet/Makefile index 7c50b48e389..2a51eae556d 100644 --- a/reactos/drivers/net/dd/pcnet/Makefile +++ b/reactos/drivers/net/dd/pcnet/Makefile @@ -6,9 +6,9 @@ TARGET_NAME = pcnet # - must define NDIS50 to get the right characteristics struct # - must define anonymous unions to make physical addresses work right # -TARGET_CFLAGS = -I. -Wall -Werror -DNDIS50 -DANONYMOUSUNIONS - -# TARGET_CFLAGS += -I$(W32API_PATH)/include/ddk -D__USE_W32API +TARGET_CFLAGS = -I. -Wall -Werror -DNDIS50_MINIPORT +TARGET_CFLAGS += -I$(W32API_PATH)/include/ddk -D__USE_W32API +# TARGET_CFLAGS += -DDBG=1 TARGET_OBJECTS = pcnet.o requests.o TARGET_DDKLIBS = ndis.a diff --git a/reactos/drivers/net/dd/pcnet/pcnet.c b/reactos/drivers/net/dd/pcnet/pcnet.c index ff15fafdc43..2a770691b7d 100644 --- a/reactos/drivers/net/dd/pcnet/pcnet.c +++ b/reactos/drivers/net/dd/pcnet/pcnet.c @@ -27,9 +27,14 @@ * - Don't read slot number from registry and * report itself as NDIS 5.0 miniport. * 11-Oct-2004 navaraf - Fix nasty bugs in halt code path. + * 17-Oct-2004 navaraf - Add multicast support. + * - Add media state detection support. + * - Protect the adapter context with spinlock + * and move code talking to card to inside + * NdisMSynchronizeWithInterrupt calls where + * necessary. * * NOTES: - * - this is hard-coded to NDIS5 * - this assumes a 32-bit machine */ @@ -52,15 +57,11 @@ MiniportHandleInterrupt( { PADAPTER Adapter = (PADAPTER)MiniportAdapterContext; USHORT Data; -#if DBG - BOOLEAN ReceiveHandled = FALSE; - BOOLEAN ErrorHandled = FALSE; - BOOLEAN IdonHandled = FALSE; - BOOLEAN TransmitHandled = FALSE; -#endif PCNET_DbgPrint(("Called\n")); + NdisDprAcquireSpinLock(&Adapter->Lock); + NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); @@ -73,46 +74,16 @@ MiniportHandleInterrupt( if(Data & CSR0_ERR) { -#if DBG - if(ErrorHandled) - { - PCNET_DbgPrint(("ERROR HANDLED TWO TIMES\n")); - ASSERT(0); - } - - ErrorHandled = TRUE; -#endif - PCNET_DbgPrint(("error: %x\n", Data & (CSR0_MERR|CSR0_BABL|CSR0_CERR|CSR0_MISS))) if (Data & CSR0_CERR) Adapter->Statistics.XmtCollisions++; } else if(Data & CSR0_IDON) { -#if DBG - if(IdonHandled) - { - PCNET_DbgPrint(("IDON HANDLED TWO TIMES\n")); - ASSERT(0); - } - - IdonHandled = TRUE; -#endif - PCNET_DbgPrint(("IDON\n")); } else if(Data & CSR0_RINT) { -#if DBG - if(ReceiveHandled) - { - PCNET_DbgPrint(("RECEIVE HANDLED TWO TIMES\n")); - ASSERT(0); - } - - ReceiveHandled = TRUE; -#endif - PCNET_DbgPrint(("receive interrupt\n")); while(1) @@ -171,16 +142,6 @@ MiniportHandleInterrupt( { PTRANSMIT_DESCRIPTOR Descriptor; -#if DBG - if(TransmitHandled) - { - PCNET_DbgPrint(("TRANSMIT HANDLED TWO TIMES\n")); - ASSERT(0); - } - - TransmitHandled = TRUE; -#endif - PCNET_DbgPrint(("transmit interrupt\n")); while (Adapter->CurrentTransmitStartIndex != @@ -198,6 +159,14 @@ MiniportHandleInterrupt( break; } + if (Descriptor->FLAGS & TD1_STP) + { + if (Descriptor->FLAGS & TD1_ONE) + Adapter->Statistics.XmtOneRetry++; + else if (Descriptor->FLAGS & TD1_MORE) + Adapter->Statistics.XmtMoreThanOneRetry++; + } + if (Descriptor->FLAGS & TD1_ERR) { PCNET_DbgPrint(("major error: %x\n", Descriptor->FLAGS2)); @@ -237,6 +206,8 @@ MiniportHandleInterrupt( NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); PCNET_DbgPrint(("CSR0 is now 0x%x\n", Data)); + + NdisDprAcquireSpinLock(&Adapter->Lock); } NDIS_STATUS @@ -546,6 +517,22 @@ MiFreeSharedMemory( } } +BOOLEAN +STDCALL +MiSyncStop( + IN PVOID SynchronizeContext) +/* + * FUNCTION: Stop the adapter + * ARGUMENTS: + * SynchronizeContext: Adapter context + */ +{ + PADAPTER Adapter = (PADAPTER)SynchronizeContext; + NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); + NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STOP); + return TRUE; +} + VOID STDCALL MiniportHalt( @@ -559,13 +546,16 @@ MiniportHalt( */ { PADAPTER Adapter = (PADAPTER)MiniportAdapterContext; + BOOLEAN TimerCancelled; PCNET_DbgPrint(("Called\n")); ASSERT(Adapter); + /* stop the media detection timer */ + NdisMCancelTimer(&Adapter->MediaDetectionTimer, &TimerCancelled); + /* stop the chip */ - NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); - NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STOP); + NdisMSynchronizeWithInterrupt(&Adapter->InterruptObject, MiSyncStop, Adapter); /* deregister the interrupt */ NdisMDeregisterInterrupt(&Adapter->InterruptObject); @@ -579,10 +569,65 @@ MiniportHalt( /* free map registers */ NdisMFreeMapRegisters(Adapter->MiniportAdapterHandle); + /* free the lock */ + NdisFreeSpinLock(&Adapter->Lock); + /* free the adapter */ NdisFreeMemory(Adapter, 0, 0); } +BOOLEAN +STDCALL +MiSyncMediaDetection( + IN PVOID SynchronizeContext) +/* + * FUNCTION: Stop the adapter + * ARGUMENTS: + * SynchronizeContext: Adapter context + */ +{ + PADAPTER Adapter = (PADAPTER)SynchronizeContext; + NDIS_MEDIA_STATE MediaState = MiGetMediaState(Adapter); + + PCNET_DbgPrint(("Called\n")); + PCNET_DbgPrint(("MediaState: %d\n", MediaState)); + if (MediaState != Adapter->MediaState) + { + Adapter->MediaState = MediaState; + return TRUE; + } + return FALSE; +} + +VOID +STDCALL +MiniportMediaDetectionTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +/* + * FUNCTION: Periodially query media state + * ARGUMENTS: + * FunctionContext: Adapter context + * NOTES: + * - Called by NDIS at DISPATCH_LEVEL + */ +{ + PADAPTER Adapter = (PADAPTER)FunctionContext; + + if (NdisMSynchronizeWithInterrupt(&Adapter->InterruptObject, + MiSyncMediaDetection, + FunctionContext)) + { + NdisMIndicateStatus(Adapter->MiniportAdapterHandle, + Adapter->MediaState == NdisMediaStateConnected ? + NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT, + (PVOID)0, 0); + NdisMIndicateStatusComplete(Adapter->MiniportAdapterHandle); + } +} + VOID MiInitChip( PADAPTER Adapter) @@ -655,6 +700,11 @@ MiInitChip( NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STRT|CSR0_INIT|CSR0_IENA); + /* detect the media state */ + NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR4); + NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR4_LNKSTE|BCR4_FDLSE/*|BCR4_XMTE|BCR4_RCVME|BCR4_MPSE|BCR4_JABE*/); + Adapter->MediaState = MiGetMediaState(Adapter); + PCNET_DbgPrint(("card started\n")); Adapter->Flags &= ~RESET_IN_PROGRESS; @@ -849,6 +899,8 @@ MiniportInitialize( /* Initialize and start the chip */ MiInitChip(Adapter); + NdisAllocateSpinLock(&Adapter->Lock); + Status = NDIS_STATUS_SUCCESS; } while(0); @@ -870,6 +922,16 @@ MiniportInitialize( NdisFreeMemory(Adapter, 0, 0); } + if(Status == NDIS_STATUS_SUCCESS) + { + NdisMInitializeTimer(&Adapter->MediaDetectionTimer, + Adapter->MiniportAdapterHandle, + MiniportMediaDetectionTimer, + Adapter); + NdisMSetPeriodicTimer(&Adapter->MediaDetectionTimer, + MEDIA_DETECTION_INTERVAL); + } + #if DBG if(!MiTestCard(Adapter)) ASSERT(0); @@ -958,6 +1020,22 @@ MiniportReset( return NDIS_STATUS_SUCCESS; } +BOOLEAN +STDCALL +MiSyncStartTransmit( + IN PVOID SynchronizeContext) +/* + * FUNCTION: Stop the adapter + * ARGUMENTS: + * SynchronizeContext: Adapter context + */ +{ + PADAPTER Adapter = (PADAPTER)SynchronizeContext; + NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); + NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_IENA | CSR0_TDMD); + return TRUE; +} + NDIS_STATUS STDCALL MiniportSend( @@ -985,6 +1063,8 @@ MiniportSend( PCNET_DbgPrint(("Called\n")); + NdisDprAcquireSpinLock(&Adapter->Lock); + /* Check if we have free entry in our circular buffer. */ if ((Adapter->CurrentTransmitEndIndex + 1 == Adapter->CurrentTransmitStartIndex) || @@ -992,6 +1072,7 @@ MiniportSend( Adapter->CurrentTransmitStartIndex == 0)) { PCNET_DbgPrint(("No free space in circular buffer\n")); + NdisDprReleaseSpinLock(&Adapter->Lock); return NDIS_STATUS_RESOURCES; } @@ -1017,7 +1098,7 @@ MiniportSend( NdisGetNextBuffer(NdisBuffer, &NdisBuffer); } -#if DBG +#if DBG && 0 { PUCHAR Ptr = Adapter->TransmitBufferPtrVirt + Adapter->CurrentTransmitEndIndex * BUFFER_SIZE; @@ -1037,12 +1118,73 @@ MiniportSend( Desc->FLAGS = TD1_OWN | TD1_STP | TD1_ENP; Desc->BCNT = 0xf000 | -TotalPacketLength; - NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); - NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_IENA | CSR0_TDMD); + NdisMSynchronizeWithInterrupt(&Adapter->InterruptObject, MiSyncStartTransmit, Adapter); + + NdisDprReleaseSpinLock(&Adapter->Lock); return NDIS_STATUS_SUCCESS; } +ULONG +STDCALL +MiEthernetCrc(UCHAR *Address) +/* + * FUNCTION: Calculate Ethernet CRC32 + * ARGUMENTS: + * Address: 6-byte ethernet address + * RETURNS: + * The calculated CRC32 value. + */ +{ + UINT Counter, Length; + ULONG Value = ~0; + + for (Length = 0; Length < 6; Length++) + { + Value ^= *Address++; + for (Counter = 0; Counter < 8; Counter++) + { + Value >>= 1; + Value ^= (Value & 1) * 0xedb88320; + } + } + + return Value; +} + +NDIS_STATUS +STDCALL +MiSetMulticast( + PADAPTER Adapter, + UCHAR *Addresses, + UINT AddressCount) +{ + UINT Index; + ULONG CrcIndex; + + NdisZeroMemory(Adapter->InitializationBlockVirt->LADR, 8); + for (Index = 0; Index < AddressCount; Index++) + { + CrcIndex = MiEthernetCrc(Addresses) >> 26; + Adapter->InitializationBlockVirt->LADR[CrcIndex >> 3] |= 1 << (CrcIndex & 15); + Addresses += 6; + } + + /* FIXME: The specification mentions we need to reload the init block here. */ + + return NDIS_STATUS_SUCCESS; +} + +NDIS_MEDIA_STATE +STDCALL +MiGetMediaState(PADAPTER Adapter) +{ + ULONG Data; + NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR4); + NdisRawReadPortUshort(Adapter->PortOffset + BDP, &Data); + return Data & BCR4_LEDOUT ? NdisMediaStateConnected : NdisMediaStateDisconnected; +} + NTSTATUS STDCALL DriverEntry( @@ -1066,8 +1208,8 @@ DriverEntry( NDIS_STATUS Status; RtlZeroMemory(&Characteristics, sizeof(Characteristics)); - Characteristics.MajorNdisVersion = NDIS_MAJOR_VERSION; - Characteristics.MinorNdisVersion = NDIS_MINOR_VERSION; + Characteristics.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION; + Characteristics.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION; Characteristics.HaltHandler = MiniportHalt; Characteristics.HandleInterruptHandler = MiniportHandleInterrupt; Characteristics.InitializeHandler = MiniportInitialize; @@ -1075,7 +1217,7 @@ DriverEntry( Characteristics.QueryInformationHandler = MiniportQueryInformation; Characteristics.ResetHandler = MiniportReset; Characteristics.SetInformationHandler = MiniportSetInformation; - Characteristics.u1.SendHandler = MiniportSend; + Characteristics.SendHandler = MiniportSend; NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, 0); diff --git a/reactos/drivers/net/dd/pcnet/pcnet.h b/reactos/drivers/net/dd/pcnet/pcnet.h index 589c000384c..d45513fc186 100644 --- a/reactos/drivers/net/dd/pcnet/pcnet.h +++ b/reactos/drivers/net/dd/pcnet/pcnet.h @@ -28,19 +28,6 @@ #ifndef _PCNET_H_ #define _PCNET_H_ -/* FIXME: We should use a general way to do this for all drivers. */ -#ifdef __GNUC__ -#define memcpy(a,b,c) __builtin_memcpy(a,b,c) -#define memset(a,b,c) __builtin_memset(a,b,c) -#undef RtlFillMemory -#define RtlFillMemory(a,b,c) __builtin_memset(a,b,c) -#undef RtlZeroMemory -#define RtlZeroMemory(a,b) __builtin_memset(a,0,b) -#endif - -#define NDIS_MAJOR_VERSION 5 -#define NDIS_MINOR_VERSION 0 - /* statistics struct */ typedef struct _ADAPTER_STATS { @@ -52,6 +39,8 @@ typedef struct _ADAPTER_STATS ULONG XmtExcessiveDefferals; ULONG XmtBufferUnderflows; ULONG XmtBufferErrors; + ULONG XmtOneRetry; + ULONG XmtMoreThanOneRetry; ULONG RcvGoodFrames; ULONG RcvBufferErrors; ULONG RcvCrcErrors; @@ -62,12 +51,16 @@ typedef struct _ADAPTER_STATS /* adapter struct */ typedef struct _ADAPTER { + NDIS_SPIN_LOCK Lock; + NDIS_HANDLE MiniportAdapterHandle; ULONG Flags; ULONG InterruptVector; ULONG IoBaseAddress; PVOID PortOffset; NDIS_MINIPORT_INTERRUPT InterruptObject; + NDIS_MEDIA_STATE MediaState; + NDIS_MINIPORT_TIMER MediaDetectionTimer; ULONG CurrentReceiveDescriptorIndex; ULONG CurrentPacketFilter; ULONG CurrentLookaheadSize; @@ -125,10 +118,23 @@ MiniportSetInformation( OUT PULONG BytesRead, OUT PULONG BytesNeeded); +NDIS_STATUS +STDCALL +MiSetMulticast( + PADAPTER Adapter, + UCHAR *Addresses, + UINT AddressCount); + +NDIS_MEDIA_STATE +STDCALL +MiGetMediaState(PADAPTER Adapter); + /* operational constants */ #define NUMBER_OF_BUFFERS 0x20 #define LOG_NUMBER_OF_BUFFERS 5 /* log2(NUMBER_OF_BUFFERS) */ #define BUFFER_SIZE 0x600 +#define MAX_MULTICAST_ADDRESSES 32 +#define MEDIA_DETECTION_INTERVAL 5000 /* flags */ #define RESET_IN_PROGRESS 0x1 diff --git a/reactos/drivers/net/dd/pcnet/requests.c b/reactos/drivers/net/dd/pcnet/requests.c index 21e4d3b368e..98c62b236f5 100644 --- a/reactos/drivers/net/dd/pcnet/requests.c +++ b/reactos/drivers/net/dd/pcnet/requests.c @@ -24,7 +24,13 @@ * borrowed very heavily from the ReactOS ne2000 driver by * Casper S. Hornstrup (chorns@users.sourceforge.net) * REVISIONS: - * 14-Sept-2003 vizzini - Created + * 14-Sep-2003 vizzini - Created + * 17-Oct-2004 navaraf - Add multicast support. + * - Add media state detection support. + * - Protect the adapter context with spinlock + * and move code talking to card to inside + * NdisMSynchronizeWithInterrupt calls where + * necessary. */ #include @@ -61,6 +67,7 @@ static ULONG MiniportOIDList[] = OID_GEN_XMIT_ERROR, OID_GEN_RCV_ERROR, OID_GEN_RCV_NO_BUFFER, + OID_GEN_RCV_CRC_ERROR, OID_802_3_PERMANENT_ADDRESS, OID_802_3_CURRENT_ADDRESS, OID_802_3_MULTICAST_LIST, @@ -110,6 +117,8 @@ MiniportQueryInformation( ASSERT(Adapter); + NdisAcquireSpinLock(&Adapter->Lock); + Status = NDIS_STATUS_SUCCESS; CopyFrom = (PVOID)&GenericULONG; CopySize = sizeof(ULONG); @@ -191,15 +200,20 @@ MiniportQueryInformation( case OID_GEN_VENDOR_ID: { - GenericULONG = 0x1022; + UCHAR *CharPtr = (UCHAR *)&GenericULONG; + GenericULONG = 0; + /* Read the first three bytes of the permanent MAC address */ + NdisRawReadPortUchar(Adapter->PortOffset, CharPtr); + NdisRawReadPortUchar(Adapter->PortOffset + 1, CharPtr + 1); + NdisRawReadPortUchar(Adapter->PortOffset + 2, CharPtr + 2); break; } case OID_GEN_VENDOR_DESCRIPTION: { - /* XXX implement me */ - CopyFrom = 0; - CopySize = 0; + static UCHAR VendorDesc[] = "ReactOS Team"; + CopyFrom = VendorDesc; + CopySize = sizeof(VendorDesc); break; } @@ -220,7 +234,7 @@ MiniportQueryInformation( { /* NDIS version used by the driver. */ static const USHORT DriverVersion = - (NDIS_MAJOR_VERSION << 8) + NDIS_MINOR_VERSION; + (NDIS_MINIPORT_MAJOR_VERSION << 8) + NDIS_MINIPORT_MINOR_VERSION; CopyFrom = (PVOID)&DriverVersion; CopySize = sizeof(DriverVersion); break; @@ -244,14 +258,13 @@ MiniportQueryInformation( { GenericULONG = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_RECEIVE_SERIALIZED | - NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | - NDIS_MAC_OPTION_NO_LOOPBACK; + NDIS_MAC_OPTION_TRANSFERS_NOT_PEND; break; } case OID_GEN_MEDIA_CONNECT_STATUS: { - GenericULONG = (ULONG)NdisMediaStateConnected; + GenericULONG = Adapter->MediaState; break; } @@ -269,29 +282,12 @@ MiniportQueryInformation( break; } - case OID_802_3_MULTICAST_LIST: - { - /* XXX Implement me */ - PCNET_DbgPrint(("OID_802_3_MULTICAST_LIST.\n")); - Status = NDIS_STATUS_NOT_SUPPORTED; - break; - } - case OID_802_3_MAXIMUM_LIST_SIZE: { - /* XXX Implement me */ - GenericULONG = 0; + GenericULONG = MAX_MULTICAST_ADDRESSES; break; } - case OID_802_3_MAC_OPTIONS: - { - /* XXX Implement me */ - PCNET_DbgPrint(("OID_802_3_MAC_OPTIONS.\n")); - Status = NDIS_STATUS_NOT_SUPPORTED; - break; - } - case OID_GEN_XMIT_OK: GenericULONG = Adapter->Statistics.XmtGoodFrames; break; @@ -318,29 +314,30 @@ MiniportQueryInformation( break; case OID_GEN_RCV_NO_BUFFER: - /* FIXME: Is this correct? */ - GenericULONG = Adapter->Statistics.RcvBufferErrors; + GenericULONG = Adapter->Statistics.RcvBufferErrors + + Adapter->Statistics.RcvOverflowErrors; + break; + + case OID_GEN_RCV_CRC_ERROR: + GenericULONG = Adapter->Statistics.RcvCrcErrors; break; case OID_802_3_RCV_ERROR_ALIGNMENT: - /* XXX Implement me */ - GenericULONG = 0; + GenericULONG = Adapter->Statistics.RcvFramingErrors; break; case OID_802_3_XMIT_ONE_COLLISION: - /* FIXME: Is this correct? */ - GenericULONG = Adapter->Statistics.XmtCollisions; + GenericULONG = Adapter->Statistics.XmtOneRetry; break; case OID_802_3_XMIT_MORE_COLLISIONS: - /* FIXME: Is this correct? */ - GenericULONG = Adapter->Statistics.XmtLateCollisions; + GenericULONG = Adapter->Statistics.XmtMoreThanOneRetry; break; default: { PCNET_DbgPrint(("Unknown OID\n")); - Status = NDIS_STATUS_INVALID_OID; + Status = NDIS_STATUS_NOT_SUPPORTED; break; } } @@ -361,6 +358,8 @@ MiniportQueryInformation( } } + NdisReleaseSpinLock(&Adapter->Lock); + PCNET_DbgPrint(("Leaving. Status is 0x%x\n", Status)); return Status; @@ -400,6 +399,8 @@ MiniportSetInformation( PCNET_DbgPrint(("Called, OID 0x%x\n", Oid)); + NdisAcquireSpinLock(&Adapter->Lock); + switch (Oid) { case OID_GEN_CURRENT_PACKET_FILTER: @@ -470,10 +471,13 @@ MiniportSetInformation( break; } + ASSERT((InformationBufferLength / 6) <= MAX_MULTICAST_ADDRESSES); + /* Set new multicast address list */ //NdisMoveMemory(Adapter->Addresses, InformationBuffer, InformationBufferLength); - /* FIXME: Update hardware */ + /* Update hardware */ + Status = MiSetMulticast(Adapter, InformationBuffer, InformationBufferLength / 6); break; } @@ -483,7 +487,7 @@ MiniportSetInformation( PCNET_DbgPrint(("Invalid object ID (0x%X).\n", Oid)); *BytesRead = 0; *BytesNeeded = 0; - Status = NDIS_STATUS_INVALID_OID; + Status = NDIS_STATUS_NOT_SUPPORTED; break; } } @@ -494,6 +498,8 @@ MiniportSetInformation( *BytesNeeded = 0; } + NdisReleaseSpinLock(&Adapter->Lock); + PCNET_DbgPrint(("Leaving. Status (0x%X).\n", Status)); return Status;