mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[DC21X4] Add driver for DECchip 21x4-compatible network adapters (#5614)
These adapters were common in DEC Alpha boxes and they are really rare nowadays. The 21140 chip is emulated in Connectix / Microsoft Virtual PC and Hyper-V Gen 1 VM. This is an experimental driver, not yet tested on real hardware. CORE-8724
This commit is contained in:
parent
a8e8add0c0
commit
59d8a77df6
28 changed files with 9751 additions and 2 deletions
|
@ -138,8 +138,6 @@ Signature = "$Windows NT$"
|
|||
"modules/optional/bcmwl5.sys" 3 optional
|
||||
"modules/optional/alcxwdm.inf" 6 optional
|
||||
"modules/optional/alcxwdm.sys" 3 optional
|
||||
"modules/optional/net21x4.inf" 6 optional
|
||||
"modules/optional/dc21x4.sys" 3 optional
|
||||
"modules/optional/mfc42.dll" 2 optional
|
||||
"modules/optional/mfc42u.dll" 2 optional
|
||||
"modules/optional/mfc71.dll" 2 optional
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
add_subdirectory(dc21x4)
|
||||
add_subdirectory(e1000)
|
||||
add_subdirectory(ne2000)
|
||||
add_subdirectory(netkvm)
|
||||
|
|
40
drivers/network/dd/dc21x4/CMakeLists.txt
Normal file
40
drivers/network/dd/dc21x4/CMakeLists.txt
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
add_definitions(
|
||||
-DNDIS_MINIPORT_DRIVER
|
||||
-DNDIS51_MINIPORT=1)
|
||||
|
||||
list(APPEND SOURCE
|
||||
dc21x4.c
|
||||
dc21x4.h
|
||||
dc21x4hw.h
|
||||
debug.h
|
||||
eeprom.c
|
||||
eeprom.h
|
||||
eeprom_data.c
|
||||
hardware.c
|
||||
init.c
|
||||
interrupt.c
|
||||
media.c
|
||||
media040.c
|
||||
media041.c
|
||||
media140.c
|
||||
media143.c
|
||||
phy.c
|
||||
power.c
|
||||
requests.c
|
||||
send.c
|
||||
util.h)
|
||||
|
||||
if(DBG)
|
||||
list(APPEND SOURCE debug.c)
|
||||
endif()
|
||||
|
||||
add_library(dc21x4 MODULE ${SOURCE} dc21x4.rc)
|
||||
if(DBG)
|
||||
target_link_libraries(dc21x4 memcmp)
|
||||
endif()
|
||||
add_pch(dc21x4 dc21x4.h SOURCE)
|
||||
set_module_type(dc21x4 kernelmodedriver)
|
||||
add_importlibs(dc21x4 ndis ntoskrnl hal)
|
||||
add_cd_file(TARGET dc21x4 DESTINATION reactos/system32/drivers FOR all)
|
||||
add_driver_inf(dc21x4 net21x4.inf)
|
401
drivers/network/dd/dc21x4/dc21x4.c
Normal file
401
drivers/network/dd/dc21x4/dc21x4.c
Normal file
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Miniport driver entry
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
ULONG
|
||||
DcEthernetCrc(
|
||||
_In_reads_bytes_(Size) const VOID* Buffer,
|
||||
_In_ ULONG Size)
|
||||
{
|
||||
ULONG i, j, Crc;
|
||||
const UCHAR* Data = Buffer;
|
||||
|
||||
Crc = 0xFFFFFFFF;
|
||||
for (i = 0; i < Size; ++i)
|
||||
{
|
||||
Crc ^= Data[i];
|
||||
for (j = 8; j > 0; j--)
|
||||
{
|
||||
/* CRC-32 polynomial little-endian */
|
||||
Crc = (Crc >> 1) ^ (-(LONG)(Crc & 1) & 0xEDB88320);
|
||||
}
|
||||
}
|
||||
|
||||
return Crc;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcFlushTransmitQueue(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
LIST_ENTRY DoneList;
|
||||
PLIST_ENTRY Entry;
|
||||
PNDIS_PACKET Packet;
|
||||
PDC_TCB Tcb;
|
||||
|
||||
InitializeListHead(&DoneList);
|
||||
|
||||
NdisAcquireSpinLock(&Adapter->SendLock);
|
||||
|
||||
/* Remove pending transmissions from the transmit ring */
|
||||
for (Tcb = Adapter->LastTcb;
|
||||
Tcb != Adapter->CurrentTcb;
|
||||
Tcb = DC_NEXT_TCB(Adapter, Tcb))
|
||||
{
|
||||
Packet = Tcb->Packet;
|
||||
|
||||
if (!Packet)
|
||||
continue;
|
||||
|
||||
InsertTailList(&DoneList, DC_LIST_ENTRY_FROM_PACKET(Packet));
|
||||
|
||||
DC_RELEASE_TCB(Adapter, Tcb);
|
||||
}
|
||||
Adapter->CurrentTcb = Tcb;
|
||||
|
||||
/* Remove pending transmissions from the internal queue */
|
||||
while (!IsListEmpty(&Adapter->SendQueueList))
|
||||
{
|
||||
Entry = RemoveHeadList(&Adapter->SendQueueList);
|
||||
|
||||
InsertTailList(&DoneList, Entry);
|
||||
}
|
||||
|
||||
NdisReleaseSpinLock(&Adapter->SendLock);
|
||||
|
||||
while (!IsListEmpty(&DoneList))
|
||||
{
|
||||
Entry = RemoveHeadList(&DoneList);
|
||||
|
||||
NdisMSendComplete(Adapter->AdapterHandle,
|
||||
DC_PACKET_FROM_LIST_ENTRY(Entry),
|
||||
NDIS_STATUS_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcStopReceivePath(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
BOOLEAN RxStopped;
|
||||
|
||||
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||||
|
||||
#if DBG
|
||||
NdisAcquireSpinLock(&Adapter->ReceiveLock);
|
||||
if (Adapter->RcbFree != Adapter->RcbCount)
|
||||
{
|
||||
INFO("RX packets: %u/%u\n", Adapter->RcbFree, Adapter->RcbCount);
|
||||
}
|
||||
NdisReleaseSpinLock(&Adapter->ReceiveLock);
|
||||
#endif
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
NdisAcquireSpinLock(&Adapter->ReceiveLock);
|
||||
|
||||
RxStopped = (Adapter->RcbFree == Adapter->RcbCount);
|
||||
|
||||
NdisReleaseSpinLock(&Adapter->ReceiveLock);
|
||||
|
||||
if (RxStopped)
|
||||
break;
|
||||
|
||||
NdisMSleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
DECLSPEC_NOINLINE /* Called from pageable code */
|
||||
VOID
|
||||
DcStopAdapter(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN WaitForPackets)
|
||||
{
|
||||
BOOLEAN TimerCancelled;
|
||||
|
||||
/* Attempt to disable interrupts to complete more quickly */
|
||||
DC_WRITE(Adapter, DcCsr7_IrqMask, 0);
|
||||
|
||||
/* Prevent DPCs from executing and stop accepting incoming packets */
|
||||
NdisAcquireSpinLock(&Adapter->SendLock);
|
||||
Adapter->Flags &= ~DC_ACTIVE;
|
||||
NdisReleaseSpinLock(&Adapter->SendLock);
|
||||
|
||||
NdisMCancelTimer(&Adapter->MediaMonitorTimer, &TimerCancelled);
|
||||
|
||||
/* Wait for any DPCs to complete */
|
||||
KeFlushQueuedDpcs();
|
||||
|
||||
/* Disable interrupts */
|
||||
DC_WRITE(Adapter, DcCsr7_IrqMask, 0);
|
||||
|
||||
/* Wait for completion of TX/RX and stop the DMA engine inside the NIC */
|
||||
DcStopTxRxProcess(Adapter);
|
||||
Adapter->OpMode &= ~(DC_OPMODE_RX_ENABLE | DC_OPMODE_TX_ENABLE);
|
||||
|
||||
DcFlushTransmitQueue(Adapter);
|
||||
|
||||
/* Wait for the packets to be returned to the driver */
|
||||
if (WaitForPackets)
|
||||
{
|
||||
DcStopReceivePath(Adapter);
|
||||
}
|
||||
|
||||
/* Make sure there is no pending OID request */
|
||||
if (Adapter->OidPending)
|
||||
{
|
||||
NdisMSetInformationComplete(Adapter->AdapterHandle, NDIS_STATUS_SUCCESS);
|
||||
|
||||
Adapter->OidPending = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcStartAdapter(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
/* Enable interrupts */
|
||||
_InterlockedExchange((PLONG)&Adapter->CurrentInterruptMask, Adapter->InterruptMask);
|
||||
DC_WRITE(Adapter, DcCsr7_IrqMask, Adapter->InterruptMask);
|
||||
|
||||
Adapter->Flags |= DC_ACTIVE;
|
||||
|
||||
/* Start the RX process */
|
||||
Adapter->OpMode |= DC_OPMODE_RX_ENABLE;
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, Adapter->OpMode);
|
||||
|
||||
/* Start the media monitor, wait the selected media to become ready */
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, 2400);
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
NTAPI
|
||||
DcResetWorker(
|
||||
_In_ PNDIS_WORK_ITEM WorkItem,
|
||||
_In_opt_ PVOID Context)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = Context;
|
||||
NDIS_STATUS Status;
|
||||
ULONG InterruptStatus;
|
||||
LONG ResetReason;
|
||||
|
||||
UNREFERENCED_PARAMETER(WorkItem);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
Status = NDIS_STATUS_SUCCESS;
|
||||
|
||||
/* Check if the device is present */
|
||||
InterruptStatus = DC_READ(Adapter, DcCsr5_Status);
|
||||
if (InterruptStatus == 0xFFFFFFFF)
|
||||
{
|
||||
ERR("Hardware is gone...\n");
|
||||
|
||||
/* Remove this adapter */
|
||||
NdisMRemoveMiniport(Adapter->AdapterHandle);
|
||||
|
||||
Status = NDIS_STATUS_HARD_ERRORS;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
DcStopAdapter(Adapter, FALSE);
|
||||
|
||||
if (Adapter->LinkUp)
|
||||
{
|
||||
Adapter->LinkUp = FALSE;
|
||||
|
||||
NdisMIndicateStatus(Adapter->AdapterHandle,
|
||||
NDIS_STATUS_MEDIA_DISCONNECT,
|
||||
NULL,
|
||||
0);
|
||||
NdisMIndicateStatusComplete(Adapter->AdapterHandle);
|
||||
}
|
||||
|
||||
DcSetupAdapter(Adapter);
|
||||
|
||||
DcStartAdapter(Adapter);
|
||||
|
||||
Done:
|
||||
ResetReason = _InterlockedExchange(&Adapter->ResetLock, 0);
|
||||
|
||||
/* Complete the pending reset request */
|
||||
if (ResetReason == 1)
|
||||
{
|
||||
NdisMResetComplete(Adapter->AdapterHandle, Status, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcTransmitTimeoutRecoveryWorker(
|
||||
_In_ PNDIS_WORK_ITEM WorkItem,
|
||||
_In_opt_ PVOID Context)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = Context;
|
||||
|
||||
UNREFERENCED_PARAMETER(WorkItem);
|
||||
|
||||
NdisAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
DcStopTxRxProcess(Adapter);
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, Adapter->OpMode);
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->SendLock);
|
||||
|
||||
DC_WRITE(Adapter, DcCsr1_TxPoll, DC_TX_POLL_DOORBELL);
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->SendLock);
|
||||
|
||||
NdisReleaseSpinLock(&Adapter->ModeLock);
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
DcCheckForHang(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
ULONG TcbCompleted;
|
||||
BOOLEAN TxHang = FALSE;
|
||||
|
||||
if (!(Adapter->Flags & DC_ACTIVE))
|
||||
return FALSE;
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->SendLock);
|
||||
|
||||
if (Adapter->TcbSlots != (DC_TRANSMIT_BLOCKS - DC_TCB_RESERVE))
|
||||
{
|
||||
TcbCompleted = Adapter->TcbCompleted;
|
||||
TxHang = (TcbCompleted == Adapter->LastTcbCompleted);
|
||||
Adapter->LastTcbCompleted = TcbCompleted;
|
||||
}
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->SendLock);
|
||||
|
||||
if (TxHang)
|
||||
{
|
||||
WARN("Transmit timeout, CSR12 %08lx, CSR5 %08lx\n",
|
||||
DC_READ(Adapter, DcCsr12_SiaStatus),
|
||||
DC_READ(Adapter, DcCsr5_Status));
|
||||
|
||||
NdisScheduleWorkItem(&Adapter->TxRecoveryWorkItem);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
NDIS_STATUS
|
||||
NTAPI
|
||||
DcReset(
|
||||
_Out_ PBOOLEAN AddressingReset,
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
|
||||
WARN("Called\n");
|
||||
|
||||
if (_InterlockedCompareExchange(&Adapter->ResetLock, 1, 0))
|
||||
{
|
||||
return NDIS_STATUS_RESET_IN_PROGRESS;
|
||||
}
|
||||
|
||||
NdisScheduleWorkItem(&Adapter->ResetWorkItem);
|
||||
|
||||
return NDIS_STATUS_PENDING;
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
NTAPI
|
||||
DcHalt(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
INFO("Called\n");
|
||||
|
||||
DcStopAdapter(Adapter, TRUE);
|
||||
|
||||
DcDisableHw(Adapter);
|
||||
|
||||
DcFreeAdapter(Adapter);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
NTAPI
|
||||
DcShutdown(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
|
||||
INFO("Called\n");
|
||||
|
||||
DcDisableHw(Adapter);
|
||||
}
|
||||
|
||||
CODE_SEG("INIT")
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DriverEntry(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
_In_ PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
NDIS_HANDLE WrapperHandle;
|
||||
NDIS_STATUS Status;
|
||||
NDIS_MINIPORT_CHARACTERISTICS Characteristics = { 0 };
|
||||
|
||||
INFO("Called\n");
|
||||
|
||||
NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);
|
||||
if (!WrapperHandle)
|
||||
return NDIS_STATUS_FAILURE;
|
||||
|
||||
Characteristics.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
|
||||
Characteristics.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
|
||||
Characteristics.CheckForHangHandler = DcCheckForHang;
|
||||
Characteristics.HaltHandler = DcHalt;
|
||||
Characteristics.HandleInterruptHandler = DcHandleInterrupt;
|
||||
Characteristics.InitializeHandler = DcInitialize;
|
||||
Characteristics.ISRHandler = DcIsr;
|
||||
Characteristics.QueryInformationHandler = DcQueryInformation;
|
||||
Characteristics.ResetHandler = DcReset;
|
||||
Characteristics.SetInformationHandler = DcSetInformation;
|
||||
Characteristics.ReturnPacketHandler = DcReturnPacket;
|
||||
Characteristics.SendPacketsHandler = DcSendPackets;
|
||||
Characteristics.CancelSendPacketsHandler = DcCancelSendPackets;
|
||||
Characteristics.AdapterShutdownHandler = DcShutdown;
|
||||
|
||||
Status = NdisMRegisterMiniport(WrapperHandle, &Characteristics, sizeof(Characteristics));
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
NdisTerminateWrapper(WrapperHandle, NULL);
|
||||
return Status;
|
||||
}
|
||||
|
||||
InitializeListHead(&SRompAdapterList);
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
}
|
541
drivers/network/dd/dc21x4/dc21x4.h
Normal file
541
drivers/network/dd/dc21x4/dc21x4.h
Normal file
|
@ -0,0 +1,541 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Main header file
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !DBG
|
||||
#define NO_KERNEL_LIST_ENTRY_CHECKS
|
||||
#endif
|
||||
#include <ndis.h>
|
||||
#include <section_attribs.h>
|
||||
|
||||
#include "dc21x4hw.h"
|
||||
#include "eeprom.h"
|
||||
#include "media.h"
|
||||
#include "util.h"
|
||||
|
||||
#define DC21X4_TAG '4x12'
|
||||
|
||||
#define DC_TRANSMIT_DESCRIPTORS 64
|
||||
#define DC_TRANSMIT_BLOCKS 48
|
||||
#define DC_TRANSMIT_BUFFERS 4
|
||||
#define DC_LOOPBACK_FRAMES 4
|
||||
|
||||
#define DC_RECEIVE_BUFFERS_DEFAULT 64
|
||||
#define DC_RECEIVE_BUFFERS_MIN 8
|
||||
#define DC_RECEIVE_BUFFERS_EXTRA 16
|
||||
|
||||
#define DC_RECEIVE_ARRAY_SIZE 16
|
||||
|
||||
#define DC_MULTICAST_LIST_SIZE 36
|
||||
|
||||
#define DC_MAXIMUM_FRAME_SIZE 1514
|
||||
#define DC_TRANSMIT_BLOCK_SIZE 1536
|
||||
#define DC_RECEIVE_BLOCK_SIZE 1536
|
||||
#define DC_ETHERNET_HEADER_SIZE 14
|
||||
|
||||
#define DC_TX_UNDERRUN_LIMIT 5
|
||||
#define DC_INTERRUPT_PROCESSING_LIMIT 8
|
||||
|
||||
#define DC_FRAGMENTATION_THRESHOLD 32
|
||||
|
||||
#define DC_PACKET_FILTERS ( \
|
||||
NDIS_PACKET_TYPE_DIRECTED | \
|
||||
NDIS_PACKET_TYPE_MULTICAST | \
|
||||
NDIS_PACKET_TYPE_BROADCAST | \
|
||||
NDIS_PACKET_TYPE_PROMISCUOUS | \
|
||||
NDIS_PACKET_TYPE_ALL_MULTICAST)
|
||||
|
||||
#define DC_LOOPBACK_FRAME_SIZE 64
|
||||
|
||||
/* Transmit descriptors reserved for internal use */
|
||||
#define DC_TBD_RESERVE (2 + DC_LOOPBACK_FRAMES) /* (+2 for setup frame) */
|
||||
#define DC_TCB_RESERVE (1 + DC_LOOPBACK_FRAMES) /* (+1 for setup frame) */
|
||||
|
||||
#define DC_EVENT_SETUP_FRAME_COMPLETED 0x00000001
|
||||
|
||||
typedef struct _DC21X4_ADAPTER DC21X4_ADAPTER, *PDC21X4_ADAPTER;
|
||||
typedef struct _DC_TCB DC_TCB, *PDC_TCB;
|
||||
typedef struct _DC_RCB DC_RCB, *PDC_RCB;
|
||||
typedef struct _DC_COALESCE_BUFFER DC_COALESCE_BUFFER, *PDC_COALESCE_BUFFER;
|
||||
|
||||
typedef VOID
|
||||
(MEDIA_HANDLE_LINK_STATE_CHANGE)(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG InterruptStatus);
|
||||
typedef MEDIA_HANDLE_LINK_STATE_CHANGE *PMEDIA_HANDLE_LINK_STATE_CHANGE;
|
||||
|
||||
typedef struct _DC_TX_BUFFER_DATA
|
||||
{
|
||||
PVOID VirtualAddress;
|
||||
NDIS_PHYSICAL_ADDRESS PhysicalAddress;
|
||||
} DC_TX_BUFFER_DATA, *PDC_TX_BUFFER_DATA;
|
||||
|
||||
typedef struct _DC_STATISTICS
|
||||
{
|
||||
ULONG64 TransmitOk;
|
||||
ULONG64 TransmitDeferred;
|
||||
ULONG64 TransmitHeartbeatErrors;
|
||||
ULONG64 TransmitOneRetry;
|
||||
ULONG64 TransmitMoreCollisions;
|
||||
ULONG64 TransmitErrors;
|
||||
ULONG64 TransmitExcessiveCollisions;
|
||||
ULONG64 TransmitUnderrunErrors;
|
||||
ULONG64 TransmitLostCarrierSense;
|
||||
ULONG64 TransmitLateCollisions;
|
||||
ULONG64 ReceiveOk;
|
||||
ULONG64 ReceiveBroadcast;
|
||||
ULONG64 ReceiveMulticast;
|
||||
ULONG64 ReceiveUnicast;
|
||||
ULONG64 ReceiveErrors;
|
||||
ULONG64 ReceiveOverrunErrors;
|
||||
ULONG64 ReceiveNoBuffers;
|
||||
ULONG64 ReceiveCrcErrors;
|
||||
ULONG64 ReceiveAlignmentErrors;
|
||||
} DC_STATISTICS, *PDC_STATISTICS;
|
||||
|
||||
typedef struct _DC21X4_ADAPTER
|
||||
{
|
||||
PUCHAR IoBase;
|
||||
ULONG InterruptMask;
|
||||
ULONG CurrentInterruptMask;
|
||||
|
||||
ULONG Features;
|
||||
#define DC_NEED_RX_OVERFLOW_WORKAROUND 0x80000000
|
||||
#define DC_SIA_GPIO 0x00000001
|
||||
#define DC_SIA_ANALOG_CONTROL 0x00000002
|
||||
#define DC_HAS_POWER_MANAGEMENT 0x00000004
|
||||
#define DC_HAS_POWER_SAVING 0x00000008
|
||||
#define DC_HAS_MII 0x00000010
|
||||
#define DC_PERFECT_FILTERING_ONLY 0x00000020
|
||||
#define DC_ENABLE_PCI_COMMANDS 0x00000040
|
||||
#define DC_MII_AUTOSENSE 0x00000080
|
||||
#define DC_HAS_TIMER 0x00000100
|
||||
|
||||
ULONG Flags;
|
||||
#define DC_ACTIVE 0x80000000
|
||||
#define DC_IO_MAPPED 0x00000001
|
||||
#define DC_IRQ_SHARED 0x00000002
|
||||
#define DC_FIRST_SETUP 0x00000004
|
||||
#define DC_AUTOSENSE 0x00000008
|
||||
|
||||
ULONG InterruptStatus;
|
||||
PMEDIA_HANDLE_LINK_STATE_CHANGE HandleLinkStateChange;
|
||||
|
||||
DECLSPEC_CACHEALIGN NDIS_SPIN_LOCK SendLock;
|
||||
PDC_TCB TailTcb;
|
||||
PDC_TCB LastTcb;
|
||||
PDC_TCB CurrentTcb;
|
||||
PDC_TBD CurrentTbd;
|
||||
PDC_TBD HeadTbd;
|
||||
PDC_TBD TailTbd;
|
||||
LIST_ENTRY SendQueueList;
|
||||
ULONG TcbSlots;
|
||||
ULONG TbdSlots;
|
||||
ULONG TcbCompleted;
|
||||
ULONG LastTcbCompleted;
|
||||
PDC_TCB HeadTcb;
|
||||
SINGLE_LIST_ENTRY SendBufferList;
|
||||
SCATTER_GATHER_LIST LocalSgList;
|
||||
|
||||
DECLSPEC_CACHEALIGN NDIS_SPIN_LOCK ReceiveLock;
|
||||
PDC_RCB* RcbArray;
|
||||
PDC_RBD CurrentRbd;
|
||||
PDC_RBD HeadRbd;
|
||||
PDC_RBD TailRbd;
|
||||
SINGLE_LIST_ENTRY FreeRcbList;
|
||||
ULONG RcbFree;
|
||||
|
||||
ULONG TransmitUnderruns;
|
||||
ULONG PacketFilter;
|
||||
|
||||
DC_STATISTICS Statistics;
|
||||
|
||||
NDIS_HANDLE AdapterHandle;
|
||||
NDIS_HANDLE WrapperConfigurationHandle;
|
||||
|
||||
DECLSPEC_CACHEALIGN NDIS_SPIN_LOCK ModeLock;
|
||||
ULONG ModeFlags;
|
||||
#define DC_MODE_AUTONEG_MASK 0x0000000F
|
||||
#define DC_MODE_PORT_AUTOSENSE 0x00000010
|
||||
#define DC_MODE_TEST_PACKET 0x00000020
|
||||
#define DC_MODE_AUI_FAILED 0x00000040
|
||||
#define DC_MODE_BNC_FAILED 0x00000080
|
||||
|
||||
#define DC_MODE_AUTONEG_NONE 0x00000000
|
||||
#define DC_MODE_AUTONEG_WAIT_INTERRUPT 0x00000001
|
||||
#define DC_MODE_AUTONEG_LINK_STATUS_CHECK 0x00000002
|
||||
|
||||
ULONG OpMode;
|
||||
ULONG MediaNumber;
|
||||
ULONG MediaBitmap;
|
||||
BOOLEAN LinkUp;
|
||||
ULONG PhyAddress;
|
||||
ULONG SiaSetting;
|
||||
ULONG LastReceiveActivity;
|
||||
volatile LONG MediaTestStatus;
|
||||
NDIS_MINIPORT_TIMER MediaMonitorTimer;
|
||||
DC_MII_MEDIA MiiMedia;
|
||||
DC_MEDIA Media[MEDIA_LIST_MAX];
|
||||
|
||||
ULONG AnalogControl;
|
||||
ULONG SymAdvertising;
|
||||
ULONG MiiAdvertising;
|
||||
ULONG MiiControl;
|
||||
DC_CHIP_TYPE ChipType;
|
||||
ULONG LinkStateChangeMask;
|
||||
|
||||
ULONG WakeUpFlags;
|
||||
NDIS_DEVICE_POWER_STATE PowerState;
|
||||
NDIS_DEVICE_POWER_STATE PrevPowerState;
|
||||
|
||||
ULONG HpnaInitBitmap;
|
||||
UCHAR HpnaRegister[32];
|
||||
|
||||
UCHAR PermanentMacAddress[ETH_LENGTH_OF_ADDRESS];
|
||||
UCHAR CurrentMacAddress[ETH_LENGTH_OF_ADDRESS];
|
||||
|
||||
ULONG MulticastMaxEntries;
|
||||
_Field_range_(0, MulticastMaxEntries)
|
||||
ULONG MulticastCount;
|
||||
struct
|
||||
{
|
||||
UCHAR MacAddress[ETH_LENGTH_OF_ADDRESS];
|
||||
} MulticastList[DC_MULTICAST_LIST_SIZE];
|
||||
|
||||
ULONG LinkSpeedMbps;
|
||||
ULONG BusMode;
|
||||
ULONG DefaultMedia;
|
||||
ULONG RcbCount;
|
||||
BOOLEAN OidPending;
|
||||
BOOLEAN ProgramHashPerfectFilter;
|
||||
PULONG SetupFrame;
|
||||
PULONG SetupFrameSaved;
|
||||
ULONG SetupFramePhys;
|
||||
ULONG LoopbackFrameSlots;
|
||||
ULONG LoopbackFrameNumber;
|
||||
ULONG LoopbackFramePhys[DC_LOOPBACK_FRAMES];
|
||||
ULONG BusNumber;
|
||||
UCHAR DeviceNumber;
|
||||
UCHAR RevisionId;
|
||||
UCHAR ControllerIndex;
|
||||
UCHAR ResetStreamLength;
|
||||
USHORT ResetStream[SROM_MAX_STREAM_REGS];
|
||||
USHORT DeviceId;
|
||||
SINGLE_LIST_ENTRY AllocRcbList;
|
||||
SINGLE_LIST_ENTRY UsedRcbList;
|
||||
NDIS_MINIPORT_INTERRUPT Interrupt;
|
||||
ULONG InterruptVector;
|
||||
ULONG InterruptLevel;
|
||||
ULONG InterruptFlags;
|
||||
ULONG AdapterSize;
|
||||
NDIS_WORK_ITEM PowerWorkItem;
|
||||
NDIS_WORK_ITEM ResetWorkItem;
|
||||
NDIS_WORK_ITEM TxRecoveryWorkItem;
|
||||
_Interlocked_ volatile LONG ResetLock;
|
||||
NDIS_PHYSICAL_ADDRESS IoBaseAddress;
|
||||
PDC_SROM_ENTRY SRomEntry;
|
||||
PVOID AdapterOriginal;
|
||||
PVOID TbdOriginal;
|
||||
PVOID RbdOriginal;
|
||||
ULONG TbdPhys;
|
||||
ULONG RbdPhys;
|
||||
NDIS_HANDLE BufferPool;
|
||||
NDIS_HANDLE PacketPool;
|
||||
NDIS_PHYSICAL_ADDRESS TbdPhysOriginal;
|
||||
NDIS_PHYSICAL_ADDRESS RbdPhysOriginal;
|
||||
PVOID LoopbackFrame[DC_LOOPBACK_FRAMES];
|
||||
PDC_COALESCE_BUFFER CoalesceBuffer;
|
||||
DC_TX_BUFFER_DATA SendBufferData[DC_TRANSMIT_BUFFERS];
|
||||
} DC21X4_ADAPTER, *PDC21X4_ADAPTER;
|
||||
|
||||
#include "sendrcv.h"
|
||||
|
||||
extern LIST_ENTRY SRompAdapterList;
|
||||
|
||||
FORCEINLINE
|
||||
ULONG
|
||||
DC_READ(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ DC_CSR Register)
|
||||
{
|
||||
ULONG Value;
|
||||
|
||||
NdisRawReadPortUlong((PULONG)(Adapter->IoBase + Register), &Value);
|
||||
return Value;
|
||||
}
|
||||
|
||||
#define DC_WRITE(Adapter, Register, Value) \
|
||||
NdisRawWritePortUlong((PULONG)((Adapter)->IoBase + (Register)), (Value));
|
||||
|
||||
CODE_SEG("INIT")
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
NDIS_STATUS
|
||||
NTAPI
|
||||
DcInitialize(
|
||||
_Out_ PNDIS_STATUS OpenErrorStatus,
|
||||
_Out_ PUINT SelectedMediumIndex,
|
||||
_In_ PNDIS_MEDIUM MediumArray,
|
||||
_In_ UINT MediumArraySize,
|
||||
_In_ NDIS_HANDLE MiniportAdapterHandle,
|
||||
_In_ NDIS_HANDLE WrapperConfigurationContext);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcSendPackets(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ PPNDIS_PACKET PacketArray,
|
||||
_In_ UINT NumberOfPackets);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcCancelSendPackets(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ PVOID CancelId);
|
||||
|
||||
VOID
|
||||
DcProcessPendingPackets(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcReturnPacket(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ PNDIS_PACKET Packet);
|
||||
|
||||
NDIS_STATUS
|
||||
NTAPI
|
||||
DcQueryInformation(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ NDIS_OID Oid,
|
||||
_In_ PVOID InformationBuffer,
|
||||
_In_ ULONG InformationBufferLength,
|
||||
_Out_ PULONG BytesWritten,
|
||||
_Out_ PULONG BytesNeeded);
|
||||
|
||||
NDIS_STATUS
|
||||
NTAPI
|
||||
DcSetInformation(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ NDIS_OID Oid,
|
||||
_In_ PVOID InformationBuffer,
|
||||
_In_ ULONG InformationBufferLength,
|
||||
_Out_ PULONG BytesRead,
|
||||
_Out_ PULONG BytesNeeded);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcIsr(
|
||||
_Out_ PBOOLEAN InterruptRecognized,
|
||||
_Out_ PBOOLEAN QueueMiniportHandleInterrupt,
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcHandleInterrupt(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
NTAPI
|
||||
DcPowerWorker(
|
||||
_In_ PNDIS_WORK_ITEM WorkItem,
|
||||
_In_opt_ PVOID Context);
|
||||
|
||||
NDIS_STATUS
|
||||
DcSetPower(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ NDIS_DEVICE_POWER_STATE PowerState);
|
||||
|
||||
NDIS_STATUS
|
||||
DcAddWakeUpPattern(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PNDIS_PM_PACKET_PATTERN PmPattern);
|
||||
|
||||
NDIS_STATUS
|
||||
DcRemoveWakeUpPattern(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PNDIS_PM_PACKET_PATTERN PmPattern);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcFreeAdapter(
|
||||
_In_ __drv_freesMem(Mem) PDC21X4_ADAPTER Adapter);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
NTAPI
|
||||
DcResetWorker(
|
||||
_In_ PNDIS_WORK_ITEM WorkItem,
|
||||
_In_opt_ PVOID Context);
|
||||
|
||||
DECLSPEC_NOINLINE
|
||||
VOID
|
||||
DcStopAdapter(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN WaitForPackets);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcStartAdapter(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
NDIS_STATUS
|
||||
DcSetupAdapter(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
NDIS_STATUS
|
||||
DcReadEeprom(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcFreeEeprom(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcInitTxRing(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcInitRxRing(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
ULONG
|
||||
DcEthernetCrc(
|
||||
_In_reads_bytes_(Size) const VOID* Buffer,
|
||||
_In_ ULONG Size);
|
||||
|
||||
VOID
|
||||
DcDisableHw(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
VOID
|
||||
DcStopTxRxProcess(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
VOID
|
||||
DcWriteGpio(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG Value);
|
||||
|
||||
VOID
|
||||
DcWriteSia(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG Csr13,
|
||||
_In_ ULONG Csr14,
|
||||
_In_ ULONG Csr15);
|
||||
|
||||
VOID
|
||||
DcTestPacket(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcSetupFrameInitialize(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
BOOLEAN
|
||||
DcSetupFrameDownload(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN WaitForCompletion);
|
||||
|
||||
NDIS_STATUS
|
||||
DcApplyPacketFilter(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG PacketFilter);
|
||||
|
||||
NDIS_STATUS
|
||||
DcUpdateMulticastList(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
VOID
|
||||
DcPowerSave(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN Enable);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
BOOLEAN
|
||||
DcFindMiiPhy(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
BOOLEAN
|
||||
MiiWrite(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG PhyAddress,
|
||||
_In_ ULONG RegAddress,
|
||||
_In_ ULONG Data);
|
||||
|
||||
BOOLEAN
|
||||
MiiRead(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG PhyAddress,
|
||||
_In_ ULONG RegAddress,
|
||||
_Out_ PULONG Data);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
HpnaPhyInit(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcTransmitTimeoutRecoveryWorker(
|
||||
_In_ PNDIS_WORK_ITEM WorkItem,
|
||||
_In_opt_ PVOID Context);
|
||||
|
||||
NDIS_TIMER_FUNCTION MediaMonitor21040Dpc;
|
||||
NDIS_TIMER_FUNCTION MediaMonitor21041Dpc;
|
||||
NDIS_TIMER_FUNCTION MediaMonitor21140Dpc;
|
||||
NDIS_TIMER_FUNCTION MediaMonitor21143Dpc;
|
||||
|
||||
MEDIA_HANDLE_LINK_STATE_CHANGE MediaLinkStateChange21040;
|
||||
MEDIA_HANDLE_LINK_STATE_CHANGE MediaLinkStateChange21041;
|
||||
MEDIA_HANDLE_LINK_STATE_CHANGE MediaLinkStateChange21143;
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
MediaInitMediaList(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
MediaInitDefaultMedia(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG MediaNumber);
|
||||
|
||||
VOID
|
||||
MediaIndicateConnect(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN LinkUp);
|
||||
|
||||
VOID
|
||||
MediaSelectMiiPort(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN ResetPhy);
|
||||
|
||||
VOID
|
||||
MediaMiiSelect(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
BOOLEAN
|
||||
MediaMiiCheckLink(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
VOID
|
||||
MediaSiaSelect(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
||||
|
||||
VOID
|
||||
MediaGprSelect(
|
||||
_In_ PDC21X4_ADAPTER Adapter);
|
5
drivers/network/dd/dc21x4/dc21x4.rc
Normal file
5
drivers/network/dd/dc21x4/dc21x4.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "DC21x4 Ethernet Adapter Driver"
|
||||
#define REACTOS_STR_INTERNAL_NAME "dc21x4"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "dc21x4.sys"
|
||||
#include <reactos/version.rc>
|
597
drivers/network/dd/dc21x4/dc21x4hw.h
Normal file
597
drivers/network/dd/dc21x4/dc21x4hw.h
Normal file
|
@ -0,0 +1,597 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Hardware specific definitions
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum _DC_CHIP_TYPE
|
||||
{
|
||||
DC21040,
|
||||
DC21041,
|
||||
DC21140,
|
||||
DC21143,
|
||||
DC21145,
|
||||
} DC_CHIP_TYPE;
|
||||
|
||||
/*
|
||||
* PCI Vendor and Device IDs
|
||||
*/
|
||||
#define DC_DEV_DECCHIP_21040 0x00021011
|
||||
#define DC_DEV_DECCHIP_21041 0x00141011
|
||||
#define DC_DEV_DECCHIP_21140 0x00091011
|
||||
#define DC_DEV_INTEL_21143 0x00191011
|
||||
#define DC_DEV_INTEL_21145 0x00398086
|
||||
|
||||
#define DC_DESCRIPTOR_ALIGNMENT 4
|
||||
#define DC_SETUP_FRAME_ALIGNMENT 4
|
||||
#define DC_RECEIVE_BUFFER_ALIGNMENT 4
|
||||
#define DC_RECEIVE_BUFFER_SIZE_MULTIPLE 4
|
||||
|
||||
#define DC_IO_LENGTH 128
|
||||
|
||||
#define DC_SETUP_FRAME_SIZE 192
|
||||
|
||||
/* Multicast perfect filter */
|
||||
#define DC_SETUP_FRAME_PERFECT_FILTER_ADDRESSES 16
|
||||
|
||||
/* -1 for physical address and -1 for broadcast address */
|
||||
#define DC_SETUP_FRAME_ADDRESSES (16 - 2)
|
||||
|
||||
/* Computed hash of FF:FF:FF:FF:FF:FF */
|
||||
#define DC_SETUP_FRAME_BROADCAST_HASH 0xFF
|
||||
|
||||
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#define DC_SETUP_FRAME_ENTRY(Value) (Value)
|
||||
#else
|
||||
#define DC_SETUP_FRAME_ENTRY(Value) ((Value) << 16)
|
||||
#endif
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
/*
|
||||
* Transmit Buffer Descriptor
|
||||
*/
|
||||
typedef struct _DC_TBD
|
||||
{
|
||||
ULONG Status;
|
||||
#define DC_TBD_STATUS_DEFFERED 0x00000001
|
||||
#define DC_TBD_STATUS_UNDERFLOW 0x00000002
|
||||
#define DC_TBD_STATUS_LINK_FAIL 0x00000004
|
||||
#define DC_TBD_STATUS_COLLISIONS_MASK 0x00000078
|
||||
#define DC_TBD_STATUS_HEARTBEAT_FAIL 0x00000080
|
||||
#define DC_TBD_STATUS_RETRY_ERROR 0x00000100
|
||||
#define DC_TBD_STATUS_LATE_COLLISION 0x00000200
|
||||
#define DC_TBD_STATUS_NO_CARRIER 0x00000400
|
||||
#define DC_TBD_STATUS_CARRIER_LOST 0x00000800
|
||||
#define DC_TBD_STATUS_JABBER_TIMEOUT 0x00004000
|
||||
#define DC_TBD_STATUS_ERROR_SUMMARY 0x00008000
|
||||
#define DC_TBD_STATUS_OWNED 0x80000000
|
||||
|
||||
#define DC_TBD_STATUS_SETUP_FRAME 0x7FFFFFFF
|
||||
|
||||
#define DC_TBD_STATUS_COLLISIONS_SHIFT 3
|
||||
|
||||
ULONG Control;
|
||||
#define DC_TBD_CONTROL_LENGTH_MASK_1 0x000007FF
|
||||
#define DC_TBD_CONTROL_LENGTH_MASK_2 0x003FF800
|
||||
#define DC_TBD_CONTROL_NO_PAD 0x00800000
|
||||
#define DC_TBD_CONTROL_CHAINED 0x01000000
|
||||
#define DC_TBD_CONTROL_END_OF_RING 0x02000000
|
||||
#define DC_TBD_CONTROL_NO_CRC 0x04000000
|
||||
#define DC_TBD_CONTROL_SETUP_FRAME 0x08000000
|
||||
#define DC_TBD_CONTROL_FIRST_FRAGMENT 0x20000000
|
||||
#define DC_TBD_CONTROL_LAST_FRAGMENT 0x40000000
|
||||
#define DC_TBD_CONTROL_REQUEST_INTERRUPT 0x80000000
|
||||
#define DC_TBD_CONTROL_PERFECT_FILTER 0x00000000
|
||||
#define DC_TBD_CONTROL_HASH_PERFECT_FILTER 0x00400000
|
||||
#define DC_TBD_CONTROL_INVERSE_FILTER 0x10000000
|
||||
#define DC_TBD_CONTROL_IMPERFECT_FILTER 0x10400000
|
||||
|
||||
#define DC_TBD_CONTROL_LENGTH_2_SHIFT 11
|
||||
|
||||
ULONG Address1;
|
||||
ULONG Address2;
|
||||
} DC_TBD, *PDC_TBD;
|
||||
|
||||
C_ASSERT(sizeof(DC_TBD) == 16);
|
||||
|
||||
/*
|
||||
* Receive Buffer Descriptor
|
||||
*/
|
||||
typedef struct _DC_RBD
|
||||
{
|
||||
ULONG Status;
|
||||
#define DC_RBD_STATUS_OVERRUN 0x00000001
|
||||
#define DC_RBD_STATUS_CRC_ERROR 0x00000002
|
||||
#define DC_RBD_STATUS_DRIBBLE 0x00000004
|
||||
#define DC_RBD_STATUS_MII_ERROR 0x00000008
|
||||
#define DC_RBD_STATUS_WDT_EXPIRED 0x00000010
|
||||
#define DC_RBD_STATUS_FRAME_TYPE 0x00000020
|
||||
#define DC_RBD_STATUS_COLLISION_SEEN 0x00000040
|
||||
#define DC_RBD_STATUS_TOO_LONG 0x00000080
|
||||
#define DC_RBD_STATUS_LAST_DESCRIPTOR 0x00000100
|
||||
#define DC_RBD_STATUS_FIRST_DESCRIPTOR 0x00000200
|
||||
#define DC_RBD_STATUS_MULTICAST 0x00000400
|
||||
#define DC_RBD_STATUS_RUNT 0x00000800
|
||||
#define DC_RBD_STATUS_DATA_TYPE_MASK 0x00003000
|
||||
#define DC_RBD_STATUS_LENGTH_ERROR 0x00004000
|
||||
#define DC_RBD_STATUS_ERROR_SUMMARY 0x00008000
|
||||
#define DC_RBD_STATUS_FRAME_LENGTH_MASK 0x3FFF0000
|
||||
#define DC_RBD_STATUS_FILTERING_FAIL 0x40000000
|
||||
#define DC_RBD_STATUS_OWNED 0x80000000
|
||||
|
||||
#define DC_RBD_STATUS_FRAME_LENGTH_SHIFT 16
|
||||
|
||||
ULONG Control;
|
||||
#define DC_RBD_CONTROL_BUFFER_LENGTH_MASK_1 0x000007FF
|
||||
#define DC_RBD_CONTROL_BUFFER_LENGTH_MASK_2 0x003FF800
|
||||
#define DC_RBD_CONTROL_CHAINED 0x01000000
|
||||
#define DC_RBD_CONTROL_END_OF_RING 0x02000000
|
||||
|
||||
ULONG Address1;
|
||||
ULONG Address2;
|
||||
} DC_RBD, *PDC_RBD;
|
||||
|
||||
C_ASSERT(sizeof(DC_RBD) == 16);
|
||||
|
||||
#define DC_PATTERN_FILTERS 4
|
||||
|
||||
/*
|
||||
* Wake-Up Filter Register Block
|
||||
*/
|
||||
typedef union _DC_PATTERN_FILTER_BLOCK
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG Mask[DC_PATTERN_FILTERS];
|
||||
|
||||
UCHAR Command[DC_PATTERN_FILTERS];
|
||||
#define DC_PATTERN_FILTER_CMD_ENABLE 0x01
|
||||
#define DC_PATTERN_FILTER_CMD_INVERSE_MODE 0x02
|
||||
#define DC_PATTERN_FILTER_CMD_ADD_PREV 0x04
|
||||
#define DC_PATTERN_FILTER_CMD_MULTICAST 0x08
|
||||
|
||||
UCHAR Offset[DC_PATTERN_FILTERS];
|
||||
USHORT Crc[DC_PATTERN_FILTERS];
|
||||
};
|
||||
ULONG AsULONG[8];
|
||||
} DC_PATTERN_FILTER_BLOCK, *PDC_PATTERN_FILTER_BLOCK;
|
||||
|
||||
C_ASSERT(sizeof(DC_PATTERN_FILTER_BLOCK) == 32);
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
/*
|
||||
* NIC Control and Status Registers
|
||||
*/
|
||||
typedef enum _DC_CSR
|
||||
{
|
||||
DcCsr0_BusMode = 0x00,
|
||||
DcCsr1_TxPoll = 0x08,
|
||||
DcCsr1_WakeUpFilter = 0x08,
|
||||
DcCsr2_RxPoll = 0x10,
|
||||
DcCsr2_WakeUpControl = 0x10,
|
||||
DcCsr3_RxRingAddress = 0x18,
|
||||
DcCsr4_TxRingAddress = 0x20,
|
||||
DcCsr5_Status = 0x28,
|
||||
DcCsr6_OpMode = 0x30,
|
||||
DcCsr7_IrqMask = 0x38,
|
||||
DcCsr8_RxCounters = 0x40,
|
||||
DcCsr9_SerialInterface = 0x48,
|
||||
DcCsr10_BootRom = 0x50,
|
||||
DcCsr11_FullDuplex = 0x58,
|
||||
DcCsr11_Timer = 0x58,
|
||||
DcCsr12_Gpio = 0x60,
|
||||
DcCsr12_SiaStatus = 0x60,
|
||||
DcCsr13_SiaConnectivity = 0x68,
|
||||
DcCsr14_SiaTxRx = 0x70,
|
||||
DcCsr15_SiaGeneral = 0x78,
|
||||
} DC_CSR;
|
||||
|
||||
/*
|
||||
* CSR0 Bus Mode
|
||||
*/
|
||||
#define DC_BUS_MODE_SOFT_RESET 0x00000001
|
||||
#define DC_BUS_MODE_BUS_ARB 0x00000002
|
||||
#define DC_BUS_MODE_DESC_SKIP_LENGTH_MASK 0x0000007C
|
||||
#define DC_BUS_MODE_BUFFERS_BIG_ENDIAN 0x00000080
|
||||
#define DC_BUS_MODE_BURST_LENGTH_MASK 0x00003F00
|
||||
#define DC_BUS_MODE_CACHE_ALIGNMENT_MASK 0x0000C000
|
||||
#define DC_BUS_MODE_DIAGNOSTIC_ADDRESS_SPACE 0x00010000
|
||||
#define DC_BUS_MODE_TX_POLL_MASK 0x000E0000
|
||||
#define DC_BUS_MODE_DESC_BIG_ENDIAN 0x00100000
|
||||
#define DC_BUS_MODE_READ_MULTIPLE 0x00200000
|
||||
#define DC_BUS_MODE_READ_LINE 0x00800000
|
||||
#define DC_BUS_MODE_WRITE_INVALIDATE 0x01000000
|
||||
#define DC_BUS_MODE_ON_NOW_UNLOCK 0x04000000
|
||||
|
||||
#define DC_BUS_MODE_BURST_LENGTH_NO_LIMIT 0x00000000
|
||||
#define DC_BUS_MODE_BURST_LENGTH_1 0x00000100
|
||||
#define DC_BUS_MODE_BURST_LENGTH_2 0x00000200
|
||||
#define DC_BUS_MODE_BURST_LENGTH_4 0x00000400
|
||||
#define DC_BUS_MODE_BURST_LENGTH_8 0x00000800
|
||||
#define DC_BUS_MODE_BURST_LENGTH_16 0x00001000
|
||||
#define DC_BUS_MODE_BURST_LENGTH_32 0x00002000
|
||||
|
||||
#define DC_BUS_MODE_CACHE_ALIGNMENT_NONE 0x00000000
|
||||
#define DC_BUS_MODE_CACHE_ALIGNMENT_8 0x00004000
|
||||
#define DC_BUS_MODE_CACHE_ALIGNMENT_16 0x00008000
|
||||
#define DC_BUS_MODE_CACHE_ALIGNMENT_32 0x0000C000
|
||||
|
||||
#define DC_BUS_MODE_TX_POLL_DISABLED 0x00000000
|
||||
#define DC_BUS_MODE_TX_POLL_1 0x00020000
|
||||
#define DC_BUS_MODE_TX_POLL_2 0x00040000
|
||||
#define DC_BUS_MODE_TX_POLL_3 0x00060000
|
||||
#define DC_BUS_MODE_TX_POLL_4 0x00080000
|
||||
#define DC_BUS_MODE_TX_POLL_5 0x000A0000
|
||||
#define DC_BUS_MODE_TX_POLL_6 0x000C0000
|
||||
#define DC_BUS_MODE_TX_POLL_7 0x000E0000
|
||||
|
||||
#define DC_BUS_MODE_DESC_SKIP_LENGTH_0 0x00000000
|
||||
#define DC_BUS_MODE_DESC_SKIP_LENGTH_1 0x00000004
|
||||
#define DC_BUS_MODE_DESC_SKIP_LENGTH_2 0x00000008
|
||||
#define DC_BUS_MODE_DESC_SKIP_LENGTH_4 0x00000010
|
||||
#define DC_BUS_MODE_DESC_SKIP_LENGTH_8 0x00000020
|
||||
#define DC_BUS_MODE_DESC_SKIP_LENGTH_16 0x00000040
|
||||
#define DC_BUS_MODE_DESC_SKIP_LENGTH_32 0x00000080
|
||||
|
||||
/*
|
||||
* CSR1 Transmit Poll Demand
|
||||
*/
|
||||
#define DC_TX_POLL_DOORBELL 0x00000001
|
||||
|
||||
/*
|
||||
* CSR2 Receive Poll Demand
|
||||
*/
|
||||
#define DC_RX_POLL_DOORBELL 0x00000001
|
||||
|
||||
/*
|
||||
* CSR2 Wake Up Control
|
||||
*/
|
||||
#define DC_WAKE_UP_CONTROL_LINK_CHANGE 0x00000001
|
||||
#define DC_WAKE_UP_CONTROL_MAGIC_PACKET 0x00000002
|
||||
#define DC_WAKE_UP_CONTROL_PATTERN_MATCH 0x00000004
|
||||
#define DC_WAKE_UP_STATUS_LINK_CHANGE 0x00000010
|
||||
#define DC_WAKE_UP_STATUS_MAGIC_PACKET 0x00000020
|
||||
#define DC_WAKE_UP_STATUS_PATTERN_MATCH 0x00000040
|
||||
#define DC_WAKE_UP_CONTROL_GLOBAL_UNICAST 0x00000200
|
||||
#define DC_WAKE_UP_CONTROL_VLAN_ENABLE 0x00000800
|
||||
#define DC_WAKE_UP_CONTROL_VLAN_TYPE_MASK 0xFFFF0000
|
||||
|
||||
/*
|
||||
* CSR5 Status, CSR7 Irq Mask
|
||||
*/
|
||||
#define DC_IRQ_TX_OK 0x00000001
|
||||
#define DC_IRQ_TX_STOPPED 0x00000002
|
||||
#define DC_IRQ_TX_NO_BUFFER 0x00000004
|
||||
#define DC_IRQ_TX_JABBER_TIMEOUT 0x00000008
|
||||
#define DC_IRQ_LINK_PASS 0x00000010
|
||||
#define DC_IRQ_TX_UNDERFLOW 0x00000020
|
||||
#define DC_IRQ_RX_OK 0x00000040
|
||||
#define DC_IRQ_RX_NO_BUFFER 0x00000080
|
||||
#define DC_IRQ_RX_STOPPED 0x00000100
|
||||
#define DC_IRQ_RX_WDT_TIMEOUT 0x00000200
|
||||
#define DC_IRQ_AUI 0x00000400
|
||||
#define DC_IRQ_TX_EARLY 0x00000400
|
||||
#define DC_IRQ_FD_FRAME_RECEIVED 0x00000800
|
||||
#define DC_IRQ_TIMER_TIMEOUT 0x00000800
|
||||
#define DC_IRQ_LINK_FAIL 0x00001000
|
||||
#define DC_IRQ_SYSTEM_ERROR 0x00002000
|
||||
#define DC_IRQ_RX_EARLY 0x00004000
|
||||
#define DC_IRQ_ABNORMAL_SUMMARY 0x00008000
|
||||
#define DC_IRQ_NORMAL_SUMMARY 0x00010000
|
||||
#define DC_STATUS_RX_STATE_MASK 0x000E0000
|
||||
#define DC_STATUS_TX_STATE_MASK 0x00700000
|
||||
#define DC_STATUS_SYSTEM_ERROR_MASK 0x03800000
|
||||
#define DC_IRQ_GPIO_PORT 0x04000000
|
||||
#define DC_IRQ_LINK_CHANGED 0x08000000
|
||||
#define DC_IRQ_HPNA_PHY 0x10000000
|
||||
|
||||
#define DC_STATUS_TX_STATE_STOPPED 0x00000000
|
||||
#define DC_STATUS_TX_STATE_FETCH 0x00100000
|
||||
#define DC_STATUS_TX_STATE_WAIT_FOR_END 0x00200000
|
||||
#define DC_STATUS_TX_STATE_READ 0x00300000
|
||||
#define DC_STATUS_TX_STATE_RESERVED 0x00400000
|
||||
#define DC_STATUS_TX_STATE_SETUP_PACKET 0x00500000
|
||||
#define DC_STATUS_TX_STATE_SUSPENDED 0x00600000
|
||||
#define DC_STATUS_TX_STATE_CLOSE 0x00700000
|
||||
|
||||
#define DC_STATUS_RX_STATE_STOPPED 0x00000000
|
||||
#define DC_STATUS_RX_STATE_FETCH 0x00020000
|
||||
#define DC_STATUS_RX_STATE_CHECK_END 0x00040000
|
||||
#define DC_STATUS_RX_STATE_WAIT_FOR_RCV 0x00060000
|
||||
#define DC_STATUS_RX_STATE_SUSPENDED 0x00080000
|
||||
#define DC_STATUS_RX_STATE_CLOSE_DESC 0x000A0000
|
||||
#define DC_STATUS_RX_STATE_FLUSH 0x000C0000
|
||||
#define DC_STATUS_RX_STATE_DEQUEUE 0x000E0000
|
||||
|
||||
#define DC_STATUS_SYSTEM_ERROR_PARITY 0x00000000
|
||||
#define DC_STATUS_SYSTEM_ERROR_MASTER_ABORT 0x00800000
|
||||
#define DC_STATUS_SYSTEM_ERROR_TARGET_ABORT 0x01000000
|
||||
|
||||
/*
|
||||
* CSR6 Operation Mode
|
||||
*/
|
||||
#define DC_OPMODE_RX_HASH_PERFECT_FILT 0x00000001
|
||||
#define DC_OPMODE_RX_ENABLE 0x00000002
|
||||
#define DC_OPMODE_RX_HASH_ONLY_FILT 0x00000004
|
||||
#define DC_OPMODE_RX_RUNTS 0x00000008
|
||||
#define DC_OPMODE_RX_INVERSE_FILT 0x00000010
|
||||
#define DC_OPMODE_BACKOFF_COUNTER 0x00000020
|
||||
#define DC_OPMODE_RX_PROMISCUOUS 0x00000040
|
||||
#define DC_OPMODE_RX_ALL_MULTICAST 0x00000080
|
||||
#define DC_OPMODE_FKD 0x00000100
|
||||
#define DC_OPMODE_FULL_DUPLEX 0x00000200
|
||||
#define DC_OPMODE_LOOPBACK_MASK 0x00000C00
|
||||
#define DC_OPMODE_FORCE_COLLISIONS 0x00001000
|
||||
#define DC_OPMODE_TX_ENABLE 0x00002000
|
||||
#define DC_OPMODE_TX_THRESHOLD_CTRL_MASK 0x0000C000
|
||||
#define DC_OPMODE_TX_BACK_PRESSURE 0x00010000
|
||||
#define DC_OPMODE_TX_CAPTURE_EFFECT 0x00020000
|
||||
#define DC_OPMODE_PORT_SELECT 0x00040000
|
||||
#define DC_OPMODE_PORT_HEARTBEAT_DISABLE 0x00080000
|
||||
#define DC_OPMODE_STORE_AND_FORWARD 0x00200000
|
||||
#define DC_OPMODE_PORT_XMIT_10 0x00400000
|
||||
#define DC_OPMODE_PORT_PCS 0x00800000
|
||||
#define DC_OPMODE_PORT_SCRAMBLER 0x01000000
|
||||
#define DC_OPMODE_PORT_ALWAYS 0x02000000
|
||||
#define DC_OPMODE_ADDR_LSB_IGNORE 0x04000000
|
||||
#define DC_OPMODE_RX_RECEIVE_ALL 0x40000000
|
||||
#define DC_OPMODE_TX_SPECIAL_CAPTURE_EFFECT 0x80000000
|
||||
|
||||
#define DC_OPMODE_LOOPBACK_NORMAL 0x00000000
|
||||
#define DC_OPMODE_LOOPBACK_INTERNAL 0x00000400
|
||||
#define DC_OPMODE_LOOPBACK_EXTERNAL 0x00000800
|
||||
|
||||
#define DC_OPMODE_TX_THRESHOLD_LEVEL 0x00004000
|
||||
#define DC_OPMODE_TX_THRESHOLD_MAX 0x0000C000
|
||||
|
||||
#define DC_OPMODE_MEDIA_MASK ( \
|
||||
DC_OPMODE_TX_THRESHOLD_CTRL_MASK | \
|
||||
DC_OPMODE_LOOPBACK_MASK | \
|
||||
DC_OPMODE_FULL_DUPLEX | \
|
||||
DC_OPMODE_PORT_SELECT | \
|
||||
DC_OPMODE_PORT_HEARTBEAT_DISABLE | \
|
||||
DC_OPMODE_PORT_XMIT_10 | \
|
||||
DC_OPMODE_PORT_PCS | \
|
||||
DC_OPMODE_PORT_SCRAMBLER)
|
||||
|
||||
/*
|
||||
* CSR8 Receive Counters
|
||||
*/
|
||||
#define DC_COUNTER_RX_NO_BUFFER_MASK 0x0001FFFF
|
||||
#define DC_COUNTER_RX_OVERFLOW_MASK 0x1FFE0000
|
||||
|
||||
#define DC_COUNTER_RX_OVERFLOW_SHIFT 17
|
||||
|
||||
/*
|
||||
* CSR9 Serial Interface
|
||||
*/
|
||||
#define DC_SERIAL_EE_CS 0x00000001
|
||||
#define DC_SERIAL_EE_SK 0x00000002
|
||||
#define DC_SERIAL_EE_DI 0x00000004
|
||||
#define DC_SERIAL_EE_DO 0x00000008
|
||||
#define DC_SERIAL_EE_REG 0x00000400
|
||||
#define DC_SERIAL_EE_SR 0x00000800
|
||||
#define DC_SERIAL_EE_WR 0x00002000
|
||||
#define DC_SERIAL_EE_RD 0x00004000
|
||||
#define DC_SERIAL_EE_MOD 0x00008000
|
||||
#define DC_SERIAL_MII_MDC 0x00010000
|
||||
#define DC_SERIAL_MII_MDO 0x00020000
|
||||
#define DC_SERIAL_MII_MII 0x00040000
|
||||
#define DC_SERIAL_MII_MDI 0x00080000
|
||||
#define DC_SERIAL_EAR_DN 0x80000000
|
||||
#define DC_SERIAL_EAR_DT 0x000000FF
|
||||
#define DC_SERIAL_SPI_CS 0x00100000
|
||||
#define DC_SERIAL_SPI_SK 0x00200000
|
||||
#define DC_SERIAL_SPI_DI 0x00400000
|
||||
#define DC_SERIAL_SPI_DO 0x00800000
|
||||
|
||||
#define DC_SERIAL_EE_DI_SHIFT 2
|
||||
#define DC_SERIAL_EE_DO_SHIFT 3
|
||||
#define DC_SERIAL_MII_MDO_SHIFT 17
|
||||
#define DC_SERIAL_MII_MDI_SHIFT 19
|
||||
#define DC_SERIAL_SPI_DI_SHIFT 22
|
||||
#define DC_SERIAL_SPI_DO_SHIFT 23
|
||||
|
||||
/*
|
||||
* CSR11 Timer
|
||||
*/
|
||||
#define DC_TIMER_VALUE_MASK 0x0000FFFF
|
||||
#define DC_TIMER_CONTINUOUS 0x00010000
|
||||
#define DC_TIMER_RX_NUMBER_MASK 0x000E0000
|
||||
#define DC_TIMER_RX_TIMER_MASK 0x00F00000
|
||||
#define DC_TIMER_TX_NUMBER_MASK 0x07000000
|
||||
#define DC_TIMER_TX_TIMER_MASK 0x78000000
|
||||
#define DC_TIMER_CYCLE_SIZE 0x80000000
|
||||
|
||||
#define DC_TIMER_RX_NUMBER_SHIFT 17
|
||||
#define DC_TIMER_RX_TIMER_SHIFT 20
|
||||
#define DC_TIMER_TX_NUMBER_SHIFT 24
|
||||
#define DC_TIMER_TX_TIMER_SHIFT 27
|
||||
|
||||
/*
|
||||
* CSR12 SIA Status
|
||||
*/
|
||||
#define DC_SIA_STATUS_MII_RECEIVE_ACTIVITY 0x00000001
|
||||
#define DC_SIA_STATUS_NETWORK_CONNECTION_ERROR 0x00000002
|
||||
#define DC_SIA_STATUS_100T_LINK_FAIL 0x00000002
|
||||
#define DC_SIA_STATUS_10T_LINK_FAIL 0x00000004
|
||||
#define DC_SIA_STATUS_SELECTED_PORT_ACTIVITY 0x00000100
|
||||
#define DC_SIA_STATUS_AUI_ACTIVITY 0x00000100
|
||||
#define DC_SIA_STATUS_HPNA_ACTIVITY 0x00000100
|
||||
#define DC_SIA_STATUS_NONSEL_PORT_ACTIVITY 0x00000200
|
||||
#define DC_SIA_STATUS_10T_ACTIVITY 0x00000200
|
||||
#define DC_SIA_STATUS_NSN 0x00000400
|
||||
#define DC_SIA_STATUS_TX_REMOTE_FAULT 0x00000800
|
||||
#define DC_SIA_STATUS_ANS_MASK 0x00007000
|
||||
#define DC_SIA_STATUS_LP_AUTONED_SUPPORTED 0x00008000
|
||||
#define DC_SIA_STATUS_LP_CODE_WORD_MASK 0xFFFF0000
|
||||
|
||||
#define DC_SIA_STATUS_ANS_AUTONEG_DISABLED 0x00000000
|
||||
#define DC_SIA_STATUS_ANS_TX_DISABLE 0x00001000
|
||||
#define DC_SIA_STATUS_ANS_ABILITY_DETECT 0x00002000
|
||||
#define DC_SIA_STATUS_ANS_ACK_DETECT 0x00003000
|
||||
#define DC_SIA_STATUS_ANS_ACK_COMPLETE 0x00004000
|
||||
#define DC_SIA_STATUS_ANS_AUTONEG_COMPLETE 0x00005000
|
||||
#define DC_SIA_STATUS_ANS_LINK_CHECK 0x00006000
|
||||
|
||||
#define DC_SIA_STATUS_LP_CODE_WORD_SHIFT 16
|
||||
|
||||
#define DC_GPIO_CONTROL 0x100
|
||||
|
||||
/*
|
||||
* CSR13 SIA Connectivity
|
||||
*/
|
||||
#define DC_SIA_CONN_RESET 0x00000000
|
||||
#define DC_SIA_CONN_HPNA 0x00000008
|
||||
|
||||
/*
|
||||
* CSR14 SIA Transmit and Receive
|
||||
*/
|
||||
#define DC_SIA_TXRX_ENCODER 0x00000001
|
||||
#define DC_SIA_TXRX_LOOPBACK 0x00000002
|
||||
#define DC_SIA_TXRX_DRIVER 0x00000004
|
||||
#define DC_SIA_TXRX_LINK_PULSE 0x00000008
|
||||
#define DC_SIA_TXRX_COMPENSATION 0x00000030
|
||||
#define DC_SIA_TXRX_ADV_10T_HD 0x00000040
|
||||
#define DC_SIA_TXRX_AUTONEG 0x00000080
|
||||
#define DC_SIA_TXRX_RX_SQUELCH 0x00000100
|
||||
#define DC_SIA_TXRX_COLLISION_SQUELCH 0x00000200
|
||||
#define DC_SIA_TXRX_COLLISION_DETECT 0x00000400
|
||||
#define DC_SIA_TXRX_HEARTBEAT 0x00000800
|
||||
#define DC_SIA_TXRX_LINK_TEST 0x00001000
|
||||
#define DC_SIA_TXRX_AUTOPOLARITY 0x00002000
|
||||
#define DC_SIA_TXRX_SET_POLARITY_PLUS 0x00004000
|
||||
#define DC_SIA_TXRX_10T_AUTOSENSE 0x00008000
|
||||
#define DC_SIA_TXRX_ADV_100TX_HD 0x00010000
|
||||
#define DC_SIA_TXRX_ADV_100TX_FD 0x00020000
|
||||
#define DC_SIA_TXRX_ADV_100T4 0x00040000
|
||||
|
||||
/*
|
||||
* CSR15 SIA and GPIO
|
||||
*/
|
||||
#define DC_SIA_GENERAL_JABBER_DISABLE 0x00000001
|
||||
#define DC_SIA_GENERAL_HOST_UNJAB 0x00000002
|
||||
#define DC_SIA_GENERAL_JABBER_CLOCK 0x00000004
|
||||
#define DC_SIA_GENERAL_AUI_BNC_MODE 0x00000008
|
||||
#define DC_SIA_GENERAL_RX_WDT_DISABLE 0x00000010
|
||||
#define DC_SIA_GENERAL_RX_WDT_RELEASE 0x00000020
|
||||
#define DC_SIA_GENERAL_LINK_EXTEND 0x00000800
|
||||
#define DC_SIA_GENERAL_RX_MAGIC_PACKET 0x00004000
|
||||
#define DC_SIA_GENERAL_HCKR 0x00008000
|
||||
#define DC_SIA_GENERAL_GPIO_MASK 0x000F0000
|
||||
#define DC_SIA_GENERAL_LGS3 0x00100000
|
||||
#define DC_SIA_GENERAL_LGS2 0x00200000
|
||||
#define DC_SIA_GENERAL_LGS1 0x00400000
|
||||
#define DC_SIA_GENERAL_LGS0 0x00800000
|
||||
#define DC_SIA_GENERAL_GEI0 0x01000000
|
||||
#define DC_SIA_GENERAL_GEI1 0x02000000
|
||||
#define DC_SIA_GENERAL_RECEIVE_MATCH 0x04000000
|
||||
#define DC_SIA_GENERAL_CONTROL_WRITE 0x08000000
|
||||
#define DC_SIA_GENERAL_GI0 0x10000000
|
||||
#define DC_SIA_GENERAL_GI1 0x20000000
|
||||
#define DC_SIA_GENERAL_IRQ_RX_MATCH 0x40000000
|
||||
|
||||
#define DC_RBD_STATUS_INVALID \
|
||||
(DC_RBD_STATUS_OVERRUN | \
|
||||
DC_RBD_STATUS_CRC_ERROR | \
|
||||
DC_RBD_STATUS_WDT_EXPIRED | \
|
||||
DC_RBD_STATUS_COLLISION_SEEN | \
|
||||
DC_RBD_STATUS_TOO_LONG | \
|
||||
DC_RBD_STATUS_RUNT | \
|
||||
DC_RBD_STATUS_LENGTH_ERROR)
|
||||
|
||||
#define DC_GENERIC_IRQ_MASK \
|
||||
(DC_IRQ_TX_OK | DC_IRQ_TX_STOPPED | DC_IRQ_TX_JABBER_TIMEOUT | \
|
||||
DC_IRQ_RX_OK | DC_IRQ_TX_UNDERFLOW | \
|
||||
DC_IRQ_RX_STOPPED | \
|
||||
DC_IRQ_SYSTEM_ERROR | DC_IRQ_ABNORMAL_SUMMARY | DC_IRQ_NORMAL_SUMMARY)
|
||||
|
||||
/* Errata: The programming guide incorrectly stated that CSR13 must be set to 0x30480009 */
|
||||
#define DC_HPNA_ANALOG_CTRL 0x708A0000
|
||||
|
||||
/*
|
||||
* PCI Configuration Registers
|
||||
*/
|
||||
#define DC_PCI_DEVICE_CONFIG 0x40
|
||||
#define DC_PCI_DEVICE_CONFIG_SNOOZE 0x40000000
|
||||
#define DC_PCI_DEVICE_CONFIG_SLEEP 0x80000000
|
||||
|
||||
/*
|
||||
* SPI Interface
|
||||
*/
|
||||
#define DC_SPI_BYTE_WRITE_OPERATION 2
|
||||
#define DC_SPI_BYTE_READ_OPERATION 3
|
||||
#define DC_SPI_CLEAR_WRITE_ENABLE 4
|
||||
#define DC_SPI_SET_WRITE_ENABLE 6
|
||||
|
||||
/*
|
||||
* HomePNA PHY Registers
|
||||
*/
|
||||
#define HPNA_CONTROL_LOW 0x00
|
||||
#define HPNA_CONTROL_HIGH 0x01
|
||||
#define HPNA_NOISE 0x10
|
||||
#define HPNA_NOISE_FLOOR 0x12
|
||||
#define HPNA_NOISE_CEILING 0x13
|
||||
#define HPNA_NOISE_ATTACK 0x14
|
||||
|
||||
/*
|
||||
* MDIO Protocol (IEEE 802.3)
|
||||
*/
|
||||
#define MDIO_START 0x01
|
||||
#define MDIO_WRITE 0x01
|
||||
#define MDIO_READ 0x02
|
||||
#define MDIO_TA 0x02
|
||||
#define MDIO_PREAMBLE 0xFFFFFFFF
|
||||
|
||||
#define MII_MAX_PHY_ADDRESSES 32
|
||||
|
||||
/*
|
||||
* PHY register definitions (IEEE 802.3)
|
||||
*/
|
||||
#define MII_CONTROL 0x00
|
||||
#define MII_CR_COLLISION_TEST 0x0080
|
||||
#define MII_CR_FULL_DUPLEX 0x0100
|
||||
#define MII_CR_AUTONEG_RESTART 0x0200
|
||||
#define MII_CR_ISOLATE 0x0400
|
||||
#define MII_CR_POWER_DOWN 0x0800
|
||||
#define MII_CR_AUTONEG 0x1000
|
||||
#define MII_CR_SPEED_SELECTION 0x2000
|
||||
#define MII_CR_LOOPBACK 0x4000
|
||||
#define MII_CR_RESET 0x8000
|
||||
#define MII_STATUS 0x01
|
||||
#define MII_SR_LINK_STATUS 0x0004
|
||||
#define MII_SR_AUTONEG_COMPLETE 0x0020
|
||||
#define MII_PHY_ID1 0x02
|
||||
#define MII_PHY_ID2 0x03
|
||||
#define MII_AUTONEG_ADVERTISE 0x04
|
||||
#define MII_ADV_CSMA 0x0001
|
||||
#define MII_ADV_10T_HD 0x0020
|
||||
#define MII_ADV_10T_FD 0x0040
|
||||
#define MII_ADV_100T_HD 0x0080
|
||||
#define MII_ADV_100T_FD 0x0100
|
||||
#define MII_ADV_100T4 0x0200
|
||||
#define MII_ADV_PAUSE_SYM 0x0400
|
||||
#define MII_ADV_PAUSE_ASYM 0x0800
|
||||
#define MII_AUTONEG_LINK_PARTNER 0x05
|
||||
#define MII_LP_10T_HD 0x0020
|
||||
#define MII_LP_10T_FD 0x0040
|
||||
#define MII_LP_100T_HD 0x0080
|
||||
#define MII_LP_100T_FD 0x0100
|
||||
#define MII_LP_100T4 0x0200
|
||||
#define MII_LP_PAUSE_SYM 0x0400
|
||||
#define MII_LP_PAUSE_ASYM 0x0800
|
||||
#define MII_AUTONEG_EXPANSION 0x06
|
||||
#define MII_EXP_LP_AUTONEG 0x0001
|
||||
#define MII_MASTER_SLAVE_CONTROL 0x09
|
||||
#define MII_MS_CR_1000T_HD 0x0100
|
||||
#define MII_MS_CR_1000T_FD 0x0200
|
||||
#define MII_MASTER_SLAVE_STATUS 0x0A
|
||||
#define MII_MS_SR_1000T_FD 0x0800
|
||||
|
||||
#define MII_ADV_100 \
|
||||
(MII_ADV_100T_HD | MII_ADV_100T_FD | MII_ADV_100T4)
|
70
drivers/network/dd/dc21x4/debug.c
Normal file
70
drivers/network/dd/dc21x4/debug.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Debug routines
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
static PCSTR MediaName[MEDIA_MAX] =
|
||||
{
|
||||
"10Base-T",
|
||||
"10Base-2 (BNC)",
|
||||
"10Base-5 (AUI)",
|
||||
"100Base-TX HD",
|
||||
"10Base-T FD",
|
||||
"100Base-TX FD",
|
||||
"100Base-T4",
|
||||
"100Base-FX HD",
|
||||
"100Base-FX FD",
|
||||
"HomePNA",
|
||||
"MII",
|
||||
};
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
PCSTR
|
||||
MediaNumber2Str(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG MediaNumber)
|
||||
{
|
||||
switch (MediaNumber)
|
||||
{
|
||||
case MEDIA_100TX_HD:
|
||||
{
|
||||
if (Adapter->ChipType == DC21041)
|
||||
return "10Base-T HD";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(MediaNumber < MEDIA_MAX);
|
||||
|
||||
return MediaName[MediaNumber];
|
||||
}
|
||||
|
||||
PCSTR
|
||||
DcDbgBusError(
|
||||
_In_ ULONG InterruptStatus)
|
||||
{
|
||||
switch (InterruptStatus & DC_STATUS_SYSTEM_ERROR_MASK)
|
||||
{
|
||||
case DC_STATUS_SYSTEM_ERROR_PARITY:
|
||||
return "Parity Error";
|
||||
case DC_STATUS_SYSTEM_ERROR_MASTER_ABORT:
|
||||
return "Master Abort";
|
||||
case DC_STATUS_SYSTEM_ERROR_TARGET_ABORT:
|
||||
return "Target Abort";
|
||||
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
96
drivers/network/dd/dc21x4/debug.h
Normal file
96
drivers/network/dd/dc21x4/debug.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Debug support header file
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __RELFILE__
|
||||
#define __RELFILE__ __FILE__
|
||||
#endif
|
||||
|
||||
#if DBG
|
||||
|
||||
// #define DEBUG_TRACE
|
||||
// #define DEBUG_INFO
|
||||
#define DEBUG_INFO_VERB
|
||||
#define DEBUG_WARN
|
||||
#define DEBUG_ERR
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
#define TRACE(fmt, ...) \
|
||||
do { \
|
||||
if (DbgPrint("(%s:%d) %s " fmt, __RELFILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)) \
|
||||
DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define TRACE
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_INFO
|
||||
#define INFO(fmt, ...) \
|
||||
do { \
|
||||
if (DbgPrint("(%s:%d) %s " fmt, __RELFILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)) \
|
||||
DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define INFO
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_INFO_VERB
|
||||
#define INFO_VERB(fmt, ...) \
|
||||
do { \
|
||||
if (DbgPrint("(%s:%d) %s " fmt, __RELFILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)) \
|
||||
DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define INFO_VERB
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_WARN
|
||||
#define WARN(fmt, ...) \
|
||||
do { \
|
||||
if (DbgPrint("(%s:%d) %s " fmt, __RELFILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)) \
|
||||
DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define WARN
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ERR
|
||||
#define ERR(fmt, ...) \
|
||||
do { \
|
||||
if (DbgPrint("(%s:%d) %s " fmt, __RELFILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)) \
|
||||
DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define ERR
|
||||
#endif
|
||||
|
||||
PCSTR
|
||||
MediaNumber2Str(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG MediaNumber);
|
||||
|
||||
PCSTR
|
||||
DcDbgBusError(
|
||||
_In_ ULONG InterruptStatus);
|
||||
|
||||
#else
|
||||
|
||||
#define TRACE
|
||||
#define INFO
|
||||
#define INFO_VERB
|
||||
#define WARN
|
||||
#define ERR
|
||||
#define MediaNumber2Str
|
||||
#define DcDbgBusError
|
||||
|
||||
#endif
|
1525
drivers/network/dd/dc21x4/eeprom.c
Normal file
1525
drivers/network/dd/dc21x4/eeprom.c
Normal file
File diff suppressed because it is too large
Load diff
108
drivers/network/dd/dc21x4/eeprom.h
Normal file
108
drivers/network/dd/dc21x4/eeprom.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: EEPROM specific definitions
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pshpack1.h>
|
||||
typedef struct _DC_SROM_COMPACT_BLOCK
|
||||
{
|
||||
USHORT SelectedConnectionType;
|
||||
UCHAR GpioDirection; /* 21140 only */
|
||||
UCHAR BlockCount;
|
||||
} DC_SROM_COMPACT_BLOCK, *PDC_SROM_COMPACT_BLOCK;
|
||||
#include <poppack.h>
|
||||
|
||||
typedef struct _DC_SROM_REPAIR_ENTRY
|
||||
{
|
||||
#if DBG
|
||||
PCSTR Name;
|
||||
#endif
|
||||
PUCHAR InfoLeaf;
|
||||
ULONG Length;
|
||||
} DC_SROM_REPAIR_ENTRY, *PDC_SROM_REPAIR_ENTRY;
|
||||
|
||||
typedef struct _DC_SROM_ENTRY
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
ULONG BusNumber;
|
||||
DC_CHIP_TYPE ChipType;
|
||||
UCHAR DeviceNumber;
|
||||
ULONG InterruptLevel;
|
||||
ULONG InterruptVector;
|
||||
ULONG DeviceBitmap;
|
||||
UCHAR SRomImage[ANYSIZE_ARRAY];
|
||||
} DC_SROM_ENTRY, *PDC_SROM_ENTRY;
|
||||
|
||||
#define SRomIsBlockExtended(Byte) ((Byte) & 0x80)
|
||||
#define SRomGetExtendedBlockLength(Byte) (((Byte) & 0x7F) + 1)
|
||||
#define SRomGetMediaCode(Byte) ((Byte) & 0x3F)
|
||||
#define SRomBlockHasExtendedData(Byte) ((Byte) & 0x40)
|
||||
#define SRomIsDefaultMedia(Word) ((Word) & 0x4000)
|
||||
#define SRomMediaHasActivityIndicator(Word) (((Word) & 0x8000) == 0)
|
||||
#define SRomMediaActivityIsActiveLow(Word) ((Word) & 0x80)
|
||||
#define SRomMediaGetSenseMask(Word) (1 << (((Word) & 0x0E) >> 1))
|
||||
#define SRomCommandToOpMode(Word) (((Word) & 0x71) << 18)
|
||||
#define SRomMediaAutoSense(Media) ((Media) & 0x800)
|
||||
#define SRomMediaToMediaNumber(Word) ((Word) & 0x1F)
|
||||
#define SRomHmrRegAddress(Byte) ((Byte) & 0x1F)
|
||||
|
||||
#define SROM_OPMODE_MASK \
|
||||
(DC_OPMODE_PORT_SELECT | \
|
||||
DC_OPMODE_PORT_XMIT_10 | \
|
||||
DC_OPMODE_PORT_PCS | \
|
||||
DC_OPMODE_PORT_SCRAMBLER)
|
||||
|
||||
#define EE_SIZE 128
|
||||
#define EAR_SIZE 32
|
||||
|
||||
#define EAR_TEST_PATTERN 0xAA5500FFAA5500FFULL
|
||||
|
||||
#define EEPROM_CMD_WRITE 5
|
||||
#define EEPROM_CMD_READ 6
|
||||
#define EEPROM_CMD_ERASE 7
|
||||
|
||||
#define EEPROM_CMD_LENGTH 3
|
||||
|
||||
/*
|
||||
* Various offsets in the SROM
|
||||
*/
|
||||
#define SROM_VERSION 18
|
||||
#define SROM_CONTROLLER_COUNT 19
|
||||
#define SROM_MAC_ADDRESS 20
|
||||
#define SROM_DEVICE_NUMBER(n) (26 + ((n) * 3))
|
||||
#define SROM_LEAF_OFFSET(n) (27 + ((n) * 3))
|
||||
#define SROM_CHECKSUM_V1 126
|
||||
#define SROM_CHECKSUM_V2 94
|
||||
|
||||
/*
|
||||
* SROM compact and extended format types
|
||||
*/
|
||||
#define SROM_BLOCK_TYPE_GPR 0
|
||||
#define SROM_BLOCK_TYPE_MII_1 1
|
||||
#define SROM_BLOCK_TYPE_SIA 2
|
||||
#define SROM_BLOCK_TYPE_MII_2 3
|
||||
#define SROM_BLOCK_TYPE_SYM 4
|
||||
#define SROM_BLOCK_TYPE_RESET 5
|
||||
#define SROM_BLOCK_TYPE_PHY_SHUTDOWN 6
|
||||
#define SROM_BLOCK_TYPE_HOMERUN 7
|
||||
|
||||
#define SROM_MAX_STREAM_REGS 6
|
||||
|
||||
/*
|
||||
* SROM media codes
|
||||
*/
|
||||
#define SROM_MEDIA_10T 0
|
||||
#define SROM_MEDIA_BNC 1
|
||||
#define SROM_MEDIA_AUI 2
|
||||
#define SROM_MEDIA_100T_HD 3
|
||||
#define SROM_MEDIA_10T_FD 4
|
||||
#define SROM_MEDIA_100TX_FD 5
|
||||
#define SROM_MEDIA_100T4 6
|
||||
#define SROM_MEDIA_100FX_HD 7
|
||||
#define SROM_MEDIA_100FX_FD 8
|
||||
#define SROM_MEDIA_MAX 8
|
||||
#define SROM_MEDIA_HMR 18
|
219
drivers/network/dd/dc21x4/eeprom_data.c
Normal file
219
drivers/network/dd/dc21x4/eeprom_data.c
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: EEPROM data for boards without the standard SROM Format
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* Adapted from the Linux tulip driver written by Donald Becker */
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/* Asante */
|
||||
static DC_PG_DATA UCHAR SRompLeafAsante[] =
|
||||
{
|
||||
0x00, 0x00, 0x94,
|
||||
|
||||
0x00, 0x08, // Default Autoselect
|
||||
0x00, // GPIO direction
|
||||
0x01, // 1 block
|
||||
|
||||
0x80 + 12, // Extended block, 12 bytes
|
||||
0x01, // MII
|
||||
0x00, // PHY #0
|
||||
0x00, // GPIO stream length
|
||||
0x00, // Reset stream length
|
||||
0x00, 0x78, // Capabilities
|
||||
0xE0, 0x01, // Advertisement
|
||||
0x00, 0x50, // FDX
|
||||
0x00, 0x18, // TTM
|
||||
};
|
||||
|
||||
/* SMC 9332DST */
|
||||
static DC_PG_DATA UCHAR SRompLeaf9332[] =
|
||||
{
|
||||
0x00, 0x00, 0xC0,
|
||||
|
||||
0x00, 0x08, // Default Autoselect
|
||||
0x1F, // GPIO direction
|
||||
0x04, // 4 blocks
|
||||
|
||||
0x00, // GPR 0
|
||||
0x00, // GPIO data
|
||||
0x9E, 0x00, // Command 0x009E
|
||||
|
||||
0x04, // GPR 4
|
||||
0x00, // GPIO data
|
||||
0x9E, 0x00, // Command 0x009E
|
||||
0x03, // GPR 3
|
||||
0x09, // GPIO data
|
||||
0x6D, 0x00, // Command 0x006D
|
||||
|
||||
0x05, // GPR 5
|
||||
0x09, // GPIO data
|
||||
0x6D, 0x00, // Command 0x006D
|
||||
};
|
||||
|
||||
/* Cogent EM100 */
|
||||
static DC_PG_DATA UCHAR SRompLeafEm100[] =
|
||||
{
|
||||
0x00, 0x00, 0x92,
|
||||
|
||||
0x00, 0x08, // Default Autoselect
|
||||
0x3F, // GPIO direction
|
||||
0x06, // 6 blocks
|
||||
|
||||
0x07, // GPR 7
|
||||
0x01, // GPIO data
|
||||
0x21, 0x80, // Command 0x8021
|
||||
|
||||
0x08, // GPR 8
|
||||
0x01, // GPIO data
|
||||
0x21, 0x80, // Command 0x8021
|
||||
|
||||
0x00, // GPR 0
|
||||
0x01, // GPIO data
|
||||
0x9E, 0x00, // Command 0x009E
|
||||
|
||||
0x04, // GPR 4
|
||||
0x01, // GPIO data
|
||||
0x9E, 0x00, // Command 0x009E
|
||||
|
||||
0x03, // GPR 3
|
||||
0x01, // GPIO data
|
||||
0x6D, 0x00, // Command 0x006D
|
||||
|
||||
0x05, // GPR 5
|
||||
0x01, // GPIO data
|
||||
0x6D, 0x00, // Command 0x006D
|
||||
};
|
||||
|
||||
/* Maxtech NX-110 */
|
||||
static DC_PG_DATA UCHAR SRompLeafNx110[] =
|
||||
{
|
||||
0x00, 0x00, 0xE8,
|
||||
|
||||
0x00, 0x08, // Default Autoselect
|
||||
0x13, // GPIO direction
|
||||
0x05, // 5 blocks
|
||||
|
||||
0x01, // GPR 1
|
||||
0x10, // GPIO data
|
||||
0x9E, 0x00, // Command 0x009E
|
||||
|
||||
0x00, // GPR 0
|
||||
0x00, // GPIO data
|
||||
0x9E, 0x00, // Command 0x009E
|
||||
|
||||
0x04, // GPR 4
|
||||
0x00, // GPIO data
|
||||
0x9E, 0x00, // Command 0x009E
|
||||
|
||||
0x03, // GPR 3
|
||||
0x03, // GPIO data
|
||||
0x6D, 0x00, // Command 0x006D
|
||||
|
||||
0x05, // GPR 5
|
||||
0x03, // GPIO data
|
||||
0x6D, 0x00, // Command 0x006D
|
||||
};
|
||||
|
||||
/* Accton EN1207 */
|
||||
static DC_PG_DATA UCHAR SRompLeafEn1207[] =
|
||||
{
|
||||
0x00, 0x00, 0xE8,
|
||||
|
||||
0x00, 0x08, // Default Autoselect
|
||||
0x1F, // GPIO direction
|
||||
0x05, // 5 blocks
|
||||
|
||||
0x01, // GPR 1
|
||||
0x1B, // GPIO data
|
||||
0x00, 0x00, // Command 0x0000
|
||||
|
||||
0x00, // GPR 0
|
||||
0x0B, // GPIO data
|
||||
0x9E, 0x00, // Command 0x009E
|
||||
|
||||
0x04, // GPR 4
|
||||
0x0B, // GPIO data
|
||||
0x9E, 0x00, // Command 0x009E
|
||||
|
||||
0x03, // GPR 3
|
||||
0x1B, // GPIO data
|
||||
0x6D, 0x00, // Command 0x006D
|
||||
|
||||
0x05, // GPR 5
|
||||
0x1B, // GPIO data
|
||||
0x6D, 0x00, // Command 0x006D
|
||||
};
|
||||
|
||||
/* NetWinder */
|
||||
static DC_PG_DATA UCHAR SRompLeafNetWinder[] =
|
||||
{
|
||||
0x00, 0x10, 0x57,
|
||||
|
||||
0x00, 0x08, // Default Autoselect
|
||||
0x01, // 1 block
|
||||
|
||||
0x80 + 21, // Extended block, 21 bytes
|
||||
0x03, // MII
|
||||
0x01, // PHY #1
|
||||
0x00, // GPIO stream length
|
||||
0x03, // Reset stream length
|
||||
0x21, 0x08,
|
||||
0x00, 0x00,
|
||||
0x01, 0x00,
|
||||
0x00, 0x00, // Capabilities
|
||||
0xE1, 0x01, // Advertisement
|
||||
0x00, 0x00, // FDX
|
||||
0x00, 0x00, // TTM
|
||||
0x00, // PHY cannot be unplugged
|
||||
};
|
||||
|
||||
/* Cobalt Microserver */
|
||||
static DC_PG_DATA UCHAR SRompLeafCobaltMicroserver[] =
|
||||
{
|
||||
0x00, 0x10, 0xE0,
|
||||
|
||||
0x00, 0x08, // Default Autoselect
|
||||
0x01, // 1 block
|
||||
|
||||
0x80 + 21, // Extended block, 21 bytes
|
||||
0x03, // MII
|
||||
0x00, // PHY #0
|
||||
0x00, // GPIO stream length
|
||||
0x04, // Reset stream length
|
||||
0x01, 0x08, // Set control mode, GP0 output
|
||||
0x00, 0x00, // Drive GP0 Low (RST is active low)
|
||||
0x00, 0x08, // Control mode, GP0 input (undriven)
|
||||
0x00, 0x00, // Clear control mode
|
||||
0x00, 0x78, // Capabilities: 100TX FDX + HDX, 10bT FDX + HDX
|
||||
0xE0, 0x01, // Advertise all above
|
||||
0x00, 0x50, // FDX all above
|
||||
0x00, 0x18, // Set fast TTM in 100bt modes
|
||||
0x00, // PHY cannot be unplugged
|
||||
};
|
||||
|
||||
#if DBG
|
||||
#define DEFINE_BOARD(Leaf, Name) { Name, Leaf, sizeof(Leaf) - 3 /* OUI (3 bytes) */}
|
||||
#else
|
||||
#define DEFINE_BOARD(Leaf, Name) { Leaf, sizeof(Leaf) - 3 }
|
||||
#endif
|
||||
|
||||
DC_PG_DATA
|
||||
DC_SROM_REPAIR_ENTRY SRompRepairData[] =
|
||||
{
|
||||
DEFINE_BOARD(SRompLeafAsante, "Asante"),
|
||||
DEFINE_BOARD(SRompLeaf9332, "SMC 9332DST"),
|
||||
DEFINE_BOARD(SRompLeafEm100, "Cogent EM100"),
|
||||
DEFINE_BOARD(SRompLeafNx110, "Maxtech NX-110"),
|
||||
DEFINE_BOARD(SRompLeafEn1207, "Accton EN1207"), // Must be defined after the NX-110
|
||||
DEFINE_BOARD(SRompLeafNetWinder, "NetWinder"),
|
||||
DEFINE_BOARD(SRompLeafCobaltMicroserver, "Cobalt Microserver"),
|
||||
DEFINE_BOARD(NULL, NULL),
|
||||
};
|
585
drivers/network/dd/dc21x4/hardware.c
Normal file
585
drivers/network/dd/dc21x4/hardware.c
Normal file
|
@ -0,0 +1,585 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Hardware specific functions
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
DcDisableHw(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG OpMode;
|
||||
|
||||
/* Disable interrupts */
|
||||
DC_WRITE(Adapter, DcCsr7_IrqMask, 0);
|
||||
|
||||
/* Stop DMA */
|
||||
OpMode = Adapter->OpMode;
|
||||
OpMode &= ~(DC_OPMODE_RX_ENABLE | DC_OPMODE_TX_ENABLE);
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, OpMode);
|
||||
|
||||
/* Put the adapter to snooze mode */
|
||||
DcPowerSave(Adapter, TRUE);
|
||||
|
||||
/* Perform a software reset */
|
||||
DC_WRITE(Adapter, DcCsr0_BusMode, DC_BUS_MODE_SOFT_RESET);
|
||||
}
|
||||
|
||||
VOID
|
||||
DcStopTxRxProcess(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG i, OpMode, Status;
|
||||
|
||||
OpMode = Adapter->OpMode;
|
||||
OpMode &= ~(DC_OPMODE_RX_ENABLE | DC_OPMODE_TX_ENABLE);
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, OpMode);
|
||||
|
||||
for (i = 0; i < 5000; ++i)
|
||||
{
|
||||
Status = DC_READ(Adapter, DcCsr5_Status);
|
||||
|
||||
if (((Status & DC_STATUS_TX_STATE_MASK) == DC_STATUS_TX_STATE_STOPPED) &&
|
||||
((Status & DC_STATUS_RX_STATE_MASK) == DC_STATUS_RX_STATE_STOPPED))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NdisStallExecution(10);
|
||||
}
|
||||
|
||||
WARN("Failed to stop the TX/RX process 0x%08lx\n", Status);
|
||||
}
|
||||
|
||||
VOID
|
||||
DcWriteGpio(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG Value)
|
||||
{
|
||||
ULONG Data, Register;
|
||||
|
||||
/* Some chips don't have a separate GPIO register */
|
||||
if (Adapter->Features & DC_SIA_GPIO)
|
||||
{
|
||||
Data = Adapter->SiaSetting;
|
||||
Data &= 0x0000FFFF; /* SIA */
|
||||
Data |= Value << 16; /* GPIO */
|
||||
Adapter->SiaSetting = Data;
|
||||
|
||||
Register = DcCsr15_SiaGeneral;
|
||||
}
|
||||
else
|
||||
{
|
||||
Data = Value;
|
||||
Register = DcCsr12_Gpio;
|
||||
}
|
||||
DC_WRITE(Adapter, Register, Data);
|
||||
}
|
||||
|
||||
VOID
|
||||
DcWriteSia(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG Csr13,
|
||||
_In_ ULONG Csr14,
|
||||
_In_ ULONG Csr15)
|
||||
{
|
||||
ULONG SiaConn, SiaGen;
|
||||
|
||||
TRACE("CSR13 %08lx, CSR14 %08lx, CSR15 %08lx\n", Csr13, Csr14, Csr15);
|
||||
|
||||
SiaConn = 0;
|
||||
|
||||
/* The 21145 comes with 16 new bits in CSR13 */
|
||||
if (Adapter->Features & DC_SIA_ANALOG_CONTROL)
|
||||
{
|
||||
SiaConn = Adapter->AnalogControl;
|
||||
}
|
||||
|
||||
/* Reset the transceiver */
|
||||
DC_WRITE(Adapter, DcCsr13_SiaConnectivity, SiaConn | DC_SIA_CONN_RESET);
|
||||
NdisStallExecution(20);
|
||||
|
||||
/* Some chips don't have a separate GPIO register */
|
||||
if (Adapter->Features & DC_SIA_GPIO)
|
||||
{
|
||||
SiaGen = Adapter->SiaSetting;
|
||||
SiaGen &= 0xFFFF0000; /* GPIO */
|
||||
SiaGen |= Csr15; /* SIA */
|
||||
Adapter->SiaSetting = SiaGen;
|
||||
}
|
||||
else
|
||||
{
|
||||
SiaGen = Csr15;
|
||||
}
|
||||
|
||||
DC_WRITE(Adapter, DcCsr14_SiaTxRx, Csr14);
|
||||
DC_WRITE(Adapter, DcCsr15_SiaGeneral, SiaGen);
|
||||
|
||||
/* Don't reset the transceiver twice */
|
||||
if (Csr13 == DC_SIA_CONN_RESET)
|
||||
return;
|
||||
|
||||
DC_WRITE(Adapter, DcCsr13_SiaConnectivity, SiaConn | Csr13);
|
||||
}
|
||||
|
||||
VOID
|
||||
DcTestPacket(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PDC_TCB Tcb;
|
||||
PDC_TBD Tbd;
|
||||
ULONG FrameNumber;
|
||||
|
||||
Adapter->MediaTestStatus = FALSE;
|
||||
Adapter->ModeFlags |= DC_MODE_TEST_PACKET;
|
||||
|
||||
if (!Adapter->LoopbackFrameSlots)
|
||||
{
|
||||
ERR("Failed to complete test packets, CSR12 %08lx, CSR5 %08lx\n",
|
||||
DC_READ(Adapter, DcCsr12_SiaStatus),
|
||||
DC_READ(Adapter, DcCsr5_Status));
|
||||
|
||||
/* Try to recover the lost TX buffers */
|
||||
NdisScheduleWorkItem(&Adapter->TxRecoveryWorkItem);
|
||||
return;
|
||||
}
|
||||
|
||||
--Adapter->LoopbackFrameSlots;
|
||||
|
||||
FrameNumber = (Adapter->LoopbackFrameNumber++) % DC_LOOPBACK_FRAMES;
|
||||
|
||||
Tbd = Adapter->CurrentTbd;
|
||||
Adapter->CurrentTbd = DC_NEXT_TBD(Adapter, Tbd);
|
||||
|
||||
Tcb = Adapter->CurrentTcb;
|
||||
Adapter->CurrentTcb = DC_NEXT_TCB(Adapter, Tcb);
|
||||
|
||||
Tcb->Tbd = Tbd;
|
||||
Tcb->Packet = NULL;
|
||||
|
||||
ASSERT(!(Tbd->Status & DC_TBD_STATUS_OWNED));
|
||||
|
||||
/* Put the loopback frame on the transmit ring */
|
||||
Tbd->Address1 = Adapter->LoopbackFramePhys[FrameNumber];
|
||||
Tbd->Address2 = 0;
|
||||
Tbd->Control &= DC_TBD_CONTROL_END_OF_RING;
|
||||
Tbd->Control |= DC_LOOPBACK_FRAME_SIZE |
|
||||
DC_TBD_CONTROL_FIRST_FRAGMENT |
|
||||
DC_TBD_CONTROL_LAST_FRAGMENT |
|
||||
DC_TBD_CONTROL_REQUEST_INTERRUPT;
|
||||
DC_WRITE_BARRIER();
|
||||
Tbd->Status = DC_TBD_STATUS_OWNED;
|
||||
|
||||
/* Send the loopback packet to verify connectivity of a media */
|
||||
DC_WRITE(Adapter, DcCsr1_TxPoll, DC_TX_POLL_DOORBELL);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
DcSetupFrameDownload(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN WaitForCompletion)
|
||||
{
|
||||
PDC_TCB Tcb;
|
||||
PDC_TBD Tbd;
|
||||
ULONG i, Control;
|
||||
|
||||
Tbd = Adapter->CurrentTbd;
|
||||
|
||||
/* Ensure correct setup frame processing */
|
||||
if (Tbd != Adapter->HeadTbd)
|
||||
{
|
||||
ASSERT(!(Tbd->Status & DC_TBD_STATUS_OWNED));
|
||||
|
||||
/* Put the null frame on the transmit ring */
|
||||
Tbd->Control &= DC_TBD_CONTROL_END_OF_RING;
|
||||
Tbd->Address1 = 0;
|
||||
Tbd->Address2 = 0;
|
||||
DC_WRITE_BARRIER();
|
||||
Tbd->Status = DC_TBD_STATUS_OWNED;
|
||||
|
||||
Tbd = DC_NEXT_TBD(Adapter, Tbd);
|
||||
}
|
||||
|
||||
Adapter->CurrentTbd = DC_NEXT_TBD(Adapter, Tbd);
|
||||
|
||||
Tcb = Adapter->CurrentTcb;
|
||||
Adapter->CurrentTcb = DC_NEXT_TCB(Adapter, Tcb);
|
||||
|
||||
Tcb->Tbd = Tbd;
|
||||
Tcb->Packet = NULL;
|
||||
|
||||
ASSERT(!(Tbd->Status & DC_TBD_STATUS_OWNED));
|
||||
|
||||
/* Prepare the setup frame */
|
||||
Tbd->Address1 = Adapter->SetupFramePhys;
|
||||
Tbd->Address2 = 0;
|
||||
Tbd->Control &= DC_TBD_CONTROL_END_OF_RING;
|
||||
Control = DC_SETUP_FRAME_SIZE | DC_TBD_CONTROL_SETUP_FRAME;
|
||||
if (!WaitForCompletion)
|
||||
Control |= DC_TBD_CONTROL_REQUEST_INTERRUPT;
|
||||
if (Adapter->ProgramHashPerfectFilter)
|
||||
Control |= DC_TBD_CONTROL_HASH_PERFECT_FILTER;
|
||||
Tbd->Control |= Control;
|
||||
DC_WRITE_BARRIER();
|
||||
Tbd->Status = DC_TBD_STATUS_OWNED;
|
||||
|
||||
DC_WRITE(Adapter, DcCsr1_TxPoll, DC_TX_POLL_DOORBELL);
|
||||
|
||||
if (!WaitForCompletion)
|
||||
return TRUE;
|
||||
|
||||
/* Wait up to 500 ms for the chip to process the setup frame */
|
||||
for (i = 50000; i > 0; --i)
|
||||
{
|
||||
NdisStallExecution(10);
|
||||
|
||||
KeMemoryBarrierWithoutFence();
|
||||
if (!(Tbd->Status & DC_TBD_STATUS_OWNED))
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
{
|
||||
ERR("Failed to complete setup frame %08lx\n", Tbd->Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcSetupFrameInitialize(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PULONG SetupFrame, SetupFrameStart;
|
||||
PUSHORT MacAddress;
|
||||
ULONG i;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
SetupFrame = Adapter->SetupFrame;
|
||||
|
||||
/* Add the physical address entry */
|
||||
MacAddress = (PUSHORT)Adapter->CurrentMacAddress;
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(MacAddress[0]);
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(MacAddress[1]);
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(MacAddress[2]);
|
||||
|
||||
/* Pad to 16 addresses */
|
||||
SetupFrameStart = Adapter->SetupFrame;
|
||||
for (i = 1; i < DC_SETUP_FRAME_PERFECT_FILTER_ADDRESSES; ++i)
|
||||
{
|
||||
*SetupFrame++ = SetupFrameStart[0];
|
||||
*SetupFrame++ = SetupFrameStart[1];
|
||||
*SetupFrame++ = SetupFrameStart[2];
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcSetupFramePerfectFiltering(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PULONG SetupFrame, SetupFrameStart;
|
||||
PUSHORT MacAddress;
|
||||
ULONG i;
|
||||
|
||||
SetupFrame = Adapter->SetupFrame;
|
||||
|
||||
/* Add the physical address entry */
|
||||
MacAddress = (PUSHORT)Adapter->CurrentMacAddress;
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(MacAddress[0]);
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(MacAddress[1]);
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(MacAddress[2]);
|
||||
|
||||
/* Store multicast addresses */
|
||||
for (i = 0; i < Adapter->MulticastCount; ++i)
|
||||
{
|
||||
MacAddress = (PUSHORT)Adapter->MulticastList[i].MacAddress;
|
||||
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(MacAddress[0]);
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(MacAddress[1]);
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(MacAddress[2]);
|
||||
}
|
||||
|
||||
++i;
|
||||
|
||||
/* Add the broadcast address entry */
|
||||
if (Adapter->PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
|
||||
{
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(0x0000FFFF);
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(0x0000FFFF);
|
||||
*SetupFrame++ = DC_SETUP_FRAME_ENTRY(0x0000FFFF);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Pad to 16 addresses */
|
||||
SetupFrameStart = Adapter->SetupFrame;
|
||||
while (i < DC_SETUP_FRAME_PERFECT_FILTER_ADDRESSES)
|
||||
{
|
||||
*SetupFrame++ = SetupFrameStart[0];
|
||||
*SetupFrame++ = SetupFrameStart[1];
|
||||
*SetupFrame++ = SetupFrameStart[2];
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcSetupFrameImperfectFiltering(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PULONG SetupFrame = Adapter->SetupFrame;
|
||||
PUSHORT MacAddress;
|
||||
ULONG Hash, i;
|
||||
|
||||
RtlZeroMemory(SetupFrame, DC_SETUP_FRAME_SIZE);
|
||||
|
||||
/* Fill up the 512-bit multicast hash table */
|
||||
for (i = 0; i < Adapter->MulticastCount; ++i)
|
||||
{
|
||||
MacAddress = (PUSHORT)Adapter->MulticastList[i].MacAddress;
|
||||
|
||||
/* Only need lower 9 bits of the hash */
|
||||
Hash = DcEthernetCrc(MacAddress, ETH_LENGTH_OF_ADDRESS);
|
||||
Hash &= 512 - 1;
|
||||
SetupFrame[Hash / 16] |= 1 << (Hash % 16);
|
||||
}
|
||||
|
||||
/* Insert the broadcast address hash to the bin */
|
||||
if (Adapter->PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
|
||||
{
|
||||
Hash = DC_SETUP_FRAME_BROADCAST_HASH;
|
||||
SetupFrame[Hash / 16] |= 1 << (Hash % 16);
|
||||
}
|
||||
|
||||
/* Add the physical address entry */
|
||||
MacAddress = (PUSHORT)Adapter->CurrentMacAddress;
|
||||
SetupFrame[39] = DC_SETUP_FRAME_ENTRY(MacAddress[0]);
|
||||
SetupFrame[40] = DC_SETUP_FRAME_ENTRY(MacAddress[1]);
|
||||
SetupFrame[41] = DC_SETUP_FRAME_ENTRY(MacAddress[2]);
|
||||
}
|
||||
|
||||
NDIS_STATUS
|
||||
DcUpdateMulticastList(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
BOOLEAN UsePerfectFiltering;
|
||||
|
||||
/* If more than 14 addresses are requested, switch to hash filtering mode */
|
||||
UsePerfectFiltering = (Adapter->MulticastCount <= DC_SETUP_FRAME_ADDRESSES);
|
||||
|
||||
Adapter->ProgramHashPerfectFilter = UsePerfectFiltering;
|
||||
Adapter->OidPending = TRUE;
|
||||
|
||||
if (UsePerfectFiltering)
|
||||
DcSetupFramePerfectFiltering(Adapter);
|
||||
else
|
||||
DcSetupFrameImperfectFiltering(Adapter);
|
||||
|
||||
NdisAcquireSpinLock(&Adapter->SendLock);
|
||||
|
||||
DcSetupFrameDownload(Adapter, FALSE);
|
||||
|
||||
NdisReleaseSpinLock(&Adapter->SendLock);
|
||||
|
||||
return NDIS_STATUS_PENDING;
|
||||
}
|
||||
|
||||
NDIS_STATUS
|
||||
DcApplyPacketFilter(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG PacketFilter)
|
||||
{
|
||||
ULONG OpMode, OldPacketFilter;
|
||||
|
||||
INFO("Packet filter value 0x%lx\n", PacketFilter);
|
||||
|
||||
NdisAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
/* Update the filtering mode */
|
||||
OpMode = Adapter->OpMode;
|
||||
OpMode &= ~(DC_OPMODE_RX_PROMISCUOUS | DC_OPMODE_RX_ALL_MULTICAST);
|
||||
if (PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
|
||||
{
|
||||
OpMode |= DC_OPMODE_RX_PROMISCUOUS;
|
||||
}
|
||||
else if (PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
|
||||
{
|
||||
OpMode |= DC_OPMODE_RX_ALL_MULTICAST;
|
||||
}
|
||||
Adapter->OpMode = OpMode;
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, OpMode);
|
||||
|
||||
NdisReleaseSpinLock(&Adapter->ModeLock);
|
||||
|
||||
OldPacketFilter = Adapter->PacketFilter;
|
||||
Adapter->PacketFilter = PacketFilter;
|
||||
|
||||
/* Program the NIC to receive or reject broadcast frames */
|
||||
if ((OldPacketFilter ^ PacketFilter) & NDIS_PACKET_TYPE_BROADCAST)
|
||||
{
|
||||
return DcUpdateMulticastList(Adapter);
|
||||
}
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcSoftReset(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
/* Linux driver does this */
|
||||
if (Adapter->Features & DC_HAS_MII)
|
||||
{
|
||||
/* Select the MII/SYM port */
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, DC_OPMODE_PORT_SELECT);
|
||||
}
|
||||
|
||||
/* Perform a software reset */
|
||||
DC_WRITE(Adapter, DcCsr0_BusMode, DC_BUS_MODE_SOFT_RESET);
|
||||
NdisMSleep(100);
|
||||
DC_WRITE(Adapter, DcCsr0_BusMode, Adapter->BusMode);
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
NDIS_STATUS
|
||||
DcSetupAdapter(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DcInitTxRing(Adapter);
|
||||
DcInitRxRing(Adapter);
|
||||
|
||||
/* Initial values */
|
||||
if (!MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
Adapter->LinkSpeedMbps = 10;
|
||||
}
|
||||
Adapter->MediaNumber = Adapter->DefaultMedia;
|
||||
Adapter->ModeFlags &= ~(DC_MODE_PORT_AUTOSENSE | DC_MODE_AUI_FAILED | DC_MODE_BNC_FAILED |
|
||||
DC_MODE_TEST_PACKET | DC_MODE_AUTONEG_MASK);
|
||||
|
||||
DcSoftReset(Adapter);
|
||||
|
||||
/* Receive descriptor ring buffer */
|
||||
DC_WRITE(Adapter, DcCsr3_RxRingAddress, Adapter->RbdPhys);
|
||||
|
||||
/* Transmit descriptor ring buffer */
|
||||
DC_WRITE(Adapter, DcCsr4_TxRingAddress, Adapter->TbdPhys);
|
||||
|
||||
switch (Adapter->ChipType)
|
||||
{
|
||||
case DC21040:
|
||||
{
|
||||
DcWriteSia(Adapter,
|
||||
Adapter->Media[Adapter->MediaNumber].Csr13,
|
||||
Adapter->Media[Adapter->MediaNumber].Csr14,
|
||||
Adapter->Media[Adapter->MediaNumber].Csr15);
|
||||
|
||||
/* Explicitly specifed by user */
|
||||
if (Adapter->MediaNumber == MEDIA_10T_FD)
|
||||
{
|
||||
Adapter->OpMode |= DC_OPMODE_FULL_DUPLEX;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DC21041:
|
||||
{
|
||||
MediaSiaSelect(Adapter);
|
||||
break;
|
||||
}
|
||||
|
||||
case DC21140:
|
||||
{
|
||||
if (Adapter->MediaNumber == MEDIA_MII)
|
||||
{
|
||||
MediaSelectMiiPort(Adapter, !(Adapter->Flags & DC_FIRST_SETUP));
|
||||
MediaMiiSelect(Adapter);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All media use the same GPIO directon */
|
||||
DC_WRITE(Adapter, DcCsr12_Gpio, Adapter->Media[Adapter->MediaNumber].GpioCtrl);
|
||||
NdisStallExecution(10);
|
||||
|
||||
MediaGprSelect(Adapter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DC21143:
|
||||
case DC21145:
|
||||
{
|
||||
/* Init the HPNA PHY */
|
||||
if ((Adapter->MediaBitmap & (1 << MEDIA_HMR)) && Adapter->HpnaInitBitmap)
|
||||
{
|
||||
HpnaPhyInit(Adapter);
|
||||
}
|
||||
|
||||
if (Adapter->MediaNumber == MEDIA_MII)
|
||||
{
|
||||
MediaSelectMiiPort(Adapter, !(Adapter->Flags & DC_FIRST_SETUP));
|
||||
MediaMiiSelect(Adapter);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the current media is FX, assume we have a link */
|
||||
if (MEDIA_IS_FX(Adapter->MediaNumber))
|
||||
{
|
||||
Adapter->LinkUp = TRUE;
|
||||
|
||||
NdisMIndicateStatus(Adapter->AdapterHandle,
|
||||
NDIS_STATUS_MEDIA_CONNECT,
|
||||
NULL,
|
||||
0);
|
||||
NdisMIndicateStatusComplete(Adapter->AdapterHandle);
|
||||
}
|
||||
|
||||
MediaSiaSelect(Adapter);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
UNREACHABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Start the TX process */
|
||||
Adapter->OpMode |= DC_OPMODE_TX_ENABLE;
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, Adapter->OpMode);
|
||||
|
||||
/* Load the address recognition RAM */
|
||||
if (!DcSetupFrameDownload(Adapter, TRUE))
|
||||
{
|
||||
/* This normally should not happen */
|
||||
ASSERT(FALSE);
|
||||
|
||||
NdisWriteErrorLogEntry(Adapter->AdapterHandle,
|
||||
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
||||
1,
|
||||
__LINE__);
|
||||
|
||||
return NDIS_STATUS_HARD_ERRORS;
|
||||
}
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
}
|
1321
drivers/network/dd/dc21x4/init.c
Normal file
1321
drivers/network/dd/dc21x4/init.c
Normal file
File diff suppressed because it is too large
Load diff
625
drivers/network/dd/dc21x4/interrupt.c
Normal file
625
drivers/network/dd/dc21x4/interrupt.c
Normal file
|
@ -0,0 +1,625 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Interrupt handling
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
DcAdjustTxFifoThreshold(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG OpMode;
|
||||
|
||||
TRACE("TX underrun\n");
|
||||
|
||||
/* Maximum threshold reached */
|
||||
if ((Adapter->OpMode & DC_OPMODE_STORE_AND_FORWARD) ||
|
||||
(++Adapter->TransmitUnderruns < DC_TX_UNDERRUN_LIMIT))
|
||||
{
|
||||
NdisDprAcquireSpinLock(&Adapter->SendLock);
|
||||
|
||||
/* Start the transmit process if it was suspended */
|
||||
DC_WRITE(Adapter, DcCsr1_TxPoll, DC_TX_POLL_DOORBELL);
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->SendLock);
|
||||
return;
|
||||
}
|
||||
Adapter->TransmitUnderruns = 0;
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
OpMode = Adapter->OpMode;
|
||||
|
||||
/* Update the FIFO threshold level to minimize Tx FIFO underrun */
|
||||
if ((OpMode & DC_OPMODE_TX_THRESHOLD_CTRL_MASK) != DC_OPMODE_TX_THRESHOLD_MAX)
|
||||
{
|
||||
OpMode += DC_OPMODE_TX_THRESHOLD_LEVEL;
|
||||
|
||||
INFO("New OP Mode %08lx\n", OpMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
OpMode |= DC_OPMODE_STORE_AND_FORWARD;
|
||||
|
||||
INFO("Store & Forward\n");
|
||||
}
|
||||
|
||||
DcStopTxRxProcess(Adapter);
|
||||
|
||||
Adapter->OpMode = OpMode;
|
||||
|
||||
/* Restart the transmit process */
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, OpMode);
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcHandleTxJabberTimeout(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
WARN("Transmit jabber timer timed out\n");
|
||||
|
||||
NdisWriteErrorLogEntry(Adapter->AdapterHandle, NDIS_ERROR_CODE_HARDWARE_FAILURE, 1, __LINE__);
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
/* Start the transmit process if it was stopped */
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, Adapter->OpMode);
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcHandleTxCompletedFrames(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_Inout_ PLIST_ENTRY SendReadyList,
|
||||
_Out_ PULONG DpcEvents)
|
||||
{
|
||||
PDC_TCB Tcb;
|
||||
PDC_TBD Tbd;
|
||||
ULONG TbdStatus, Collisions;
|
||||
|
||||
for (Tcb = Adapter->LastTcb;
|
||||
Tcb != Adapter->CurrentTcb;
|
||||
Tcb = DC_NEXT_TCB(Adapter, Tcb))
|
||||
{
|
||||
Tbd = Tcb->Tbd;
|
||||
TbdStatus = Tbd->Status;
|
||||
|
||||
if (TbdStatus & DC_TBD_STATUS_OWNED)
|
||||
break;
|
||||
|
||||
++Adapter->TcbCompleted;
|
||||
|
||||
/* Complete the packet filter change request asynchronously */
|
||||
if (Tbd->Control & DC_TBD_CONTROL_SETUP_FRAME)
|
||||
{
|
||||
Tbd->Control &= ~DC_TBD_CONTROL_SETUP_FRAME;
|
||||
|
||||
if (Tbd->Control & DC_TBD_CONTROL_REQUEST_INTERRUPT)
|
||||
{
|
||||
*DpcEvents |= DC_EVENT_SETUP_FRAME_COMPLETED;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This is our media test packet, so no need to update the TX statistics */
|
||||
if (!Tcb->Packet)
|
||||
{
|
||||
_InterlockedExchange(&Adapter->MediaTestStatus,
|
||||
!(TbdStatus & DC_TBD_STATUS_ERROR_SUMMARY));
|
||||
|
||||
ASSERT(Adapter->LoopbackFrameSlots < DC_LOOPBACK_FRAMES);
|
||||
|
||||
++Adapter->LoopbackFrameSlots;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TbdStatus & DC_TBD_STATUS_ERROR_SUMMARY)
|
||||
{
|
||||
++Adapter->Statistics.TransmitErrors;
|
||||
|
||||
if (TbdStatus & DC_TBD_STATUS_UNDERFLOW)
|
||||
++Adapter->Statistics.TransmitUnderrunErrors;
|
||||
else if (TbdStatus & DC_TBD_STATUS_LATE_COLLISION)
|
||||
++Adapter->Statistics.TransmitLateCollisions;
|
||||
|
||||
if (TbdStatus & DC_TBD_STATUS_RETRY_ERROR)
|
||||
++Adapter->Statistics.TransmitExcessiveCollisions;
|
||||
if (TbdStatus & DC_TBD_STATUS_CARRIER_LOST)
|
||||
++Adapter->Statistics.TransmitLostCarrierSense;
|
||||
}
|
||||
else
|
||||
{
|
||||
++Adapter->Statistics.TransmitOk;
|
||||
|
||||
if (TbdStatus & DC_TBD_STATUS_DEFFERED)
|
||||
++Adapter->Statistics.TransmitDeferred;
|
||||
if (TbdStatus & DC_TBD_STATUS_HEARTBEAT_FAIL)
|
||||
++Adapter->Statistics.TransmitHeartbeatErrors;
|
||||
|
||||
Collisions = (TbdStatus & DC_TBD_STATUS_COLLISIONS_MASK) >>
|
||||
DC_TBD_STATUS_COLLISIONS_SHIFT;
|
||||
if (Collisions == 1)
|
||||
++Adapter->Statistics.TransmitOneRetry;
|
||||
else if (Collisions > 1)
|
||||
++Adapter->Statistics.TransmitMoreCollisions;
|
||||
}
|
||||
|
||||
InsertTailList(SendReadyList, DC_LIST_ENTRY_FROM_PACKET(Tcb->Packet));
|
||||
|
||||
DC_RELEASE_TCB(Adapter, Tcb);
|
||||
}
|
||||
|
||||
Adapter->LastTcb = Tcb;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcHandleTx(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
LIST_ENTRY SendReadyList;
|
||||
ULONG DpcEvents;
|
||||
|
||||
TRACE("Handle TX\n");
|
||||
|
||||
InitializeListHead(&SendReadyList);
|
||||
DpcEvents = 0;
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->SendLock);
|
||||
|
||||
DcHandleTxCompletedFrames(Adapter, &SendReadyList, &DpcEvents);
|
||||
|
||||
if (!IsListEmpty(&Adapter->SendQueueList))
|
||||
{
|
||||
DcProcessPendingPackets(Adapter);
|
||||
}
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->SendLock);
|
||||
|
||||
while (!IsListEmpty(&SendReadyList))
|
||||
{
|
||||
PLIST_ENTRY Entry = RemoveHeadList(&SendReadyList);
|
||||
|
||||
TRACE("Complete TX packet %p\n", DC_PACKET_FROM_LIST_ENTRY(Entry));
|
||||
|
||||
NdisMSendComplete(Adapter->AdapterHandle,
|
||||
DC_PACKET_FROM_LIST_ENTRY(Entry),
|
||||
NDIS_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/* We have to complete the OID request outside of the spinlock */
|
||||
if (DpcEvents & DC_EVENT_SETUP_FRAME_COMPLETED)
|
||||
{
|
||||
TRACE("SP completed\n");
|
||||
|
||||
Adapter->OidPending = FALSE;
|
||||
|
||||
NdisMSetInformationComplete(Adapter->AdapterHandle, NDIS_STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcStopRxProcess(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG i, OpMode, Status;
|
||||
|
||||
OpMode = Adapter->OpMode;
|
||||
OpMode &= ~DC_OPMODE_RX_ENABLE;
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, OpMode);
|
||||
|
||||
for (i = 0; i < 5000; ++i)
|
||||
{
|
||||
Status = DC_READ(Adapter, DcCsr5_Status);
|
||||
|
||||
if ((Status & DC_STATUS_RX_STATE_MASK) == DC_STATUS_RX_STATE_STOPPED)
|
||||
return;
|
||||
|
||||
NdisStallExecution(10);
|
||||
}
|
||||
|
||||
WARN("Failed to stop the RX process 0x%08lx\n", Status);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcReturnPacket(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ PNDIS_PACKET Packet)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
PDC_RCB Rcb;
|
||||
|
||||
Rcb = *DC_RCB_FROM_PACKET(Packet);
|
||||
|
||||
NdisAcquireSpinLock(&Adapter->ReceiveLock);
|
||||
|
||||
PushEntryList(&Adapter->FreeRcbList, &Rcb->ListEntry);
|
||||
|
||||
++Adapter->RcbFree;
|
||||
|
||||
NdisReleaseSpinLock(&Adapter->ReceiveLock);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcIndicateReceivePackets(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PNDIS_PACKET* ReceiveArray,
|
||||
_In_ ULONG PacketsToIndicate)
|
||||
{
|
||||
PNDIS_PACKET Packet;
|
||||
PDC_RBD Rbd;
|
||||
PDC_RCB Rcb;
|
||||
ULONG i;
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ReceiveLock);
|
||||
|
||||
NdisMIndicateReceivePacket(Adapter->AdapterHandle,
|
||||
ReceiveArray,
|
||||
PacketsToIndicate);
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ReceiveLock);
|
||||
|
||||
for (i = 0; i < PacketsToIndicate; ++i)
|
||||
{
|
||||
Packet = ReceiveArray[i];
|
||||
Rcb = *DC_RCB_FROM_PACKET(Packet);
|
||||
|
||||
/* Reuse the RCB immediately */
|
||||
if (Rcb->Flags & DC_RCB_FLAG_RECLAIM)
|
||||
{
|
||||
Rbd = *DC_RBD_FROM_PACKET(Packet);
|
||||
|
||||
Rbd->Status = DC_RBD_STATUS_OWNED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcHandleRxReceivedFrames(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PDC_RBD Rbd, StartRbd, LastRbd;
|
||||
ULONG PacketsToIndicate;
|
||||
PNDIS_PACKET ReceiveArray[DC_RECEIVE_ARRAY_SIZE];
|
||||
|
||||
Rbd = StartRbd = LastRbd = Adapter->CurrentRbd;
|
||||
PacketsToIndicate = 0;
|
||||
|
||||
while (PacketsToIndicate < RTL_NUMBER_OF(ReceiveArray))
|
||||
{
|
||||
PDC_RCB Rcb;
|
||||
PDC_RCB* RcbSlot;
|
||||
PNDIS_PACKET Packet;
|
||||
ULONG RbdStatus, PacketLength, RxCounters;
|
||||
|
||||
if (Rbd->Status & DC_RBD_STATUS_OWNED)
|
||||
break;
|
||||
|
||||
/* Work around the RX overflow bug */
|
||||
if ((Adapter->Features & DC_NEED_RX_OVERFLOW_WORKAROUND) && (Rbd == LastRbd))
|
||||
{
|
||||
/* Find the last received packet, to correctly catch invalid packets */
|
||||
do
|
||||
{
|
||||
LastRbd = DC_NEXT_RBD(Adapter, LastRbd);
|
||||
|
||||
if (LastRbd->Status & DC_RBD_STATUS_OWNED)
|
||||
break;
|
||||
}
|
||||
while (LastRbd != Rbd);
|
||||
|
||||
RxCounters = DC_READ(Adapter, DcCsr8_RxCounters);
|
||||
|
||||
Adapter->Statistics.ReceiveNoBuffers += RxCounters & DC_COUNTER_RX_NO_BUFFER_MASK;
|
||||
|
||||
/* A receive overflow might indicate a data corruption */
|
||||
if (RxCounters & DC_COUNTER_RX_OVERFLOW_MASK)
|
||||
{
|
||||
ERR("RX overflow, dropping the packets\n");
|
||||
|
||||
Adapter->Statistics.ReceiveOverrunErrors +=
|
||||
(RxCounters & DC_COUNTER_RX_OVERFLOW_MASK) >> DC_COUNTER_RX_OVERFLOW_SHIFT;
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
/* Stop the receive process */
|
||||
DcStopRxProcess(Adapter);
|
||||
|
||||
/* Drop all received packets regardless of what the status indicates */
|
||||
while (TRUE)
|
||||
{
|
||||
if (Rbd->Status & DC_RBD_STATUS_OWNED)
|
||||
break;
|
||||
|
||||
++Adapter->Statistics.ReceiveOverrunErrors;
|
||||
|
||||
Rbd->Status = DC_RBD_STATUS_OWNED;
|
||||
|
||||
Rbd = DC_NEXT_RBD(Adapter, Rbd);
|
||||
}
|
||||
LastRbd = Rbd;
|
||||
|
||||
/* Restart the receive process */
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, Adapter->OpMode);
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
RbdStatus = Rbd->Status;
|
||||
|
||||
/* Ignore oversized packets */
|
||||
if (!(RbdStatus & DC_RBD_STATUS_LAST_DESCRIPTOR))
|
||||
{
|
||||
Rbd->Status = DC_RBD_STATUS_OWNED;
|
||||
goto NextRbd;
|
||||
}
|
||||
|
||||
/* Check for an invalid packet */
|
||||
if (RbdStatus & DC_RBD_STATUS_INVALID)
|
||||
{
|
||||
++Adapter->Statistics.ReceiveErrors;
|
||||
|
||||
if (RbdStatus & DC_RBD_STATUS_OVERRUN)
|
||||
++Adapter->Statistics.ReceiveOverrunErrors;
|
||||
|
||||
if (RbdStatus & DC_RBD_STATUS_CRC_ERROR)
|
||||
{
|
||||
if (RbdStatus & DC_RBD_STATUS_DRIBBLE)
|
||||
++Adapter->Statistics.ReceiveAlignmentErrors;
|
||||
else
|
||||
++Adapter->Statistics.ReceiveCrcErrors;
|
||||
}
|
||||
|
||||
Rbd->Status = DC_RBD_STATUS_OWNED;
|
||||
goto NextRbd;
|
||||
}
|
||||
|
||||
++Adapter->Statistics.ReceiveOk;
|
||||
|
||||
PacketLength = (RbdStatus & DC_RBD_STATUS_FRAME_LENGTH_MASK) >>
|
||||
DC_RBD_STATUS_FRAME_LENGTH_SHIFT;
|
||||
|
||||
/* Omit the CRC */
|
||||
PacketLength -= 4;
|
||||
|
||||
RcbSlot = DC_GET_RCB_SLOT(Adapter, Rbd);
|
||||
Rcb = *RcbSlot;
|
||||
|
||||
TRACE("RX packet (len %u), RCB %p\n", PacketLength, Rcb);
|
||||
|
||||
NdisAdjustBufferLength(Rcb->NdisBuffer, PacketLength);
|
||||
|
||||
/* Receive buffers are in cached memory */
|
||||
NdisFlushBuffer(Rcb->NdisBuffer, FALSE);
|
||||
|
||||
if (RbdStatus & DC_RBD_STATUS_MULTICAST)
|
||||
{
|
||||
if (ETH_IS_BROADCAST(Rcb->VirtualAddress))
|
||||
++Adapter->Statistics.ReceiveBroadcast;
|
||||
else
|
||||
++Adapter->Statistics.ReceiveMulticast;
|
||||
}
|
||||
else
|
||||
{
|
||||
++Adapter->Statistics.ReceiveUnicast;
|
||||
}
|
||||
|
||||
Packet = Rcb->Packet;
|
||||
|
||||
ReceiveArray[PacketsToIndicate++] = Packet;
|
||||
|
||||
if (Adapter->FreeRcbList.Next)
|
||||
{
|
||||
Rcb->Flags = 0;
|
||||
NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_SUCCESS);
|
||||
|
||||
Rcb = (PDC_RCB)DcPopEntryList(&Adapter->FreeRcbList);
|
||||
*RcbSlot = Rcb;
|
||||
|
||||
ASSERT(Adapter->RcbFree > 0);
|
||||
--Adapter->RcbFree;
|
||||
|
||||
Rbd->Address1 = Rcb->PhysicalAddress;
|
||||
DC_WRITE_BARRIER();
|
||||
Rbd->Status = DC_RBD_STATUS_OWNED;
|
||||
}
|
||||
else
|
||||
{
|
||||
Rcb->Flags = DC_RCB_FLAG_RECLAIM;
|
||||
NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_RESOURCES);
|
||||
|
||||
*DC_RBD_FROM_PACKET(Packet) = Rbd;
|
||||
}
|
||||
|
||||
NextRbd:
|
||||
Rbd = DC_NEXT_RBD(Adapter, Rbd);
|
||||
|
||||
/*
|
||||
* Check the next descriptor to prevent wrap-around.
|
||||
* Since we don't use a fixed-sized ring,
|
||||
* the receive ring may be smaller in length than the ReceiveArray[].
|
||||
*/
|
||||
if (Rbd == StartRbd)
|
||||
break;
|
||||
}
|
||||
|
||||
Adapter->CurrentRbd = Rbd;
|
||||
|
||||
/* Pass the packets up */
|
||||
if (PacketsToIndicate)
|
||||
{
|
||||
DcIndicateReceivePackets(Adapter, ReceiveArray, PacketsToIndicate);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcHandleRx(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
NdisDprAcquireSpinLock(&Adapter->ReceiveLock);
|
||||
|
||||
do
|
||||
{
|
||||
DcHandleRxReceivedFrames(Adapter);
|
||||
}
|
||||
while (!(Adapter->CurrentRbd->Status & DC_RBD_STATUS_OWNED));
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ReceiveLock);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DcHandleSystemError(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG InterruptStatus)
|
||||
{
|
||||
ERR("%s error occured, CSR5 %08lx\n", DcDbgBusError(InterruptStatus), InterruptStatus);
|
||||
|
||||
NdisWriteErrorLogEntry(Adapter->AdapterHandle, NDIS_ERROR_CODE_HARDWARE_FAILURE, 1, __LINE__);
|
||||
|
||||
/* Issue a software reset, which also enables the interrupts */
|
||||
if (_InterlockedCompareExchange(&Adapter->ResetLock, 2, 0) == 0)
|
||||
{
|
||||
NdisScheduleWorkItem(&Adapter->ResetWorkItem);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcHandleInterrupt(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext)
|
||||
{
|
||||
ULONG InterruptStatus, IoLimit;
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
|
||||
TRACE("Events %08lx\n", Adapter->InterruptStatus);
|
||||
|
||||
if (!(Adapter->Flags & DC_ACTIVE))
|
||||
return;
|
||||
|
||||
IoLimit = DC_INTERRUPT_PROCESSING_LIMIT;
|
||||
InterruptStatus = Adapter->InterruptStatus;
|
||||
|
||||
/* Loop until the condition to stop is encountered */
|
||||
while (TRUE)
|
||||
{
|
||||
/* Uncommon interrupts */
|
||||
if (InterruptStatus & DC_IRQ_ABNORMAL_SUMMARY)
|
||||
{
|
||||
/* PCI bus error detected */
|
||||
if (InterruptStatus & DC_IRQ_SYSTEM_ERROR)
|
||||
{
|
||||
DcHandleSystemError(Adapter, InterruptStatus);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Transmit jabber timeout */
|
||||
if (InterruptStatus & DC_IRQ_TX_JABBER_TIMEOUT)
|
||||
{
|
||||
DcHandleTxJabberTimeout(Adapter);
|
||||
}
|
||||
|
||||
/* Link state changed */
|
||||
if (InterruptStatus & Adapter->LinkStateChangeMask)
|
||||
{
|
||||
Adapter->HandleLinkStateChange(Adapter, InterruptStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handling receive interrupts */
|
||||
if (InterruptStatus & (DC_IRQ_RX_OK | DC_IRQ_RX_STOPPED))
|
||||
{
|
||||
DcHandleRx(Adapter);
|
||||
}
|
||||
|
||||
/* Handling transmit interrupts */
|
||||
if (InterruptStatus & (DC_IRQ_TX_OK | DC_IRQ_TX_STOPPED))
|
||||
{
|
||||
DcHandleTx(Adapter);
|
||||
}
|
||||
|
||||
/* Transmit underflow error detected */
|
||||
if (InterruptStatus & DC_IRQ_TX_UNDERFLOW)
|
||||
{
|
||||
DcAdjustTxFifoThreshold(Adapter);
|
||||
}
|
||||
|
||||
/* Limit in order to avoid doing too much work at DPC level */
|
||||
if (!--IoLimit)
|
||||
break;
|
||||
|
||||
/* Check if new events have occurred */
|
||||
InterruptStatus = DC_READ(Adapter, DcCsr5_Status);
|
||||
if (InterruptStatus == 0xFFFFFFFF || !(InterruptStatus & Adapter->InterruptMask))
|
||||
break;
|
||||
|
||||
/* Acknowledge the events */
|
||||
DC_WRITE(Adapter, DcCsr5_Status, InterruptStatus);
|
||||
}
|
||||
|
||||
/* TODO: Add interrupt mitigation (CSR11) */
|
||||
|
||||
/* Reenable interrupts */
|
||||
_InterlockedExchange((PLONG)&Adapter->CurrentInterruptMask, Adapter->InterruptMask);
|
||||
DC_WRITE(Adapter, DcCsr7_IrqMask, Adapter->InterruptMask);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcIsr(
|
||||
_Out_ PBOOLEAN InterruptRecognized,
|
||||
_Out_ PBOOLEAN QueueMiniportHandleInterrupt,
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
ULONG InterruptStatus;
|
||||
|
||||
if (Adapter->CurrentInterruptMask == 0)
|
||||
goto NotOurs;
|
||||
|
||||
InterruptStatus = DC_READ(Adapter, DcCsr5_Status);
|
||||
if (InterruptStatus == 0xFFFFFFFF || !(InterruptStatus & Adapter->CurrentInterruptMask))
|
||||
goto NotOurs;
|
||||
|
||||
/* Disable further interrupts */
|
||||
DC_WRITE(Adapter, DcCsr7_IrqMask, 0);
|
||||
|
||||
/* Clear all pending events */
|
||||
DC_WRITE(Adapter, DcCsr5_Status, InterruptStatus);
|
||||
|
||||
Adapter->InterruptStatus = InterruptStatus;
|
||||
Adapter->CurrentInterruptMask = 0;
|
||||
|
||||
*InterruptRecognized = TRUE;
|
||||
*QueueMiniportHandleInterrupt = TRUE;
|
||||
return;
|
||||
|
||||
NotOurs:
|
||||
*InterruptRecognized = FALSE;
|
||||
*QueueMiniportHandleInterrupt = FALSE;
|
||||
}
|
634
drivers/network/dd/dc21x4/media.c
Normal file
634
drivers/network/dd/dc21x4/media.c
Normal file
|
@ -0,0 +1,634 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Media common code
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
MediaIndicateConnect(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN LinkUp)
|
||||
{
|
||||
/* Nothing to do */
|
||||
if (Adapter->LinkUp == LinkUp)
|
||||
return;
|
||||
|
||||
Adapter->LinkUp = LinkUp;
|
||||
|
||||
INFO_VERB("Link %sconnected, media is %s\n",
|
||||
LinkUp ? "" : "dis",
|
||||
MediaNumber2Str(Adapter, Adapter->MediaNumber));
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
|
||||
NdisMIndicateStatus(Adapter->AdapterHandle,
|
||||
LinkUp ? NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT,
|
||||
NULL,
|
||||
0);
|
||||
NdisMIndicateStatusComplete(Adapter->AdapterHandle);
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
}
|
||||
|
||||
static
|
||||
ULONG
|
||||
MediaMiiNextMedia(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
Adapter->ModeFlags &= ~(DC_MODE_TEST_PACKET | DC_MODE_AUI_FAILED | DC_MODE_BNC_FAILED);
|
||||
Adapter->LastReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
|
||||
|
||||
/*
|
||||
* In MII mode, we don't know exactly which port is active.
|
||||
* Switch to the media with a higher priority.
|
||||
*/
|
||||
if (Adapter->MediaBitmap & (1 << MEDIA_HMR))
|
||||
return MEDIA_HMR;
|
||||
else if (Adapter->MediaBitmap & (1 << MEDIA_AUI))
|
||||
return MEDIA_AUI;
|
||||
else
|
||||
return MEDIA_BNC;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
MediaMiiSetSpeedAndDuplex(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN FullDuplex,
|
||||
_In_ BOOLEAN Speed100)
|
||||
{
|
||||
ULONG OpMode = Adapter->OpMode;
|
||||
|
||||
if (FullDuplex)
|
||||
OpMode |= DC_OPMODE_FULL_DUPLEX;
|
||||
else
|
||||
OpMode &= ~DC_OPMODE_FULL_DUPLEX;
|
||||
|
||||
if (Speed100)
|
||||
OpMode &= ~DC_OPMODE_PORT_XMIT_10;
|
||||
else
|
||||
OpMode |= DC_OPMODE_PORT_XMIT_10;
|
||||
|
||||
/* Nothing to do */
|
||||
if (OpMode == Adapter->OpMode)
|
||||
return;
|
||||
|
||||
INFO_VERB("Configuring MAC from %u %s-duplex to %u %s-duplex\n",
|
||||
Adapter->LinkSpeedMbps,
|
||||
(Adapter->OpMode & DC_OPMODE_FULL_DUPLEX) ? "full" : "half",
|
||||
Speed100 ? 100 : 10,
|
||||
FullDuplex ? "full" : "half");
|
||||
|
||||
Adapter->LinkSpeedMbps = Speed100 ? 100 : 10;
|
||||
|
||||
DcStopTxRxProcess(Adapter);
|
||||
|
||||
Adapter->OpMode = OpMode;
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, Adapter->OpMode);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
MediaMiiGetSpeedAndDuplex(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_Out_ PBOOLEAN FullDuplex,
|
||||
_Out_ PBOOLEAN Speed100)
|
||||
{
|
||||
ULONG MiiLinkPartnerAbility, AdvLpa;
|
||||
|
||||
MiiRead(Adapter, Adapter->PhyAddress, MII_AUTONEG_LINK_PARTNER, &MiiLinkPartnerAbility);
|
||||
|
||||
TRACE("MII LPA %04lx\n", MiiLinkPartnerAbility);
|
||||
|
||||
AdvLpa = Adapter->MiiMedia.Advertising & MiiLinkPartnerAbility;
|
||||
if (AdvLpa & MII_LP_100T_FD)
|
||||
{
|
||||
*FullDuplex = TRUE;
|
||||
*Speed100 = TRUE;
|
||||
}
|
||||
else if (AdvLpa & MII_LP_100T4)
|
||||
{
|
||||
*FullDuplex = FALSE;
|
||||
*Speed100 = TRUE;
|
||||
}
|
||||
else if (AdvLpa & MII_LP_100T_HD)
|
||||
{
|
||||
*FullDuplex = FALSE;
|
||||
*Speed100 = TRUE;
|
||||
}
|
||||
else if (AdvLpa & MII_LP_10T_FD)
|
||||
{
|
||||
*FullDuplex = TRUE;
|
||||
*Speed100 = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*FullDuplex = FALSE;
|
||||
*Speed100 = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
MediaMiiCheckLink(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG MiiStatus;
|
||||
BOOLEAN FullDuplex, Speed100;
|
||||
|
||||
/* The link status is a latched-low bit, read it twice */
|
||||
if (!MiiRead(Adapter, Adapter->PhyAddress, MII_STATUS, &MiiStatus))
|
||||
{
|
||||
goto NoLink;
|
||||
}
|
||||
if (!(MiiStatus & MII_SR_LINK_STATUS))
|
||||
{
|
||||
MiiRead(Adapter, Adapter->PhyAddress, MII_STATUS, &MiiStatus);
|
||||
}
|
||||
TRACE("MII Status %04lx\n", MiiStatus);
|
||||
|
||||
/* Check the link status */
|
||||
if (!(MiiStatus & MII_SR_LINK_STATUS))
|
||||
{
|
||||
NoLink:
|
||||
/* No link detected, check the other port */
|
||||
if (Adapter->MediaBitmap & ((1 << MEDIA_HMR) | (1 << MEDIA_AUI) | (1 << MEDIA_BNC)))
|
||||
{
|
||||
if ((Adapter->Features & DC_MII_AUTOSENSE) && !MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
Adapter->MediaNumber = MediaMiiNextMedia(Adapter);
|
||||
MediaSiaSelect(Adapter);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If we are forcing speed and duplex */
|
||||
if (MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
FullDuplex = !!(Adapter->MiiControl & MII_CR_FULL_DUPLEX);
|
||||
Speed100 = !!(Adapter->MiiControl & MII_CR_SPEED_SELECTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check auto-negotiation is complete */
|
||||
if (!(MiiStatus & MII_SR_AUTONEG_COMPLETE))
|
||||
return FALSE;
|
||||
|
||||
MediaMiiGetSpeedAndDuplex(Adapter, &FullDuplex, &Speed100);
|
||||
}
|
||||
|
||||
/* Set the link speed and duplex */
|
||||
MediaMiiSetSpeedAndDuplex(Adapter, FullDuplex, Speed100);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
MediaMiiSelect(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG MiiControl, MiiAdvertise;
|
||||
|
||||
MiiRead(Adapter, Adapter->PhyAddress, MII_CONTROL, &MiiControl);
|
||||
MiiControl &= ~(MII_CR_POWER_DOWN | MII_CR_ISOLATE | MII_CR_RESET | MII_CR_SPEED_SELECTION |
|
||||
MII_CR_FULL_DUPLEX | MII_CR_AUTONEG | MII_CR_AUTONEG_RESTART);
|
||||
MiiWrite(Adapter, Adapter->PhyAddress, MII_CONTROL, MiiControl);
|
||||
|
||||
MiiControl |= Adapter->MiiControl;
|
||||
MiiAdvertise = Adapter->MiiAdvertising;
|
||||
|
||||
MiiWrite(Adapter, Adapter->PhyAddress, MII_AUTONEG_ADVERTISE, MiiAdvertise | MII_ADV_CSMA);
|
||||
MiiWrite(Adapter, Adapter->PhyAddress, MII_CONTROL, MiiControl);
|
||||
}
|
||||
|
||||
VOID
|
||||
MediaSelectMiiPort(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN ResetPhy)
|
||||
{
|
||||
ULONG OpMode, i;
|
||||
|
||||
if (Adapter->ChipType != DC21140)
|
||||
{
|
||||
DcWriteSia(Adapter, 0, 0, 0);
|
||||
}
|
||||
|
||||
OpMode = Adapter->OpMode;
|
||||
OpMode &= ~DC_OPMODE_MEDIA_MASK;
|
||||
OpMode |= DC_OPMODE_PORT_SELECT | DC_OPMODE_PORT_HEARTBEAT_DISABLE;
|
||||
Adapter->OpMode = OpMode;
|
||||
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, OpMode);
|
||||
|
||||
NdisStallExecution(10);
|
||||
|
||||
if (ResetPhy)
|
||||
{
|
||||
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||||
|
||||
/* Execute the GPIO reset sequence */
|
||||
if (Adapter->MiiMedia.ResetStreamLength)
|
||||
{
|
||||
/* Set the GPIO direction */
|
||||
DcWriteGpio(Adapter, Adapter->MiiMedia.SetupStream[0]);
|
||||
|
||||
for (i = 0; i < Adapter->MiiMedia.ResetStreamLength; ++i)
|
||||
{
|
||||
NdisMSleep(100);
|
||||
DcWriteGpio(Adapter, Adapter->MiiMedia.ResetStream[i]);
|
||||
}
|
||||
|
||||
/* Give the PHY some time to reset */
|
||||
NdisMSleep(5000);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the GPIO direction */
|
||||
DcWriteGpio(Adapter, Adapter->MiiMedia.SetupStream[0]);
|
||||
|
||||
/* Execute the GPIO setup sequence */
|
||||
for (i = 1; i < Adapter->MiiMedia.SetupStreamLength; ++i)
|
||||
{
|
||||
NdisStallExecution(10);
|
||||
DcWriteGpio(Adapter, Adapter->MiiMedia.SetupStream[i]);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
MediaSiaSelect(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG OpMode;
|
||||
PDC_MEDIA Media;
|
||||
|
||||
INFO_VERB("Selected media %s\n",
|
||||
MediaNumber2Str(Adapter, Adapter->MediaNumber));
|
||||
|
||||
Media = &Adapter->Media[Adapter->MediaNumber];
|
||||
|
||||
DcStopTxRxProcess(Adapter);
|
||||
|
||||
if (Adapter->ChipType != DC21041)
|
||||
{
|
||||
/* Make sure the reset pulse is wide enough */
|
||||
NdisStallExecution(100);
|
||||
DcWriteGpio(Adapter, Media->GpioCtrl);
|
||||
NdisStallExecution(100);
|
||||
DcWriteGpio(Adapter, Media->GpioData);
|
||||
}
|
||||
|
||||
DcWriteSia(Adapter, Media->Csr13, Media->Csr14, Media->Csr15);
|
||||
|
||||
NdisStallExecution(10);
|
||||
|
||||
OpMode = Adapter->OpMode;
|
||||
OpMode &= ~DC_OPMODE_MEDIA_MASK;
|
||||
OpMode |= Media->OpMode;
|
||||
Adapter->OpMode = OpMode;
|
||||
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, OpMode);
|
||||
}
|
||||
|
||||
VOID
|
||||
MediaGprSelect(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG OpMode;
|
||||
PDC_MEDIA Media;
|
||||
|
||||
INFO("Selected media %s\n", MediaNumber2Str(Adapter, Adapter->MediaNumber));
|
||||
|
||||
Media = &Adapter->Media[Adapter->MediaNumber];
|
||||
|
||||
DC_WRITE(Adapter, DcCsr12_Gpio, Media->GpioData);
|
||||
|
||||
OpMode = Adapter->OpMode;
|
||||
OpMode &= ~DC_OPMODE_MEDIA_MASK;
|
||||
OpMode |= Media->OpMode;
|
||||
Adapter->OpMode = OpMode;
|
||||
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, OpMode);
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
MediaInitDefaultMedia(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG MediaNumber)
|
||||
{
|
||||
ULONG Csr14, MiiAdvertising, MiiControl, i;
|
||||
BOOLEAN UseMii;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Media auto-detection */
|
||||
if (MediaNumber == MEDIA_AUTO)
|
||||
{
|
||||
Adapter->Flags |= DC_AUTOSENSE;
|
||||
|
||||
/* Initial value for all boards */
|
||||
Adapter->DefaultMedia = MEDIA_10T;
|
||||
|
||||
Adapter->MiiAdvertising = Adapter->MiiMedia.Advertising;
|
||||
Adapter->MiiControl = MII_CR_AUTONEG | MII_CR_AUTONEG_RESTART;
|
||||
|
||||
switch (Adapter->ChipType)
|
||||
{
|
||||
case DC21041:
|
||||
{
|
||||
/* Errata: don't enable auto-negotiation */
|
||||
if (Adapter->RevisionId < 0x20)
|
||||
break;
|
||||
|
||||
/* Advertise 10T HD and 10T FD. The chip chooses the 10T FD mode automatically */
|
||||
Adapter->Media[MEDIA_10T].Csr14 |= DC_SIA_TXRX_AUTONEG | DC_SIA_TXRX_ADV_10T_HD;
|
||||
Adapter->Media[MEDIA_10T].OpMode |= DC_OPMODE_FULL_DUPLEX;
|
||||
break;
|
||||
}
|
||||
|
||||
case DC21140:
|
||||
{
|
||||
/* Pick the default media */
|
||||
if (Adapter->Features & DC_HAS_MII)
|
||||
{
|
||||
Adapter->DefaultMedia = MEDIA_MII;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The final entry in the media list should be checked first */
|
||||
_BitScanReverse(&Adapter->DefaultMedia, Adapter->MediaBitmap);
|
||||
|
||||
/*
|
||||
* Select the first half-duplex media.
|
||||
* If you want to be able to use 21140 boards without MII in full-duplex mode,
|
||||
* you have to manually select the media.
|
||||
*/
|
||||
for (i = Adapter->DefaultMedia; i > 0; --i)
|
||||
{
|
||||
if ((Adapter->MediaBitmap & (1 << i)) && !MEDIA_IS_FD(i))
|
||||
break;
|
||||
}
|
||||
Adapter->DefaultMedia = i;
|
||||
break;
|
||||
}
|
||||
|
||||
case DC21143:
|
||||
case DC21145:
|
||||
{
|
||||
/* Pick the default media */
|
||||
if (Adapter->Features & DC_HAS_MII)
|
||||
{
|
||||
Adapter->DefaultMedia = MEDIA_MII;
|
||||
}
|
||||
else if (Adapter->MediaBitmap & (1 << MEDIA_10T))
|
||||
{
|
||||
/* Start at 10mbps to do internal auto-negotiation */
|
||||
Adapter->DefaultMedia = MEDIA_10T;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The final entry in the media list should be checked first */
|
||||
_BitScanReverse(&Adapter->DefaultMedia, Adapter->MediaBitmap);
|
||||
}
|
||||
|
||||
/* Enable the PCS function to do 100mbps parallel detection */
|
||||
if (Adapter->SymAdvertising & MII_ADV_100)
|
||||
{
|
||||
Adapter->Media[MEDIA_10T].OpMode |= DC_OPMODE_PORT_PCS;
|
||||
Adapter->Media[MEDIA_10T_FD].OpMode |= DC_OPMODE_PORT_PCS;
|
||||
Adapter->Media[MEDIA_AUI].OpMode |= DC_OPMODE_PORT_PCS;
|
||||
Adapter->Media[MEDIA_BNC].OpMode |= DC_OPMODE_PORT_PCS;
|
||||
Adapter->Media[MEDIA_HMR].OpMode |= DC_OPMODE_PORT_PCS;
|
||||
}
|
||||
|
||||
Csr14 = DC_SIA_TXRX_AUTONEG;
|
||||
|
||||
if (Adapter->SymAdvertising & MII_ADV_10T_HD)
|
||||
Csr14 |= DC_SIA_TXRX_ADV_10T_HD;
|
||||
|
||||
/* When NWay is turned on, the FDX bit advertises 10T FD */
|
||||
if (Adapter->SymAdvertising & MII_ADV_10T_FD)
|
||||
Adapter->Media[MEDIA_10T].OpMode |= DC_OPMODE_FULL_DUPLEX;
|
||||
|
||||
if (Adapter->SymAdvertising & MII_ADV_100T_HD)
|
||||
Csr14 |= DC_SIA_TXRX_ADV_100TX_HD;
|
||||
|
||||
if (Adapter->SymAdvertising & MII_ADV_100T_FD)
|
||||
Csr14 |= DC_SIA_TXRX_ADV_100TX_FD;
|
||||
|
||||
if (Adapter->SymAdvertising & MII_ADV_100T4)
|
||||
Csr14 |= DC_SIA_TXRX_ADV_100T4;
|
||||
|
||||
/* Advertise the PHY capability */
|
||||
Adapter->Media[MEDIA_10T].Csr14 |= Csr14;
|
||||
|
||||
/* This media may use GPIO data different from the 10T HD */
|
||||
Adapter->Media[MEDIA_10T_FD].Csr14 |= Csr14;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* Forced speed and duplex */
|
||||
{
|
||||
UseMii = FALSE;
|
||||
|
||||
if (Adapter->Features & DC_HAS_MII)
|
||||
{
|
||||
if (!MEDIA_MII_OVERRIDE(MediaNumber))
|
||||
{
|
||||
UseMii = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!UseMii)
|
||||
{
|
||||
Adapter->DefaultMedia = MediaNumber;
|
||||
|
||||
if (MEDIA_IS_10T(MediaNumber))
|
||||
{
|
||||
Adapter->InterruptMask &= ~DC_IRQ_LINK_CHANGED;
|
||||
Adapter->LinkStateChangeMask &= ~DC_IRQ_LINK_CHANGED;
|
||||
}
|
||||
|
||||
if (MEDIA_IS_100(MediaNumber))
|
||||
{
|
||||
Adapter->InterruptMask &= ~(DC_IRQ_LINK_FAIL | DC_IRQ_LINK_PASS);
|
||||
Adapter->LinkStateChangeMask &= ~(DC_IRQ_LINK_FAIL | DC_IRQ_LINK_PASS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Adapter->DefaultMedia = MEDIA_MII;
|
||||
|
||||
switch (MediaNumber)
|
||||
{
|
||||
case MEDIA_10T:
|
||||
MiiAdvertising = MII_ADV_10T_HD;
|
||||
break;
|
||||
case MEDIA_10T_FD:
|
||||
MiiAdvertising = MII_ADV_10T_FD;
|
||||
MiiControl = MII_CR_FULL_DUPLEX;
|
||||
break;
|
||||
case MEDIA_100TX_HD:
|
||||
MiiAdvertising = MII_ADV_100T_HD;
|
||||
MiiControl = MII_CR_SPEED_SELECTION;
|
||||
break;
|
||||
case MEDIA_100TX_FD:
|
||||
MiiAdvertising = MII_ADV_100T_FD;
|
||||
MiiControl = MII_CR_FULL_DUPLEX | MII_CR_SPEED_SELECTION;
|
||||
break;
|
||||
case MEDIA_100T4:
|
||||
MiiAdvertising = MII_ADV_100T4 | MII_CR_SPEED_SELECTION;
|
||||
break;
|
||||
|
||||
default:
|
||||
MiiAdvertising = 0;
|
||||
MiiControl = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MiiControl & MII_CR_SPEED_SELECTION)
|
||||
Adapter->LinkSpeedMbps = 100;
|
||||
else
|
||||
Adapter->LinkSpeedMbps = 10;
|
||||
|
||||
Adapter->MiiAdvertising = MiiAdvertising;
|
||||
Adapter->MiiControl = MiiControl;
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Default media is %s\n", MediaNumber2Str(Adapter, Adapter->DefaultMedia));
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
MediaInitOpMode2114x(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
Adapter->Media[MEDIA_10T ].OpMode = 0;
|
||||
Adapter->Media[MEDIA_BNC ].OpMode = 0;
|
||||
Adapter->Media[MEDIA_AUI ].OpMode = 0;
|
||||
Adapter->Media[MEDIA_100TX_HD].OpMode = DC_OPMODE_PORT_SELECT |
|
||||
DC_OPMODE_PORT_HEARTBEAT_DISABLE;
|
||||
Adapter->Media[MEDIA_10T_FD ].OpMode = DC_OPMODE_FULL_DUPLEX;
|
||||
Adapter->Media[MEDIA_100TX_FD].OpMode = DC_OPMODE_PORT_SELECT | DC_OPMODE_FULL_DUPLEX |
|
||||
DC_OPMODE_PORT_HEARTBEAT_DISABLE;
|
||||
Adapter->Media[MEDIA_100T4 ].OpMode = DC_OPMODE_PORT_SELECT |
|
||||
DC_OPMODE_PORT_HEARTBEAT_DISABLE;
|
||||
Adapter->Media[MEDIA_100FX_HD].OpMode = DC_OPMODE_PORT_SELECT |
|
||||
DC_OPMODE_PORT_HEARTBEAT_DISABLE |
|
||||
DC_OPMODE_PORT_PCS;
|
||||
Adapter->Media[MEDIA_100FX_FD].OpMode = DC_OPMODE_PORT_SELECT | DC_OPMODE_FULL_DUPLEX |
|
||||
DC_OPMODE_PORT_HEARTBEAT_DISABLE |
|
||||
DC_OPMODE_PORT_PCS;
|
||||
Adapter->Media[MEDIA_HMR ].OpMode = DC_OPMODE_PORT_HEARTBEAT_DISABLE;
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
MediaInitMediaList(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
/*
|
||||
* Set the default internal values for the SIA/SYM operating modes.
|
||||
* The SROM parsing code may later overwrite them.
|
||||
*/
|
||||
switch (Adapter->ChipType)
|
||||
{
|
||||
case DC21040:
|
||||
{
|
||||
Adapter->Media[MEDIA_10T].Csr13 = 0x8F01;
|
||||
Adapter->Media[MEDIA_10T].Csr14 = 0xFFFF;
|
||||
Adapter->Media[MEDIA_10T].Csr15 = 0x0000;
|
||||
|
||||
Adapter->Media[MEDIA_BNC].Csr13 = 0x8F09;
|
||||
Adapter->Media[MEDIA_BNC].Csr14 = 0x0705;
|
||||
Adapter->Media[MEDIA_BNC].Csr15 = 0x0006;
|
||||
|
||||
Adapter->Media[MEDIA_10T_FD].Csr13 = 0x8F01;
|
||||
Adapter->Media[MEDIA_10T_FD].Csr14 = 0xFFFD;
|
||||
Adapter->Media[MEDIA_10T_FD].Csr15 = 0x0000;
|
||||
Adapter->Media[MEDIA_10T_FD].OpMode = DC_OPMODE_FULL_DUPLEX;
|
||||
break;
|
||||
}
|
||||
|
||||
case DC21041:
|
||||
{
|
||||
Adapter->Media[MEDIA_10T].Csr13 = 0xEF01;
|
||||
Adapter->Media[MEDIA_10T].Csr14 = 0xFF3F;
|
||||
Adapter->Media[MEDIA_10T].Csr15 = 0x0008;
|
||||
|
||||
Adapter->Media[MEDIA_BNC].Csr13 = 0xEF09;
|
||||
Adapter->Media[MEDIA_BNC].Csr14 = 0xF7FD;
|
||||
Adapter->Media[MEDIA_BNC].Csr15 = 0x0006;
|
||||
|
||||
Adapter->Media[MEDIA_AUI].Csr13 = 0xEF09;
|
||||
Adapter->Media[MEDIA_AUI].Csr14 = 0xF7FD;
|
||||
Adapter->Media[MEDIA_AUI].Csr15 = 0x000E;
|
||||
|
||||
Adapter->Media[MEDIA_10T_HD].Csr13 = 0xEF01;
|
||||
Adapter->Media[MEDIA_10T_HD].Csr14 = 0x7F3F;
|
||||
Adapter->Media[MEDIA_10T_HD].Csr15 = 0x0008;
|
||||
|
||||
Adapter->Media[MEDIA_10T_FD].Csr13 = 0xEF01;
|
||||
Adapter->Media[MEDIA_10T_FD].Csr14 = 0x7F3D;
|
||||
Adapter->Media[MEDIA_10T_FD].Csr15 = 0x0008;
|
||||
Adapter->Media[MEDIA_10T_FD].OpMode = DC_OPMODE_FULL_DUPLEX;
|
||||
break;
|
||||
}
|
||||
|
||||
case DC21140:
|
||||
{
|
||||
MediaInitOpMode2114x(Adapter);
|
||||
break;
|
||||
}
|
||||
|
||||
case DC21143:
|
||||
case DC21145:
|
||||
{
|
||||
Adapter->Media[MEDIA_10T].Csr13 = 0x0001;
|
||||
Adapter->Media[MEDIA_10T].Csr14 = 0x7F3F;
|
||||
Adapter->Media[MEDIA_10T].Csr15 = 0x0008;
|
||||
|
||||
Adapter->Media[MEDIA_BNC].Csr13 = 0x0009;
|
||||
Adapter->Media[MEDIA_BNC].Csr14 = 0x0705;
|
||||
Adapter->Media[MEDIA_BNC].Csr15 = 0x0006;
|
||||
|
||||
Adapter->Media[MEDIA_AUI].Csr13 = 0x0009;
|
||||
Adapter->Media[MEDIA_AUI].Csr14 = 0x0705;
|
||||
Adapter->Media[MEDIA_AUI].Csr15 = 0x000E;
|
||||
|
||||
Adapter->Media[MEDIA_10T_FD].Csr13 = 0x0001;
|
||||
Adapter->Media[MEDIA_10T_FD].Csr14 = 0x7F3D;
|
||||
Adapter->Media[MEDIA_10T_FD].Csr15 = 0x0008;
|
||||
|
||||
Adapter->Media[MEDIA_HMR].Csr13 = 0x0009;
|
||||
Adapter->Media[MEDIA_HMR].Csr14 = 0x0505;
|
||||
Adapter->Media[MEDIA_HMR].Csr15 = 0x0010;
|
||||
|
||||
MediaInitOpMode2114x(Adapter);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
127
drivers/network/dd/dc21x4/media.h
Normal file
127
drivers/network/dd/dc21x4/media.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Media support header file
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct _DC_MEDIA
|
||||
{
|
||||
ULONG OpMode;
|
||||
|
||||
USHORT GpioCtrl;
|
||||
USHORT GpioData;
|
||||
|
||||
union
|
||||
{
|
||||
struct _DC_MEDIA_SIA_DATA
|
||||
{
|
||||
ULONG Csr13;
|
||||
ULONG Csr14;
|
||||
ULONG Csr15;
|
||||
};
|
||||
|
||||
struct _DC_MEDIA_GPR_DATA
|
||||
{
|
||||
ULONG LinkMask;
|
||||
ULONG Polarity;
|
||||
};
|
||||
};
|
||||
} DC_MEDIA, *PDC_MEDIA;
|
||||
|
||||
typedef struct _DC_MII_MEDIA
|
||||
{
|
||||
UCHAR SetupStreamLength;
|
||||
UCHAR ResetStreamLength;
|
||||
USHORT Advertising;
|
||||
USHORT SetupStream[SROM_MAX_STREAM_REGS + 1]; // +1 for GPIO direction (21140)
|
||||
USHORT ResetStream[SROM_MAX_STREAM_REGS];
|
||||
} DC_MII_MEDIA, *PDC_MII_MEDIA;
|
||||
|
||||
/*
|
||||
* SROM-defined media values
|
||||
*/
|
||||
#define MEDIA_10T 0
|
||||
#define MEDIA_BNC 1
|
||||
#define MEDIA_AUI 2
|
||||
#define MEDIA_100TX_HD 3
|
||||
#define MEDIA_10T_HD MEDIA_100TX_HD /* 21041 only */
|
||||
#define MEDIA_10T_FD 4
|
||||
#define MEDIA_100TX_FD 5
|
||||
#define MEDIA_100T4 6
|
||||
#define MEDIA_100FX_HD 7
|
||||
#define MEDIA_100FX_FD 8
|
||||
#define MEDIA_HMR 9
|
||||
#define MEDIA_LIST_MAX 10
|
||||
|
||||
/*
|
||||
* Registry configuration
|
||||
*/
|
||||
#define MEDIA_AUTO MEDIA_LIST_MAX
|
||||
|
||||
/*
|
||||
* Extra codes
|
||||
*/
|
||||
#define MEDIA_MII MEDIA_LIST_MAX
|
||||
#define MEDIA_MAX (MEDIA_LIST_MAX + 1)
|
||||
|
||||
#define MEDIA_MII_OVERRIDE_MASK \
|
||||
((1 << MEDIA_AUI) | \
|
||||
(1 << MEDIA_BNC) | \
|
||||
(1 << MEDIA_100FX_HD) | \
|
||||
(1 << MEDIA_100FX_FD) | \
|
||||
(1 << MEDIA_HMR))
|
||||
|
||||
#define MEDIA_FD_MASK \
|
||||
((1 << MEDIA_10T_FD) | \
|
||||
(1 << MEDIA_100TX_FD) | \
|
||||
(1 << MEDIA_100FX_FD))
|
||||
|
||||
#define MEDIA_AUI_BNC_MASK \
|
||||
((1 << MEDIA_AUI) | \
|
||||
(1 << MEDIA_BNC))
|
||||
|
||||
#define MEDIA_10T_MASK \
|
||||
((1 << MEDIA_10T) | \
|
||||
(1 << MEDIA_10T_FD))
|
||||
|
||||
#define MEDIA_100_MASK \
|
||||
((1 << MEDIA_100TX_HD) | \
|
||||
(1 << MEDIA_100TX_FD) | \
|
||||
(1 << MEDIA_100T4) | \
|
||||
(1 << MEDIA_100FX_HD) | \
|
||||
(1 << MEDIA_100FX_FD))
|
||||
|
||||
#define MEDIA_FX_MASK \
|
||||
((1 << MEDIA_100FX_HD) | \
|
||||
(1 << MEDIA_100FX_FD))
|
||||
|
||||
/* Specifying this media code override the default MII selection */
|
||||
#define MEDIA_MII_OVERRIDE(MediaNumber) \
|
||||
(((1 << (MediaNumber)) & MEDIA_MII_OVERRIDE_MASK) != 0)
|
||||
|
||||
/* Full-duplex media */
|
||||
#define MEDIA_IS_FD(MediaNumber) \
|
||||
(((1 << (MediaNumber)) & MEDIA_FD_MASK) != 0)
|
||||
|
||||
/* AUI or BNC media */
|
||||
#define MEDIA_IS_AUI_BNC(MediaNumber) \
|
||||
(((1 << (MediaNumber)) & MEDIA_AUI_BNC_MASK) != 0)
|
||||
|
||||
/* 10Base-T media */
|
||||
#define MEDIA_IS_10T(MediaNumber) \
|
||||
(((1 << (MediaNumber)) & MEDIA_10T_MASK) != 0)
|
||||
|
||||
/* 100mbps media */
|
||||
#define MEDIA_IS_100(MediaNumber) \
|
||||
(((1 << (MediaNumber)) & MEDIA_100_MASK) != 0)
|
||||
|
||||
/* 100Base-FX media */
|
||||
#define MEDIA_IS_FX(MediaNumber) \
|
||||
(((1 << (MediaNumber)) & MEDIA_FX_MASK) != 0)
|
||||
|
||||
/* Forced speed and duplex */
|
||||
#define MEDIA_IS_FIXED(Adapter) \
|
||||
(((Adapter)->Flags & DC_AUTOSENSE) == 0)
|
143
drivers/network/dd/dc21x4/media040.c
Normal file
143
drivers/network/dd/dc21x4/media040.c
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: 21040 media support code
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
MediaLinkStateChange21040(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG InterruptStatus)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(InterruptStatus);
|
||||
|
||||
INFO_VERB("Link failed, CSR12 %08lx\n", DC_READ(Adapter, DcCsr12_SiaStatus));
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
/* Start the media timer when the 10Base-T link has changed state */
|
||||
if (Adapter->MediaNumber != MEDIA_BNC)
|
||||
{
|
||||
MediaIndicateConnect(Adapter, FALSE);
|
||||
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, 3000);
|
||||
}
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MediaMonitor21040Dpc(
|
||||
_In_ PVOID SystemSpecific1,
|
||||
_In_ PVOID FunctionContext,
|
||||
_In_ PVOID SystemSpecific2,
|
||||
_In_ PVOID SystemSpecific3)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = FunctionContext;
|
||||
BOOLEAN LinkUp, Report, RunAgain;
|
||||
|
||||
UNREFERENCED_PARAMETER(SystemSpecific1);
|
||||
UNREFERENCED_PARAMETER(SystemSpecific2);
|
||||
UNREFERENCED_PARAMETER(SystemSpecific3);
|
||||
|
||||
if (!(Adapter->Flags & DC_ACTIVE))
|
||||
return;
|
||||
|
||||
LinkUp = FALSE;
|
||||
Report = FALSE;
|
||||
RunAgain = TRUE;
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
if (Adapter->MediaNumber != MEDIA_BNC)
|
||||
{
|
||||
ULONG SiaStatus = DC_READ(Adapter, DcCsr12_SiaStatus);
|
||||
|
||||
Report = TRUE;
|
||||
LinkUp = !(SiaStatus & (DC_SIA_STATUS_NETWORK_CONNECTION_ERROR |
|
||||
DC_SIA_STATUS_10T_LINK_FAIL));
|
||||
|
||||
if (!LinkUp)
|
||||
{
|
||||
/* Select the other port */
|
||||
if (!MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
Adapter->MediaNumber = MEDIA_BNC;
|
||||
|
||||
DcWriteSia(Adapter,
|
||||
Adapter->Media[MEDIA_BNC].Csr13,
|
||||
Adapter->Media[MEDIA_BNC].Csr14,
|
||||
Adapter->Media[MEDIA_BNC].Csr15);
|
||||
|
||||
Adapter->LastReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait until the next link change event */
|
||||
RunAgain = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG ReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
|
||||
|
||||
if (!(Adapter->ModeFlags & DC_MODE_TEST_PACKET))
|
||||
{
|
||||
/* Check for any received packets */
|
||||
if (ReceiveActivity != Adapter->LastReceiveActivity)
|
||||
{
|
||||
LinkUp = TRUE;
|
||||
Report = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send a loopback packet */
|
||||
NdisDprAcquireSpinLock(&Adapter->SendLock);
|
||||
DcTestPacket(Adapter);
|
||||
NdisDprReleaseSpinLock(&Adapter->SendLock);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Adapter->ModeFlags &= ~DC_MODE_TEST_PACKET;
|
||||
|
||||
LinkUp = !!Adapter->MediaTestStatus;
|
||||
Report = TRUE;
|
||||
|
||||
/* Select the other port */
|
||||
if (!LinkUp && !MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
Adapter->MediaNumber = MEDIA_10T;
|
||||
|
||||
DcWriteSia(Adapter,
|
||||
Adapter->Media[MEDIA_10T].Csr13,
|
||||
Adapter->Media[MEDIA_10T].Csr14,
|
||||
Adapter->Media[MEDIA_10T].Csr15);
|
||||
}
|
||||
}
|
||||
Adapter->LastReceiveActivity = ReceiveActivity;
|
||||
}
|
||||
|
||||
if (Report)
|
||||
{
|
||||
MediaIndicateConnect(Adapter, LinkUp);
|
||||
}
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
|
||||
if (RunAgain)
|
||||
{
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, LinkUp ? 6000 : 3000);
|
||||
}
|
||||
}
|
222
drivers/network/dd/dc21x4/media041.c
Normal file
222
drivers/network/dd/dc21x4/media041.c
Normal file
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: 21041 media support code
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
MediaLinkStateChange21041(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG InterruptStatus)
|
||||
{
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
if (InterruptStatus & DC_IRQ_LINK_PASS)
|
||||
{
|
||||
INFO_VERB("Link passed, CSR12 %08lx\n", DC_READ(Adapter, DcCsr12_SiaStatus));
|
||||
|
||||
/* 10Base-T is the active port now */
|
||||
if (MEDIA_IS_AUI_BNC(Adapter->MediaNumber))
|
||||
{
|
||||
/* Switch to TP medium */
|
||||
if (!MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
Adapter->MediaNumber = MEDIA_10T;
|
||||
MediaSiaSelect(Adapter);
|
||||
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
/* 10Base-T link is up */
|
||||
if (!MEDIA_IS_AUI_BNC(Adapter->MediaNumber))
|
||||
{
|
||||
MediaIndicateConnect(Adapter, TRUE);
|
||||
}
|
||||
}
|
||||
else // DC_IRQ_LINK_FAIL
|
||||
{
|
||||
INFO_VERB("Link failed, CSR12 %08lx\n", DC_READ(Adapter, DcCsr12_SiaStatus));
|
||||
|
||||
/* 10Base-T link is down */
|
||||
if (!MEDIA_IS_AUI_BNC(Adapter->MediaNumber))
|
||||
{
|
||||
MediaIndicateConnect(Adapter, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
Media041SelectNextMedia(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
if (Adapter->MediaNumber == MEDIA_AUI)
|
||||
Adapter->ModeFlags |= DC_MODE_AUI_FAILED;
|
||||
else if (Adapter->MediaNumber == MEDIA_BNC)
|
||||
Adapter->ModeFlags |= DC_MODE_BNC_FAILED;
|
||||
|
||||
if ((Adapter->ModeFlags & (DC_MODE_AUI_FAILED | DC_MODE_BNC_FAILED)) ==
|
||||
(DC_MODE_AUI_FAILED | DC_MODE_BNC_FAILED))
|
||||
{
|
||||
Adapter->MediaNumber = MEDIA_10T;
|
||||
}
|
||||
else
|
||||
{
|
||||
Adapter->MediaNumber = (MEDIA_BNC + MEDIA_AUI) - Adapter->MediaNumber;
|
||||
}
|
||||
|
||||
MediaSiaSelect(Adapter);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MediaMonitor21041Dpc(
|
||||
_In_ PVOID SystemSpecific1,
|
||||
_In_ PVOID FunctionContext,
|
||||
_In_ PVOID SystemSpecific2,
|
||||
_In_ PVOID SystemSpecific3)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = FunctionContext;
|
||||
BOOLEAN LinkUp, Report;
|
||||
ULONG DelayMs, SiaStatus;
|
||||
|
||||
UNREFERENCED_PARAMETER(SystemSpecific1);
|
||||
UNREFERENCED_PARAMETER(SystemSpecific2);
|
||||
UNREFERENCED_PARAMETER(SystemSpecific3);
|
||||
|
||||
if (!(Adapter->Flags & DC_ACTIVE))
|
||||
return;
|
||||
|
||||
Report = FALSE;
|
||||
DelayMs = 5000;
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
SiaStatus = DC_READ(Adapter, DcCsr12_SiaStatus);
|
||||
|
||||
if (MEDIA_IS_AUI_BNC(Adapter->MediaNumber))
|
||||
{
|
||||
if ((Adapter->ModeFlags & DC_MODE_PORT_AUTOSENSE))
|
||||
{
|
||||
Adapter->ModeFlags &= ~DC_MODE_PORT_AUTOSENSE;
|
||||
|
||||
/* Select the other port */
|
||||
if (!(SiaStatus & DC_SIA_STATUS_SELECTED_PORT_ACTIVITY))
|
||||
{
|
||||
Adapter->MediaNumber = MEDIA_BNC;
|
||||
MediaSiaSelect(Adapter);
|
||||
}
|
||||
|
||||
DelayMs = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG ReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
|
||||
|
||||
if (!(Adapter->ModeFlags & DC_MODE_TEST_PACKET))
|
||||
{
|
||||
if ((Adapter->MediaNumber == MEDIA_AUI) &&
|
||||
(SiaStatus & DC_SIA_STATUS_SELECTED_PORT_ACTIVITY))
|
||||
{
|
||||
/* Clear the selected port activity bit */
|
||||
DC_WRITE(Adapter, DcCsr12_SiaStatus, DC_SIA_STATUS_SELECTED_PORT_ACTIVITY);
|
||||
|
||||
LinkUp = TRUE;
|
||||
Report = TRUE;
|
||||
}
|
||||
/* Check for any received packets */
|
||||
else if (ReceiveActivity != Adapter->LastReceiveActivity)
|
||||
{
|
||||
LinkUp = TRUE;
|
||||
Report = TRUE;
|
||||
|
||||
DelayMs = 3000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send a loopback packet */
|
||||
NdisDprAcquireSpinLock(&Adapter->SendLock);
|
||||
DcTestPacket(Adapter);
|
||||
NdisDprReleaseSpinLock(&Adapter->SendLock);
|
||||
|
||||
DelayMs = 3000;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Adapter->ModeFlags &= ~DC_MODE_TEST_PACKET;
|
||||
|
||||
LinkUp = !!Adapter->MediaTestStatus;
|
||||
Report = TRUE;
|
||||
|
||||
/* Select the other port */
|
||||
if (!LinkUp && !MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
Media041SelectNextMedia(Adapter);
|
||||
|
||||
DelayMs = 3000;
|
||||
}
|
||||
}
|
||||
Adapter->LastReceiveActivity = ReceiveActivity;
|
||||
}
|
||||
}
|
||||
else // 10Base-T
|
||||
{
|
||||
Report = TRUE;
|
||||
LinkUp = !(SiaStatus & (DC_SIA_STATUS_NETWORK_CONNECTION_ERROR |
|
||||
DC_SIA_STATUS_10T_LINK_FAIL));
|
||||
|
||||
if (!LinkUp)
|
||||
{
|
||||
DelayMs = 3000;
|
||||
|
||||
/* Select the AUI or BNC port */
|
||||
if (!MEDIA_IS_FIXED(Adapter) && (Adapter->MediaBitmap & MEDIA_AUI_BNC_MASK))
|
||||
{
|
||||
Adapter->ModeFlags &= ~(DC_MODE_AUI_FAILED |
|
||||
DC_MODE_BNC_FAILED |
|
||||
DC_MODE_TEST_PACKET);
|
||||
|
||||
if (SiaStatus & DC_SIA_STATUS_NONSEL_PORT_ACTIVITY)
|
||||
{
|
||||
Adapter->MediaNumber = MEDIA_AUI;
|
||||
Adapter->ModeFlags |= DC_MODE_PORT_AUTOSENSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Adapter->MediaNumber = MEDIA_BNC;
|
||||
}
|
||||
MediaSiaSelect(Adapter);
|
||||
|
||||
Adapter->LastReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
|
||||
|
||||
/* Clear the port activity bits */
|
||||
DC_WRITE(Adapter, DcCsr12_SiaStatus, DC_SIA_STATUS_SELECTED_PORT_ACTIVITY |
|
||||
DC_SIA_STATUS_NONSEL_PORT_ACTIVITY);
|
||||
|
||||
DelayMs = 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Report)
|
||||
{
|
||||
MediaIndicateConnect(Adapter, LinkUp);
|
||||
}
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, DelayMs);
|
||||
}
|
136
drivers/network/dd/dc21x4/media140.c
Normal file
136
drivers/network/dd/dc21x4/media140.c
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: 21140 media support code
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
MediaGprCheckLink(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG GpioData;
|
||||
PDC_MEDIA Media;
|
||||
|
||||
Media = &Adapter->Media[Adapter->MediaNumber];
|
||||
|
||||
/* No media activity indicator */
|
||||
if (Media->LinkMask == 0)
|
||||
{
|
||||
TRACE("No activity indicator\n");
|
||||
|
||||
/* Assume we have a link */
|
||||
if (MEDIA_IS_FIXED(Adapter))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GpioData = DC_READ(Adapter, DcCsr12_Gpio);
|
||||
|
||||
TRACE("CSR12 %08lx\n", GpioData);
|
||||
|
||||
/* This media supports link indication via GPIO pins */
|
||||
return !!((GpioData & Media->LinkMask) ^ Media->Polarity);
|
||||
}
|
||||
|
||||
static
|
||||
ULONG
|
||||
MediaGprNextMedia(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
/* No half-duplex media in the media list */
|
||||
if (!(Adapter->MediaBitmap & ~MEDIA_FD_MASK))
|
||||
{
|
||||
return Adapter->MediaNumber;
|
||||
}
|
||||
|
||||
/* Find the next half-duplex media */
|
||||
i = Adapter->MediaNumber;
|
||||
while (TRUE)
|
||||
{
|
||||
/* We have reached the end of the media list, try the first media */
|
||||
if (i == 0)
|
||||
{
|
||||
_BitScanReverse(&i, Adapter->MediaBitmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
--i;
|
||||
}
|
||||
|
||||
if ((Adapter->MediaBitmap & (1 << i)) && !MEDIA_IS_FD(i))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MediaMonitor21140Dpc(
|
||||
_In_ PVOID SystemSpecific1,
|
||||
_In_ PVOID FunctionContext,
|
||||
_In_ PVOID SystemSpecific2,
|
||||
_In_ PVOID SystemSpecific3)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = FunctionContext;
|
||||
ULONG DelayMs, MediaNumber;
|
||||
BOOLEAN LinkUp;
|
||||
|
||||
UNREFERENCED_PARAMETER(SystemSpecific1);
|
||||
UNREFERENCED_PARAMETER(SystemSpecific2);
|
||||
UNREFERENCED_PARAMETER(SystemSpecific3);
|
||||
|
||||
if (!(Adapter->Flags & DC_ACTIVE))
|
||||
return;
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
if (Adapter->MediaNumber == MEDIA_MII)
|
||||
{
|
||||
LinkUp = MediaMiiCheckLink(Adapter);
|
||||
|
||||
DelayMs = 5000;
|
||||
}
|
||||
else
|
||||
{
|
||||
LinkUp = MediaGprCheckLink(Adapter);
|
||||
|
||||
/* This media is unconnected, try the next media */
|
||||
if (!LinkUp && !MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
MediaNumber = MediaGprNextMedia(Adapter);
|
||||
|
||||
if (Adapter->MediaNumber != MediaNumber)
|
||||
{
|
||||
Adapter->MediaNumber = MediaNumber;
|
||||
MediaGprSelect(Adapter);
|
||||
}
|
||||
|
||||
DelayMs = 3000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we are forcing media, then we need to poll the media less frequently */
|
||||
DelayMs = 5000;
|
||||
}
|
||||
}
|
||||
|
||||
MediaIndicateConnect(Adapter, LinkUp);
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, DelayMs);
|
||||
}
|
510
drivers/network/dd/dc21x4/media143.c
Normal file
510
drivers/network/dd/dc21x4/media143.c
Normal file
|
@ -0,0 +1,510 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: 21142/21143/21145 media support code
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
Media143SelectNextSerialMedia(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG MediaNumber;
|
||||
|
||||
MediaNumber = Adapter->MediaNumber;
|
||||
|
||||
/* The HMR media isn't checked as HMR boards use it instead of AUI and BNC */
|
||||
if (MediaNumber == MEDIA_AUI || MediaNumber == MEDIA_BNC)
|
||||
{
|
||||
if (MediaNumber == MEDIA_AUI)
|
||||
Adapter->ModeFlags |= DC_MODE_AUI_FAILED;
|
||||
else if (MediaNumber == MEDIA_BNC)
|
||||
Adapter->ModeFlags |= DC_MODE_BNC_FAILED;
|
||||
|
||||
if ((Adapter->ModeFlags & (DC_MODE_AUI_FAILED | DC_MODE_BNC_FAILED)) !=
|
||||
(DC_MODE_AUI_FAILED | DC_MODE_BNC_FAILED))
|
||||
{
|
||||
MediaNumber = (MEDIA_BNC + MEDIA_AUI) - MediaNumber;
|
||||
|
||||
if (Adapter->MediaBitmap & (1 << MediaNumber))
|
||||
{
|
||||
Adapter->MediaNumber = MediaNumber;
|
||||
MediaSiaSelect(Adapter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Adapter->Features & DC_HAS_MII)
|
||||
{
|
||||
Adapter->MediaNumber = MEDIA_MII;
|
||||
|
||||
DcStopTxRxProcess(Adapter);
|
||||
MediaSelectMiiPort(Adapter, FALSE);
|
||||
MediaMiiSelect(Adapter);
|
||||
}
|
||||
else
|
||||
{
|
||||
Adapter->MediaNumber = MEDIA_10T;
|
||||
MediaSiaSelect(Adapter);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
Media143SelectNextMedia(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG SiaStatus)
|
||||
{
|
||||
ULONG MediaBitmap, MediaNumber;
|
||||
|
||||
MediaIndicateConnect(Adapter, FALSE);
|
||||
|
||||
MediaBitmap = Adapter->MediaBitmap;
|
||||
|
||||
if (MediaBitmap & (1 << MEDIA_HMR))
|
||||
{
|
||||
MediaNumber = MEDIA_HMR;
|
||||
}
|
||||
else if ((MediaBitmap & MEDIA_AUI_BNC_MASK) == MEDIA_AUI_BNC_MASK)
|
||||
{
|
||||
if (SiaStatus & DC_SIA_STATUS_AUI_ACTIVITY)
|
||||
{
|
||||
MediaNumber = MEDIA_AUI;
|
||||
}
|
||||
else
|
||||
{
|
||||
MediaNumber = MEDIA_BNC;
|
||||
}
|
||||
}
|
||||
else if (MediaBitmap & (1 << MEDIA_AUI))
|
||||
{
|
||||
MediaNumber = MEDIA_AUI;
|
||||
}
|
||||
else if (MediaBitmap & (1 << MEDIA_BNC))
|
||||
{
|
||||
MediaNumber = MEDIA_BNC;
|
||||
}
|
||||
else
|
||||
{
|
||||
MediaNumber = MEDIA_10T;
|
||||
}
|
||||
|
||||
Adapter->ModeFlags &= ~DC_MODE_AUTONEG_MASK;
|
||||
Adapter->ModeFlags |= DC_MODE_AUTONEG_NONE;
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, 3000);
|
||||
|
||||
if (Adapter->MediaNumber != MediaNumber)
|
||||
{
|
||||
Adapter->MediaNumber = MediaNumber;
|
||||
MediaSiaSelect(Adapter);
|
||||
}
|
||||
|
||||
Adapter->ModeFlags &= ~(DC_MODE_TEST_PACKET |
|
||||
DC_MODE_AUI_FAILED |
|
||||
DC_MODE_BNC_FAILED);
|
||||
Adapter->LastReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
Media143Handle10LinkFail(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG SiaStatus)
|
||||
{
|
||||
INFO_VERB("Link failed, CSR12 %08lx\n", SiaStatus);
|
||||
|
||||
/* 10Base-T link is down */
|
||||
MediaIndicateConnect(Adapter, FALSE);
|
||||
|
||||
/* Select the other port */
|
||||
if (!MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
Media143SelectNextMedia(Adapter, SiaStatus);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
Media143Handle10LinkPass(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG SiaStatus)
|
||||
{
|
||||
INFO_VERB("Link passed, CSR12 %08lx\n", SiaStatus);
|
||||
|
||||
/* 10Base-T is the active port now */
|
||||
if (!MEDIA_IS_10T(Adapter->MediaNumber))
|
||||
{
|
||||
/* Switch to TP medium */
|
||||
if (!MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
Adapter->MediaNumber = MEDIA_10T;
|
||||
MediaSiaSelect(Adapter);
|
||||
|
||||
/* Wait for a link pass interrupt to signal the link test completed */
|
||||
Adapter->ModeFlags &= ~DC_MODE_AUTONEG_MASK;
|
||||
Adapter->ModeFlags |= DC_MODE_AUTONEG_WAIT_INTERRUPT;
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, 3000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 10Base-T link is up */
|
||||
MediaIndicateConnect(Adapter, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
Media143Handle100LinkChange(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG SiaStatus)
|
||||
{
|
||||
BOOLEAN LinkUp;
|
||||
|
||||
INFO_VERB("Link changed, CSR12 %08lx\n", SiaStatus);
|
||||
|
||||
LinkUp = !(SiaStatus & DC_SIA_STATUS_100T_LINK_FAIL);
|
||||
|
||||
if (MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
MediaIndicateConnect(Adapter, LinkUp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Select the other port */
|
||||
if (!LinkUp)
|
||||
{
|
||||
Media143SelectNextMedia(Adapter, SiaStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ignore this hint */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
Media143HandleNWayComplete(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG SiaStatus)
|
||||
{
|
||||
ULONG MediaNumber, AdvLpa;
|
||||
|
||||
/* Select media according to auto-negotiation result */
|
||||
if (SiaStatus & DC_SIA_STATUS_LP_AUTONED_SUPPORTED)
|
||||
{
|
||||
INFO_VERB("Auto-negotiation has completed, LPA %08lx ADV %08lx\n",
|
||||
SiaStatus, Adapter->SymAdvertising);
|
||||
|
||||
AdvLpa = (SiaStatus >> DC_SIA_STATUS_LP_CODE_WORD_SHIFT) & Adapter->SymAdvertising;
|
||||
if (AdvLpa & MII_ADV_100T_FD)
|
||||
{
|
||||
MediaNumber = MEDIA_100TX_FD;
|
||||
}
|
||||
else if (AdvLpa & MII_ADV_100T4)
|
||||
{
|
||||
MediaNumber = MEDIA_100T4;
|
||||
}
|
||||
else if (AdvLpa & MII_ADV_100T_HD)
|
||||
{
|
||||
MediaNumber = MEDIA_100TX_HD;
|
||||
}
|
||||
else if (AdvLpa & MII_ADV_10T_FD)
|
||||
{
|
||||
MediaNumber = MEDIA_10T_FD;
|
||||
}
|
||||
else if (AdvLpa & MII_ADV_10T_HD)
|
||||
{
|
||||
MediaNumber = MEDIA_10T;
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_VERB("No common mode\n");
|
||||
|
||||
/* No common mode, select the other port */
|
||||
Media143SelectNextMedia(Adapter, SiaStatus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_VERB("Link partner does not support auto-negotiation, CSR12 %08lx\n", SiaStatus);
|
||||
|
||||
/* Check the results of parallel detection */
|
||||
if (!(SiaStatus & DC_SIA_STATUS_100T_LINK_FAIL))
|
||||
{
|
||||
MediaNumber = MEDIA_100TX_HD;
|
||||
}
|
||||
else if (!(SiaStatus & DC_SIA_STATUS_10T_LINK_FAIL))
|
||||
{
|
||||
MediaNumber = MEDIA_10T;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No link detected, select the other port */
|
||||
Media143SelectNextMedia(Adapter, SiaStatus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (MEDIA_IS_10T(MediaNumber) && (MediaNumber != Adapter->MediaNumber))
|
||||
{
|
||||
/* Set the time limit for auto-negotiation */
|
||||
Adapter->ModeFlags &= ~DC_MODE_AUTONEG_MASK;
|
||||
Adapter->ModeFlags |= DC_MODE_AUTONEG_WAIT_INTERRUPT;
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, 5000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait for the link integrity test to complete before we can read the link status */
|
||||
Adapter->ModeFlags &= ~DC_MODE_AUTONEG_MASK;
|
||||
Adapter->ModeFlags |= DC_MODE_AUTONEG_LINK_STATUS_CHECK;
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, 1000);
|
||||
}
|
||||
|
||||
if (Adapter->MediaNumber != MediaNumber)
|
||||
{
|
||||
Adapter->MediaNumber = MediaNumber;
|
||||
MediaSiaSelect(Adapter);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
MediaLinkStateChange21143(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG InterruptStatus)
|
||||
{
|
||||
ULONG SiaStatus;
|
||||
|
||||
INFO_VERB("Link interrupt, CSR5 %08lx\n", InterruptStatus);
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
/* Ignore link changes caused by media being estabilished */
|
||||
if ((Adapter->ModeFlags & DC_MODE_AUTONEG_MASK) == DC_MODE_AUTONEG_LINK_STATUS_CHECK)
|
||||
{
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
return;
|
||||
}
|
||||
|
||||
SiaStatus = DC_READ(Adapter, DcCsr12_SiaStatus);
|
||||
|
||||
if ((InterruptStatus & DC_IRQ_LINK_FAIL) && MEDIA_IS_10T(Adapter->MediaNumber))
|
||||
{
|
||||
/* Link has failed */
|
||||
Media143Handle10LinkFail(Adapter, SiaStatus);
|
||||
}
|
||||
else if (InterruptStatus & DC_IRQ_LINK_PASS)
|
||||
{
|
||||
if (DC_READ(Adapter, DcCsr14_SiaTxRx) & DC_SIA_TXRX_AUTONEG)
|
||||
{
|
||||
/* Auto-negotiation has completed */
|
||||
Media143HandleNWayComplete(Adapter, SiaStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Link has passed */
|
||||
Media143Handle10LinkPass(Adapter, SiaStatus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NOTE: The Link Changed bit is reserved on the 21142 and always reads as 1 */
|
||||
if (InterruptStatus & Adapter->LinkStateChangeMask & DC_IRQ_LINK_CHANGED)
|
||||
{
|
||||
/* Link has changed */
|
||||
Media143Handle100LinkChange(Adapter, SiaStatus);
|
||||
}
|
||||
}
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
Media143CheckLink(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG SiaStatus)
|
||||
{
|
||||
if (MEDIA_IS_100(Adapter->MediaNumber))
|
||||
{
|
||||
if (SiaStatus & DC_SIA_STATUS_100T_LINK_FAIL)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The auto-negotiation process can be restarted upon link failure in 10Base-T mode */
|
||||
if ((SiaStatus & DC_SIA_STATUS_ANS_MASK) != DC_SIA_STATUS_ANS_AUTONEG_COMPLETE)
|
||||
return FALSE;
|
||||
|
||||
if (SiaStatus & DC_SIA_STATUS_10T_LINK_FAIL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
MediaMonitor143(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG SiaStatus;
|
||||
BOOLEAN LinkUp;
|
||||
|
||||
SiaStatus = DC_READ(Adapter, DcCsr12_SiaStatus);
|
||||
|
||||
switch (Adapter->ModeFlags & DC_MODE_AUTONEG_MASK)
|
||||
{
|
||||
case DC_MODE_AUTONEG_WAIT_INTERRUPT:
|
||||
{
|
||||
/* Timeout, select the other port */
|
||||
Media143SelectNextMedia(Adapter, SiaStatus);
|
||||
break;
|
||||
}
|
||||
|
||||
case DC_MODE_AUTONEG_LINK_STATUS_CHECK:
|
||||
{
|
||||
/* Check the link status */
|
||||
LinkUp = Media143CheckLink(Adapter, SiaStatus);
|
||||
if (LinkUp)
|
||||
{
|
||||
Adapter->ModeFlags &= ~DC_MODE_AUTONEG_MASK;
|
||||
Adapter->ModeFlags |= DC_MODE_AUTONEG_NONE;
|
||||
|
||||
MediaIndicateConnect(Adapter, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No link detected, select the other port */
|
||||
Media143SelectNextMedia(Adapter, SiaStatus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DC_MODE_AUTONEG_NONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
UNREACHABLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MediaMonitor21143Dpc(
|
||||
_In_ PVOID SystemSpecific1,
|
||||
_In_ PVOID FunctionContext,
|
||||
_In_ PVOID SystemSpecific2,
|
||||
_In_ PVOID SystemSpecific3)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = FunctionContext;
|
||||
ULONG DelayMs;
|
||||
BOOLEAN LinkUp;
|
||||
|
||||
UNREFERENCED_PARAMETER(SystemSpecific1);
|
||||
UNREFERENCED_PARAMETER(SystemSpecific2);
|
||||
UNREFERENCED_PARAMETER(SystemSpecific3);
|
||||
|
||||
if (!(Adapter->Flags & DC_ACTIVE))
|
||||
return;
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->ModeLock);
|
||||
|
||||
switch (Adapter->MediaNumber)
|
||||
{
|
||||
case MEDIA_MII:
|
||||
{
|
||||
LinkUp = MediaMiiCheckLink(Adapter);
|
||||
|
||||
MediaIndicateConnect(Adapter, LinkUp);
|
||||
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, 5000);
|
||||
break;
|
||||
}
|
||||
|
||||
case MEDIA_AUI:
|
||||
case MEDIA_BNC:
|
||||
case MEDIA_HMR:
|
||||
{
|
||||
ULONG ReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
|
||||
|
||||
if (!(Adapter->ModeFlags & DC_MODE_TEST_PACKET))
|
||||
{
|
||||
if ((Adapter->MediaNumber == MEDIA_AUI || Adapter->MediaNumber == MEDIA_HMR) &&
|
||||
(DC_READ(Adapter, DcCsr12_SiaStatus) & DC_SIA_STATUS_AUI_ACTIVITY))
|
||||
{
|
||||
/* Clear the AUI/HMR port activity bit */
|
||||
DC_WRITE(Adapter, DcCsr12_SiaStatus, DC_SIA_STATUS_AUI_ACTIVITY);
|
||||
|
||||
MediaIndicateConnect(Adapter, TRUE);
|
||||
|
||||
DelayMs = 5000;
|
||||
}
|
||||
/* Check for any received packets */
|
||||
else if (ReceiveActivity != Adapter->LastReceiveActivity)
|
||||
{
|
||||
MediaIndicateConnect(Adapter, TRUE);
|
||||
|
||||
DelayMs = 3000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send a loopback packet */
|
||||
NdisDprAcquireSpinLock(&Adapter->SendLock);
|
||||
DcTestPacket(Adapter);
|
||||
NdisDprReleaseSpinLock(&Adapter->SendLock);
|
||||
|
||||
DelayMs = 3000;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Adapter->ModeFlags &= ~DC_MODE_TEST_PACKET;
|
||||
|
||||
LinkUp = !!Adapter->MediaTestStatus;
|
||||
|
||||
MediaIndicateConnect(Adapter, LinkUp);
|
||||
|
||||
/* Select the other port */
|
||||
if (!LinkUp && !MEDIA_IS_FIXED(Adapter))
|
||||
{
|
||||
Media143SelectNextSerialMedia(Adapter);
|
||||
|
||||
DelayMs = 3000;
|
||||
}
|
||||
else
|
||||
{
|
||||
DelayMs = 5000;
|
||||
}
|
||||
}
|
||||
Adapter->LastReceiveActivity = ReceiveActivity;
|
||||
|
||||
NdisMSetTimer(&Adapter->MediaMonitorTimer, DelayMs);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
MediaMonitor143(Adapter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->ModeLock);
|
||||
}
|
158
drivers/network/dd/dc21x4/net21x4.inf
Normal file
158
drivers/network/dd/dc21x4/net21x4.inf
Normal file
|
@ -0,0 +1,158 @@
|
|||
; NET21X4.INF
|
||||
|
||||
; Installation file for DC21x4-based NICs
|
||||
|
||||
[Version]
|
||||
Signature = "$Windows NT$"
|
||||
;Signature = "$ReactOS$"
|
||||
LayoutFile = layout.inf
|
||||
Class = Net
|
||||
ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
|
||||
Provider = %ReactOS%
|
||||
DriverVer = 08/24/2023,1.00
|
||||
|
||||
[DestinationDirs]
|
||||
DefaultDestDir = 12
|
||||
|
||||
[Manufacturer]
|
||||
%IntelMfg% = IntelMfg
|
||||
|
||||
[ControlFlags]
|
||||
ExcludeFromSelect = *
|
||||
|
||||
[IntelMfg]
|
||||
%DC21040.DeviceDesc% = DC21040.ndi,PCI\VEN_1011&DEV_0002
|
||||
%DC21041.DeviceDesc% = DC21041.ndi,PCI\VEN_1011&DEV_0014
|
||||
%DC21140.DeviceDesc% = DC21140.ndi,PCI\VEN_1011&DEV_0009
|
||||
%DC21143.DeviceDesc% = DC21143.ndi,PCI\VEN_1011&DEV_0019
|
||||
%DC21145.DeviceDesc% = DC21145.ndi,PCI\VEN_8086&DEV_0039
|
||||
%DC21140_VPC.DeviceDesc% = DC21140.ndi,PCI\VEN_1011&DEV_0009&SUBSYS_21140A00&REV_20
|
||||
|
||||
[DC21040.ndi.NT]
|
||||
Characteristics = 0x84 ; NCF_PHYSICAL | NCF_HAS_UI
|
||||
BusType = 5 ; PCIBus
|
||||
CopyFiles = DC_CopyFiles.NT
|
||||
AddReg = Common, DC_SD, DC_AUIBNC, DC_10
|
||||
|
||||
[DC21041.ndi.NT]
|
||||
Characteristics = 0x84
|
||||
BusType = 5
|
||||
CopyFiles = DC_CopyFiles.NT
|
||||
AddReg = Common, DC_SD, DC_AUI_BNC, DC_10
|
||||
|
||||
[DC21140.ndi.NT]
|
||||
Characteristics = 0x84
|
||||
BusType = 5
|
||||
CopyFiles = DC_CopyFiles.NT
|
||||
AddReg = Common, DC_SD, DC_10, DC_100
|
||||
|
||||
[DC21143.ndi.NT]
|
||||
Characteristics = 0x84
|
||||
BusType = 5
|
||||
CopyFiles = DC_CopyFiles.NT
|
||||
AddReg = Common, DC_SD, DC_AUI_BNC, DC_10, DC_100
|
||||
|
||||
[DC21145.ndi.NT]
|
||||
Characteristics = 0x84
|
||||
BusType = 5
|
||||
CopyFiles = DC_CopyFiles.NT
|
||||
AddReg = Common, DC_SD, DC_10, DC_HMR
|
||||
|
||||
[DC_CopyFiles.NT]
|
||||
dc21x4.sys
|
||||
|
||||
[DC21040.ndi.NT.Services]
|
||||
AddService = dc21x4, 2, DC_Service_Inst, DC_EventLog
|
||||
|
||||
[DC21041.ndi.NT.Services]
|
||||
AddService = dc21x4, 2, DC_Service_Inst, DC_EventLog
|
||||
|
||||
[DC21140.ndi.NT.Services]
|
||||
AddService = dc21x4, 2, DC_Service_Inst, DC_EventLog
|
||||
|
||||
[DC21143.ndi.NT.Services]
|
||||
AddService = dc21x4, 2, DC_Service_Inst, DC_EventLog
|
||||
|
||||
[DC21145.ndi.NT.Services]
|
||||
AddService = dc21x4, 2, DC_Service_Inst, DC_EventLog
|
||||
|
||||
[Common]
|
||||
HKR, Ndi, Service, 0, "dc21x4"
|
||||
HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
|
||||
HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
|
||||
|
||||
HKR, Ndi\params\NetworkAddress, ParamDesc, 0, %NA%
|
||||
HKR, Ndi\params\NetworkAddress, type, 0, "edit"
|
||||
HKR, Ndi\params\NetworkAddress, LimitText, 0, "12"
|
||||
HKR, Ndi\params\NetworkAddress, UpperCase, 0, "1"
|
||||
HKR, Ndi\params\NetworkAddress, default, 0, " "
|
||||
HKR, Ndi\params\NetworkAddress, optional, 0, "1"
|
||||
|
||||
[DC_SD]
|
||||
HKR, Ndi\params\SpeedDuplex, ParamDesc, 0, %SD%
|
||||
HKR, Ndi\params\SpeedDuplex, type, 0, "enum"
|
||||
HKR, Ndi\params\SpeedDuplex, default, 0, "0"
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "10", 0, "%Auto%"
|
||||
|
||||
[DC_AUIBNC]
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "1", 0, "AUI/BNC"
|
||||
|
||||
[DC_AUI_BNC]
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "1", 0, "BNC"
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "2", 0, "AUI"
|
||||
|
||||
[DC_10]
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "0", 0, "10T HD"
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "4", 0, "10T FD"
|
||||
|
||||
[DC_100]
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "3", 0, "100TX HD"
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "5", 0, "100TX FD"
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "6", 0, "100T4"
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "7", 0, "100FX HD"
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "8", 0, "100FX FD"
|
||||
|
||||
[DC_HMR]
|
||||
HKR, Ndi\params\SpeedDuplex\enum, "9", 0, "HomePNA"
|
||||
|
||||
[DC_Service_Inst]
|
||||
ServiceType = 1
|
||||
StartType = 3
|
||||
ErrorControl = 1
|
||||
ServiceBinary = %12%\dc21x4.sys
|
||||
LoadOrderGroup = NDIS
|
||||
|
||||
[DC_EventLog]
|
||||
AddReg = DC_EventLog_AddReg
|
||||
|
||||
[DC_EventLog_AddReg]
|
||||
HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll"
|
||||
HKR, , TypesSupported, 0x00010001, 7
|
||||
|
||||
[Strings]
|
||||
; Non-localizable
|
||||
ReactOS="ReactOS Team"
|
||||
IntelMfg="Intel"
|
||||
|
||||
NA="Network Address"
|
||||
SD="Speed & Duplex"
|
||||
Auto="Auto"
|
||||
|
||||
DC21040.DeviceDesc="Intel 21040-based PCI Ethernet Adapter"
|
||||
DC21041.DeviceDesc="Intel 21041-based PCI Ethernet Adapter"
|
||||
DC21140.DeviceDesc="Intel 21140-based PCI Ethernet Adapter"
|
||||
DC21143.DeviceDesc="Intel 21143-based PCI Ethernet Adapter"
|
||||
DC21145.DeviceDesc="Intel 21145-based PCI Ethernet Adapter"
|
||||
DC21140_VPC.DeviceDesc="Intel 21140-based PCI Ethernet Adapter (emulated)"
|
||||
|
||||
[Strings.0419]
|
||||
NA="Сетевой адрес"
|
||||
SD="Скорость и дуплекс"
|
||||
Auto="Авто"
|
||||
|
||||
DC21040.DeviceDesc="Intel 21040-based PCI сетевой адаптер"
|
||||
DC21041.DeviceDesc="Intel 21041-based PCI сетевой адаптер"
|
||||
DC21140.DeviceDesc="Intel 21140-based PCI сетевой адаптер"
|
||||
DC21143.DeviceDesc="Intel 21143-based PCI сетевой адаптер"
|
||||
DC21145.DeviceDesc="Intel 21145-based PCI сетевой адаптер"
|
||||
DC21140_VPC.DeviceDesc="Intel 21140-based PCI сетевой адаптер (эмуляция)"
|
263
drivers/network/dd/dc21x4/phy.c
Normal file
263
drivers/network/dd/dc21x4/phy.c
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: PHY layer setup and management
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
#define MII_READ(Adapter, Data) \
|
||||
do { \
|
||||
*Data = DC_READ((Adapter), DcCsr9_SerialInterface); \
|
||||
NdisStallExecution(2); \
|
||||
} while (0)
|
||||
|
||||
#define MII_WRITE(Adapter, Value) \
|
||||
do { \
|
||||
DC_WRITE((Adapter), DcCsr9_SerialInterface, Value); \
|
||||
NdisStallExecution(2); \
|
||||
} while (0)
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
MiiMdioPacket(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG Sequence,
|
||||
_In_ ULONG BitCount)
|
||||
{
|
||||
LONG i;
|
||||
|
||||
for (i = BitCount - 1; i >= 0; --i)
|
||||
{
|
||||
ULONG Mdo = ((Sequence >> i) & 1) << DC_SERIAL_MII_MDO_SHIFT;
|
||||
|
||||
MII_WRITE(Adapter, Mdo);
|
||||
MII_WRITE(Adapter, Mdo | DC_SERIAL_MII_MDC);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
ULONG
|
||||
MiiMdioShiftIn(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG i, Csr;
|
||||
ULONG Result = 0;
|
||||
|
||||
for (i = 0; i < RTL_BITS_OF(USHORT); ++i)
|
||||
{
|
||||
MII_WRITE(Adapter, DC_SERIAL_MII_MII);
|
||||
MII_WRITE(Adapter, DC_SERIAL_MII_MII | DC_SERIAL_MII_MDC);
|
||||
|
||||
MII_READ(Adapter, &Csr);
|
||||
Result = (Result << 1) | ((Csr >> DC_SERIAL_MII_MDI_SHIFT) & 1);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
MiiMdioClearExtraBits(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
MII_WRITE(Adapter, DC_SERIAL_MII_MII);
|
||||
MII_WRITE(Adapter, DC_SERIAL_MII_MII | DC_SERIAL_MII_MDC);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
MiiWrite(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG PhyAddress,
|
||||
_In_ ULONG RegAddress,
|
||||
_In_ ULONG Data)
|
||||
{
|
||||
MiiMdioPacket(Adapter, MDIO_PREAMBLE, 32);
|
||||
MiiMdioPacket(Adapter,
|
||||
(MDIO_START << 30) |
|
||||
(MDIO_WRITE << 28) |
|
||||
(PhyAddress << 23) |
|
||||
(RegAddress << 18) |
|
||||
(MDIO_TA << 16) |
|
||||
Data,
|
||||
32);
|
||||
|
||||
/* Idle state */
|
||||
MiiMdioClearExtraBits(Adapter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
MiiRead(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG PhyAddress,
|
||||
_In_ ULONG RegAddress,
|
||||
_Out_ PULONG Data)
|
||||
{
|
||||
ULONG Csr;
|
||||
BOOLEAN Success;
|
||||
|
||||
MiiMdioPacket(Adapter, MDIO_PREAMBLE, 32);
|
||||
MiiMdioPacket(Adapter,
|
||||
(MDIO_START << 12) |
|
||||
(MDIO_READ << 10) |
|
||||
(PhyAddress << 5) |
|
||||
RegAddress,
|
||||
14);
|
||||
|
||||
/* Turnaround */
|
||||
MiiMdioClearExtraBits(Adapter);
|
||||
|
||||
Csr = DC_READ(Adapter, DcCsr9_SerialInterface);
|
||||
Success = !(Csr & DC_SERIAL_MII_MDI);
|
||||
|
||||
*Data = MiiMdioShiftIn(Adapter);
|
||||
|
||||
/* Idle state */
|
||||
MiiMdioClearExtraBits(Adapter);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
HpnaSpiClose(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DC_WRITE(Adapter, DcCsr9_SerialInterface, 0);
|
||||
DC_WRITE(Adapter, DcCsr9_SerialInterface, DC_SERIAL_SPI_SK);
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
HpnaSpiShiftOut(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG Sequence,
|
||||
_In_ ULONG BitCount)
|
||||
{
|
||||
LONG i;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DC_WRITE(Adapter, DcCsr9_SerialInterface, 0);
|
||||
DC_WRITE(Adapter, DcCsr9_SerialInterface, DC_SERIAL_SPI_CS);
|
||||
|
||||
for (i = BitCount - 1; i >= 0; --i)
|
||||
{
|
||||
ULONG DataIn = ((Sequence >> i) & 1) << DC_SERIAL_SPI_DI_SHIFT;
|
||||
|
||||
DC_WRITE(Adapter, DcCsr9_SerialInterface, DataIn | DC_SERIAL_SPI_CS);
|
||||
DC_WRITE(Adapter, DcCsr9_SerialInterface, DataIn | DC_SERIAL_SPI_CS | DC_SERIAL_SPI_SK);
|
||||
}
|
||||
|
||||
DC_WRITE(Adapter, DcCsr9_SerialInterface, 0);
|
||||
DC_WRITE(Adapter, DcCsr9_SerialInterface, DC_SERIAL_SPI_SK);
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
HpnaWrite(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ ULONG RegAddress,
|
||||
_In_ ULONG Data)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
HpnaSpiShiftOut(Adapter, DC_SPI_SET_WRITE_ENABLE, 8);
|
||||
HpnaSpiClose(Adapter);
|
||||
|
||||
HpnaSpiShiftOut(Adapter,
|
||||
(Data << 16) |
|
||||
(RegAddress << 8) |
|
||||
DC_SPI_BYTE_WRITE_OPERATION,
|
||||
RTL_BITS_OF(UCHAR) * 3);
|
||||
HpnaSpiClose(Adapter);
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
HpnaPhyInit(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG SiaConn, i;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Select the HPNA interface */
|
||||
SiaConn = DC_READ(Adapter, DcCsr13_SiaConnectivity);
|
||||
SiaConn |= DC_SIA_CONN_HPNA;
|
||||
DC_WRITE(Adapter, DcCsr13_SiaConnectivity, SiaConn);
|
||||
|
||||
for (i = 0; i < RTL_NUMBER_OF(Adapter->HpnaRegister); ++i)
|
||||
{
|
||||
if (Adapter->HpnaInitBitmap & (1 << i))
|
||||
{
|
||||
HpnaWrite(Adapter, i, Adapter->HpnaRegister[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
BOOLEAN
|
||||
DcFindMiiPhy(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG Phy;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Look for the first connected PHY */
|
||||
for (Phy = 1; Phy <= MII_MAX_PHY_ADDRESSES; ++Phy)
|
||||
{
|
||||
ULONG PhyAddress = Phy % MII_MAX_PHY_ADDRESSES; /* Check the PHY 0 last */
|
||||
ULONG MiiStatus;
|
||||
#if DBG
|
||||
ULONG PhyIdLow, PhyIdHigh, MiiControl, MiiAdvertise;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read the status register. Some PHYs, such as the ML6692,
|
||||
* don't implement the IEEE ID registers.
|
||||
*/
|
||||
if (!MiiRead(Adapter, PhyAddress, MII_STATUS, &MiiStatus))
|
||||
continue;
|
||||
if (MiiStatus == 0xFFFF || MiiStatus == 0)
|
||||
continue;
|
||||
|
||||
#if DBG
|
||||
MiiRead(Adapter, PhyAddress, MII_PHY_ID1, &PhyIdLow);
|
||||
MiiRead(Adapter, PhyAddress, MII_PHY_ID2, &PhyIdHigh);
|
||||
MiiRead(Adapter, PhyAddress, MII_CONTROL, &MiiControl);
|
||||
MiiRead(Adapter, PhyAddress, MII_AUTONEG_ADVERTISE, &MiiAdvertise);
|
||||
|
||||
INFO_VERB("Found PHY at address %u: ID %04lx:%04lx, Ctrl %04lx, Status %04lx, Adv %04lx\n",
|
||||
PhyAddress,
|
||||
PhyIdLow,
|
||||
PhyIdHigh,
|
||||
MiiControl,
|
||||
MiiStatus,
|
||||
MiiAdvertise);
|
||||
#endif
|
||||
|
||||
Adapter->PhyAddress = PhyAddress;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
252
drivers/network/dd/dc21x4/power.c
Normal file
252
drivers/network/dd/dc21x4/power.c
Normal file
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Power management
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcDownloadPatternFilter(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PDC_PATTERN_FILTER_BLOCK FilterBlock)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
for (i = 0; i < sizeof(*FilterBlock) / sizeof(ULONG); ++i)
|
||||
{
|
||||
DC_WRITE(Adapter, DcCsr1_WakeUpFilter, FilterBlock->AsULONG[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcSetupWakeUpFilter(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
DC_PATTERN_FILTER_BLOCK FilterBlock;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Save the address filtering */
|
||||
NdisMoveMemory(Adapter->SetupFrameSaved, Adapter->SetupFrame, DC_SETUP_FRAME_SIZE);
|
||||
|
||||
NdisZeroMemory(&FilterBlock, sizeof(FilterBlock));
|
||||
|
||||
// TODO: Convert NDIS patterns to HW filter and prepare a setup frame
|
||||
|
||||
DcDownloadPatternFilter(Adapter, &FilterBlock);
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcProgramWakeUpEvents(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG WakeUpControl;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Clear the wake-up events */
|
||||
WakeUpControl = (DC_WAKE_UP_STATUS_LINK_CHANGE |
|
||||
DC_WAKE_UP_STATUS_MAGIC_PACKET |
|
||||
DC_WAKE_UP_CONTROL_PATTERN_MATCH);
|
||||
|
||||
/* Convert NDIS flags to hardware-specific values */
|
||||
if (Adapter->WakeUpFlags & NDIS_PNP_WAKE_UP_LINK_CHANGE)
|
||||
WakeUpControl |= DC_WAKE_UP_CONTROL_LINK_CHANGE;
|
||||
if (Adapter->WakeUpFlags & NDIS_PNP_WAKE_UP_MAGIC_PACKET)
|
||||
WakeUpControl |= DC_WAKE_UP_CONTROL_MAGIC_PACKET;
|
||||
#if 0 // TODO: Pattern matching is not yet supported
|
||||
if (Adapter->WakeUpFlags & NDIS_PNP_WAKE_UP_PATTERN_MATCH)
|
||||
WakeUpControl |= DC_WAKE_UP_CONTROL_PATTERN_MATCH;
|
||||
#endif
|
||||
|
||||
DC_WRITE(Adapter, DcCsr2_WakeUpControl, WakeUpControl);
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcPowerDown(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG SiaState, SerialInterface;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Stop the receive and transmit processes */
|
||||
DcStopAdapter(Adapter, FALSE);
|
||||
|
||||
Adapter->CurrentInterruptMask = 0;
|
||||
|
||||
/* Enable the link integrity test bit */
|
||||
switch (Adapter->MediaNumber)
|
||||
{
|
||||
case MEDIA_AUI:
|
||||
case MEDIA_BNC:
|
||||
case MEDIA_HMR:
|
||||
{
|
||||
SiaState = DC_READ(Adapter, DcCsr14_SiaTxRx);
|
||||
if (!(SiaState & DC_SIA_TXRX_LINK_TEST))
|
||||
{
|
||||
SiaState |= DC_SIA_TXRX_LINK_TEST;
|
||||
DC_WRITE(Adapter, DcCsr14_SiaTxRx, SiaState);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clear the MDC bit */
|
||||
SerialInterface = DC_READ(Adapter, DcCsr9_SerialInterface);
|
||||
if (SerialInterface & DC_SERIAL_MII_MDC)
|
||||
{
|
||||
SerialInterface &= ~DC_SERIAL_MII_MDC;
|
||||
DC_WRITE(Adapter, DcCsr9_SerialInterface, SerialInterface);
|
||||
}
|
||||
|
||||
/* Unprotect PM access */
|
||||
DC_WRITE(Adapter, DcCsr0_BusMode, Adapter->BusMode | DC_BUS_MODE_ON_NOW_UNLOCK);
|
||||
|
||||
/* Program the requested WOL events */
|
||||
DcSetupWakeUpFilter(Adapter);
|
||||
DcProgramWakeUpEvents(Adapter);
|
||||
|
||||
/* Protect PM access */
|
||||
DC_WRITE(Adapter, DcCsr0_BusMode, Adapter->BusMode);
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
DcPowerUp(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
/* Restore the address filtering */
|
||||
NdisMoveMemory(Adapter->SetupFrame, Adapter->SetupFrameSaved, DC_SETUP_FRAME_SIZE);
|
||||
|
||||
/* Re-initialize the chip to leave D3 state */
|
||||
if (Adapter->PrevPowerState == NdisDeviceStateD3)
|
||||
{
|
||||
NT_VERIFY(DcSetupAdapter(Adapter) == TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start the transmit process */
|
||||
Adapter->OpMode |= DC_OPMODE_TX_ENABLE;
|
||||
DC_WRITE(Adapter, DcCsr6_OpMode, Adapter->OpMode);
|
||||
|
||||
/* Load the address recognition RAM */
|
||||
NT_VERIFY(DcSetupFrameDownload(Adapter, TRUE) == TRUE);
|
||||
}
|
||||
|
||||
DcStartAdapter(Adapter);
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
NTAPI
|
||||
DcPowerWorker(
|
||||
_In_ PNDIS_WORK_ITEM WorkItem,
|
||||
_In_opt_ PVOID Context)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = Context;
|
||||
|
||||
UNREFERENCED_PARAMETER(WorkItem);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
if (Adapter->PowerState == NdisDeviceStateD0)
|
||||
{
|
||||
DcPowerUp(Adapter);
|
||||
}
|
||||
else
|
||||
{
|
||||
DcPowerDown(Adapter);
|
||||
}
|
||||
Adapter->PrevPowerState = Adapter->PowerState;
|
||||
|
||||
NdisMSetInformationComplete(Adapter->AdapterHandle, NDIS_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NDIS_STATUS
|
||||
DcSetPower(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ NDIS_DEVICE_POWER_STATE PowerState)
|
||||
{
|
||||
INFO("Power state %u\n", PowerState);
|
||||
|
||||
Adapter->PowerState = PowerState;
|
||||
|
||||
NdisScheduleWorkItem(&Adapter->PowerWorkItem);
|
||||
|
||||
return NDIS_STATUS_PENDING;
|
||||
}
|
||||
|
||||
NDIS_STATUS
|
||||
DcRemoveWakeUpPattern(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PNDIS_PM_PACKET_PATTERN PmPattern)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
ERR("FIXME: Not implemented\n");
|
||||
return NDIS_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NDIS_STATUS
|
||||
DcAddWakeUpPattern(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PNDIS_PM_PACKET_PATTERN PmPattern)
|
||||
{
|
||||
// TODO: Not implemented
|
||||
ERR("FIXME: Not implemented\n");
|
||||
return NDIS_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
DcPowerSave(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ BOOLEAN Enable)
|
||||
{
|
||||
ULONG ConfigValue;
|
||||
|
||||
if (!(Adapter->Features & DC_HAS_POWER_SAVING))
|
||||
return;
|
||||
|
||||
NdisReadPciSlotInformation(Adapter->AdapterHandle,
|
||||
0,
|
||||
DC_PCI_DEVICE_CONFIG,
|
||||
&ConfigValue,
|
||||
sizeof(ConfigValue));
|
||||
|
||||
ConfigValue &= ~DC_PCI_DEVICE_CONFIG_SLEEP;
|
||||
|
||||
if (Enable)
|
||||
ConfigValue |= DC_PCI_DEVICE_CONFIG_SNOOZE;
|
||||
else
|
||||
ConfigValue &= ~DC_PCI_DEVICE_CONFIG_SNOOZE;
|
||||
|
||||
NdisWritePciSlotInformation(Adapter->AdapterHandle,
|
||||
0,
|
||||
DC_PCI_DEVICE_CONFIG,
|
||||
&ConfigValue,
|
||||
sizeof(ConfigValue));
|
||||
}
|
660
drivers/network/dd/dc21x4/requests.c
Normal file
660
drivers/network/dd/dc21x4/requests.c
Normal file
|
@ -0,0 +1,660 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Miniport information callbacks
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
static const NDIS_OID DcpSupportedOidList[] =
|
||||
{
|
||||
OID_GEN_SUPPORTED_LIST,
|
||||
OID_GEN_CURRENT_PACKET_FILTER,
|
||||
OID_GEN_HARDWARE_STATUS,
|
||||
OID_GEN_MEDIA_SUPPORTED,
|
||||
OID_GEN_MEDIA_IN_USE,
|
||||
OID_GEN_MAXIMUM_LOOKAHEAD,
|
||||
OID_GEN_MAXIMUM_FRAME_SIZE,
|
||||
OID_GEN_MAXIMUM_SEND_PACKETS,
|
||||
OID_GEN_LINK_SPEED,
|
||||
OID_GEN_TRANSMIT_BUFFER_SPACE,
|
||||
OID_GEN_RECEIVE_BUFFER_SPACE,
|
||||
OID_GEN_RECEIVE_BLOCK_SIZE,
|
||||
OID_GEN_TRANSMIT_BLOCK_SIZE,
|
||||
OID_GEN_VENDOR_ID,
|
||||
OID_GEN_VENDOR_DESCRIPTION,
|
||||
OID_GEN_VENDOR_DRIVER_VERSION,
|
||||
OID_GEN_CURRENT_LOOKAHEAD,
|
||||
OID_GEN_DRIVER_VERSION,
|
||||
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
||||
OID_GEN_MAC_OPTIONS,
|
||||
OID_GEN_MEDIA_CONNECT_STATUS,
|
||||
OID_802_3_PERMANENT_ADDRESS,
|
||||
OID_802_3_CURRENT_ADDRESS,
|
||||
OID_802_3_MULTICAST_LIST,
|
||||
OID_802_3_MAXIMUM_LIST_SIZE,
|
||||
|
||||
/* Statistics */
|
||||
OID_GEN_XMIT_OK,
|
||||
OID_GEN_RCV_OK,
|
||||
OID_GEN_XMIT_ERROR,
|
||||
OID_GEN_RCV_ERROR,
|
||||
OID_GEN_RCV_NO_BUFFER,
|
||||
OID_GEN_DIRECTED_FRAMES_RCV,
|
||||
OID_GEN_MULTICAST_FRAMES_RCV,
|
||||
OID_GEN_BROADCAST_FRAMES_RCV,
|
||||
OID_GEN_RCV_CRC_ERROR,
|
||||
OID_GEN_TRANSMIT_QUEUE_LENGTH,
|
||||
OID_802_3_RCV_ERROR_ALIGNMENT,
|
||||
OID_802_3_XMIT_ONE_COLLISION,
|
||||
OID_802_3_XMIT_MORE_COLLISIONS,
|
||||
OID_802_3_XMIT_DEFERRED,
|
||||
OID_802_3_XMIT_MAX_COLLISIONS,
|
||||
OID_802_3_RCV_OVERRUN,
|
||||
OID_802_3_XMIT_UNDERRUN,
|
||||
OID_802_3_XMIT_HEARTBEAT_FAILURE,
|
||||
OID_802_3_XMIT_TIMES_CRS_LOST,
|
||||
OID_802_3_XMIT_LATE_COLLISIONS,
|
||||
|
||||
/* Power management */
|
||||
OID_PNP_CAPABILITIES,
|
||||
OID_PNP_SET_POWER,
|
||||
OID_PNP_QUERY_POWER,
|
||||
OID_PNP_ADD_WAKE_UP_PATTERN,
|
||||
OID_PNP_REMOVE_WAKE_UP_PATTERN,
|
||||
OID_PNP_ENABLE_WAKE_UP
|
||||
};
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
DcQueryStatisticCounter(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ NDIS_OID Oid,
|
||||
_Out_ PULONG64 Counter)
|
||||
{
|
||||
/* When there is no workaround, this function is used to read the hardware RX counters */
|
||||
if (!(Adapter->Features & DC_NEED_RX_OVERFLOW_WORKAROUND))
|
||||
{
|
||||
ULONG RxCounters;
|
||||
|
||||
/*
|
||||
* Read the RX missed frame counter. Note that the RX overflow counter is not supported
|
||||
* on older chips without the workaround enabled and reads will return 0xFFFE****.
|
||||
*/
|
||||
RxCounters = DC_READ(Adapter, DcCsr8_RxCounters);
|
||||
|
||||
Adapter->Statistics.ReceiveNoBuffers += RxCounters & DC_COUNTER_RX_NO_BUFFER_MASK;
|
||||
}
|
||||
|
||||
switch (Oid)
|
||||
{
|
||||
case OID_GEN_XMIT_OK:
|
||||
*Counter = Adapter->Statistics.TransmitOk;
|
||||
break;
|
||||
case OID_GEN_RCV_OK:
|
||||
*Counter = Adapter->Statistics.ReceiveOk;
|
||||
break;
|
||||
case OID_GEN_XMIT_ERROR:
|
||||
*Counter = Adapter->Statistics.TransmitErrors;
|
||||
break;
|
||||
case OID_GEN_RCV_ERROR:
|
||||
*Counter = Adapter->Statistics.ReceiveErrors;
|
||||
break;
|
||||
case OID_GEN_RCV_NO_BUFFER:
|
||||
*Counter = Adapter->Statistics.ReceiveNoBuffers;
|
||||
break;
|
||||
case OID_GEN_DIRECTED_FRAMES_RCV:
|
||||
*Counter = Adapter->Statistics.ReceiveUnicast;
|
||||
break;
|
||||
case OID_GEN_MULTICAST_FRAMES_RCV:
|
||||
*Counter = Adapter->Statistics.ReceiveMulticast;
|
||||
break;
|
||||
case OID_GEN_BROADCAST_FRAMES_RCV:
|
||||
*Counter = Adapter->Statistics.ReceiveBroadcast;
|
||||
break;
|
||||
case OID_GEN_RCV_CRC_ERROR:
|
||||
*Counter = Adapter->Statistics.ReceiveCrcErrors;
|
||||
break;
|
||||
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
||||
*Counter = Adapter->Statistics.ReceiveAlignmentErrors;
|
||||
break;
|
||||
case OID_802_3_XMIT_ONE_COLLISION:
|
||||
*Counter = Adapter->Statistics.TransmitOneRetry;
|
||||
break;
|
||||
case OID_802_3_XMIT_MORE_COLLISIONS:
|
||||
*Counter = Adapter->Statistics.TransmitMoreCollisions;
|
||||
break;
|
||||
case OID_802_3_XMIT_DEFERRED:
|
||||
*Counter = Adapter->Statistics.TransmitDeferred;
|
||||
break;
|
||||
case OID_802_3_XMIT_MAX_COLLISIONS:
|
||||
*Counter = Adapter->Statistics.TransmitExcessiveCollisions;
|
||||
break;
|
||||
case OID_802_3_RCV_OVERRUN:
|
||||
*Counter = Adapter->Statistics.ReceiveOverrunErrors;
|
||||
break;
|
||||
case OID_802_3_XMIT_UNDERRUN:
|
||||
*Counter = Adapter->Statistics.TransmitUnderrunErrors;
|
||||
break;
|
||||
case OID_802_3_XMIT_HEARTBEAT_FAILURE:
|
||||
*Counter = Adapter->Statistics.TransmitHeartbeatErrors;
|
||||
break;
|
||||
case OID_802_3_XMIT_TIMES_CRS_LOST:
|
||||
*Counter = Adapter->Statistics.TransmitLostCarrierSense;
|
||||
break;
|
||||
case OID_802_3_XMIT_LATE_COLLISIONS:
|
||||
*Counter = Adapter->Statistics.TransmitLateCollisions;
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
UNREACHABLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
ULONG
|
||||
DcGetLinkSpeed(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
ULONG LinkSpeedMbps;
|
||||
|
||||
switch (Adapter->MediaNumber)
|
||||
{
|
||||
case MEDIA_HMR:
|
||||
LinkSpeedMbps = 1;
|
||||
break;
|
||||
|
||||
case MEDIA_10T:
|
||||
case MEDIA_BNC:
|
||||
case MEDIA_AUI:
|
||||
case MEDIA_10T_FD:
|
||||
LinkSpeedMbps = 10;
|
||||
break;
|
||||
|
||||
case MEDIA_100TX_HD:
|
||||
case MEDIA_100TX_FD:
|
||||
case MEDIA_100T4:
|
||||
case MEDIA_100FX_HD:
|
||||
case MEDIA_100FX_FD:
|
||||
LinkSpeedMbps = 100;
|
||||
break;
|
||||
|
||||
case MEDIA_MII:
|
||||
LinkSpeedMbps = Adapter->LinkSpeedMbps;
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
UNREACHABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
return LinkSpeedMbps;
|
||||
}
|
||||
|
||||
NDIS_STATUS
|
||||
NTAPI
|
||||
DcQueryInformation(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ NDIS_OID Oid,
|
||||
_In_ PVOID InformationBuffer,
|
||||
_In_ ULONG InformationBufferLength,
|
||||
_Out_ PULONG BytesWritten,
|
||||
_Out_ PULONG BytesNeeded)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
||||
ULONG InfoLength;
|
||||
PVOID InfoPtr;
|
||||
union _GENERIC_INFORMATION
|
||||
{
|
||||
USHORT Ushort;
|
||||
ULONG Ulong;
|
||||
ULONG64 Ulong64;
|
||||
NDIS_MEDIUM Medium;
|
||||
NDIS_HARDWARE_STATUS Status;
|
||||
NDIS_DEVICE_POWER_STATE PowerState;
|
||||
} GenericInfo;
|
||||
|
||||
InfoLength = sizeof(ULONG);
|
||||
InfoPtr = &GenericInfo;
|
||||
|
||||
switch (Oid)
|
||||
{
|
||||
case OID_GEN_SUPPORTED_LIST:
|
||||
InfoPtr = (PVOID)&DcpSupportedOidList;
|
||||
InfoLength = sizeof(DcpSupportedOidList);
|
||||
break;
|
||||
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
GenericInfo.Ulong = Adapter->PacketFilter;
|
||||
break;
|
||||
|
||||
case OID_802_3_MULTICAST_LIST:
|
||||
InfoPtr = Adapter->MulticastList;
|
||||
InfoLength = Adapter->MulticastCount * ETH_LENGTH_OF_ADDRESS;
|
||||
break;
|
||||
|
||||
case OID_802_3_MAXIMUM_LIST_SIZE:
|
||||
GenericInfo.Ulong = Adapter->MulticastMaxEntries;
|
||||
break;
|
||||
|
||||
case OID_GEN_MEDIA_SUPPORTED:
|
||||
case OID_GEN_MEDIA_IN_USE:
|
||||
{
|
||||
GenericInfo.Medium = NdisMedium802_3;
|
||||
InfoLength = sizeof(NDIS_MEDIUM);
|
||||
break;
|
||||
}
|
||||
|
||||
case OID_GEN_HARDWARE_STATUS:
|
||||
{
|
||||
ULONG InterruptStatus;
|
||||
|
||||
/* NOTE: Reading the status register has no effect on the events */
|
||||
InterruptStatus = DC_READ(Adapter, DcCsr5_Status);
|
||||
|
||||
/* Inserted into the motherboard */
|
||||
if (InterruptStatus != 0xFFFFFFFF)
|
||||
GenericInfo.Status = NdisHardwareStatusReady;
|
||||
else
|
||||
GenericInfo.Status = NdisHardwareStatusNotReady;
|
||||
|
||||
InfoLength = sizeof(NDIS_HARDWARE_STATUS);
|
||||
break;
|
||||
}
|
||||
|
||||
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||||
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
||||
case OID_GEN_CURRENT_LOOKAHEAD:
|
||||
GenericInfo.Ulong = DC_MAXIMUM_FRAME_SIZE - DC_ETHERNET_HEADER_SIZE;
|
||||
break;
|
||||
|
||||
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||||
GenericInfo.Ulong = DC_MAXIMUM_FRAME_SIZE;
|
||||
break;
|
||||
|
||||
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
||||
GenericInfo.Ulong = DC_TRANSMIT_BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
case OID_GEN_TRANSMIT_BUFFER_SPACE:
|
||||
GenericInfo.Ulong = DC_TRANSMIT_BLOCK_SIZE * DC_TRANSMIT_BLOCKS;
|
||||
break;
|
||||
|
||||
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
||||
GenericInfo.Ulong = DC_RECEIVE_BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
case OID_GEN_RECEIVE_BUFFER_SPACE:
|
||||
GenericInfo.Ulong = DC_RECEIVE_BLOCK_SIZE * Adapter->RcbCount;
|
||||
break;
|
||||
|
||||
case OID_GEN_LINK_SPEED:
|
||||
GenericInfo.Ulong = DcGetLinkSpeed(Adapter) * 10000;
|
||||
break;
|
||||
|
||||
case OID_GEN_VENDOR_ID:
|
||||
GenericInfo.Ulong = 0;
|
||||
GenericInfo.Ulong |= (Adapter->PermanentMacAddress[0] << 16);
|
||||
GenericInfo.Ulong |= (Adapter->PermanentMacAddress[1] << 8);
|
||||
GenericInfo.Ulong |= (Adapter->PermanentMacAddress[2] & 0xFF);
|
||||
break;
|
||||
|
||||
case OID_GEN_VENDOR_DESCRIPTION:
|
||||
{
|
||||
static const CHAR VendorDesc[] = "DC21x4 compatible Ethernet Adapter";
|
||||
InfoPtr = (PVOID)&VendorDesc;
|
||||
InfoLength = sizeof(VendorDesc);
|
||||
break;
|
||||
}
|
||||
|
||||
case OID_GEN_VENDOR_DRIVER_VERSION:
|
||||
/* 1.0.0 */
|
||||
GenericInfo.Ulong = 0x100;
|
||||
break;
|
||||
|
||||
case OID_GEN_DRIVER_VERSION:
|
||||
{
|
||||
InfoLength = sizeof(USHORT);
|
||||
GenericInfo.Ushort = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
|
||||
break;
|
||||
}
|
||||
|
||||
case OID_GEN_MAXIMUM_SEND_PACKETS:
|
||||
GenericInfo.Ulong = DC_TRANSMIT_BLOCKS - DC_TCB_RESERVE;
|
||||
break;
|
||||
|
||||
case OID_GEN_MAC_OPTIONS:
|
||||
GenericInfo.Ulong = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
|
||||
NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
|
||||
NDIS_MAC_OPTION_NO_LOOPBACK;
|
||||
break;
|
||||
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||
GenericInfo.Ulong = Adapter->LinkUp ? NdisMediaStateConnected
|
||||
: NdisMediaStateDisconnected;
|
||||
break;
|
||||
|
||||
case OID_802_3_PERMANENT_ADDRESS:
|
||||
InfoPtr = Adapter->PermanentMacAddress;
|
||||
InfoLength = ETH_LENGTH_OF_ADDRESS;
|
||||
break;
|
||||
|
||||
case OID_802_3_CURRENT_ADDRESS:
|
||||
InfoPtr = Adapter->CurrentMacAddress;
|
||||
InfoLength = ETH_LENGTH_OF_ADDRESS;
|
||||
break;
|
||||
|
||||
case OID_GEN_XMIT_OK:
|
||||
case OID_GEN_RCV_OK:
|
||||
case OID_GEN_XMIT_ERROR:
|
||||
case OID_GEN_RCV_ERROR:
|
||||
case OID_GEN_RCV_NO_BUFFER:
|
||||
case OID_GEN_DIRECTED_FRAMES_RCV:
|
||||
case OID_GEN_MULTICAST_FRAMES_RCV:
|
||||
case OID_GEN_BROADCAST_FRAMES_RCV:
|
||||
case OID_GEN_RCV_CRC_ERROR:
|
||||
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
||||
case OID_802_3_XMIT_ONE_COLLISION:
|
||||
case OID_802_3_XMIT_MORE_COLLISIONS:
|
||||
case OID_802_3_XMIT_DEFERRED:
|
||||
case OID_802_3_XMIT_MAX_COLLISIONS:
|
||||
case OID_802_3_RCV_OVERRUN:
|
||||
case OID_802_3_XMIT_UNDERRUN:
|
||||
case OID_802_3_XMIT_HEARTBEAT_FAILURE:
|
||||
case OID_802_3_XMIT_TIMES_CRS_LOST:
|
||||
case OID_802_3_XMIT_LATE_COLLISIONS:
|
||||
{
|
||||
DcQueryStatisticCounter(Adapter, Oid, &GenericInfo.Ulong64);
|
||||
|
||||
*BytesNeeded = sizeof(ULONG64);
|
||||
if (InformationBufferLength < sizeof(ULONG))
|
||||
{
|
||||
*BytesWritten = 0;
|
||||
return NDIS_STATUS_BUFFER_TOO_SHORT;
|
||||
}
|
||||
if (InformationBufferLength >= sizeof(ULONG64))
|
||||
{
|
||||
*BytesWritten = sizeof(ULONG64);
|
||||
NdisMoveMemory(InformationBuffer, InfoPtr, sizeof(ULONG64));
|
||||
}
|
||||
else
|
||||
{
|
||||
*BytesWritten = sizeof(ULONG);
|
||||
NdisMoveMemory(InformationBuffer, InfoPtr, sizeof(ULONG));
|
||||
}
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
case OID_GEN_TRANSMIT_QUEUE_LENGTH:
|
||||
GenericInfo.Ulong = (DC_TRANSMIT_BLOCKS - DC_TCB_RESERVE) - Adapter->TcbSlots;
|
||||
break;
|
||||
|
||||
case OID_PNP_CAPABILITIES:
|
||||
{
|
||||
PNDIS_PNP_CAPABILITIES Capabilities;
|
||||
|
||||
InfoLength = sizeof(NDIS_PNP_CAPABILITIES);
|
||||
|
||||
if (InformationBufferLength < InfoLength)
|
||||
{
|
||||
*BytesWritten = 0;
|
||||
*BytesNeeded = InfoLength;
|
||||
return NDIS_STATUS_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
|
||||
return NDIS_STATUS_NOT_SUPPORTED;
|
||||
|
||||
*BytesWritten = InfoLength;
|
||||
*BytesNeeded = 0;
|
||||
|
||||
Capabilities = InformationBuffer;
|
||||
Capabilities->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateD3;
|
||||
Capabilities->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateD3;
|
||||
Capabilities->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateD3;
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
case OID_PNP_QUERY_POWER:
|
||||
{
|
||||
if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
|
||||
return NDIS_STATUS_NOT_SUPPORTED;
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
case OID_PNP_ENABLE_WAKE_UP:
|
||||
{
|
||||
if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
|
||||
return NDIS_STATUS_NOT_SUPPORTED;
|
||||
|
||||
GenericInfo.Ulong = Adapter->WakeUpFlags & (NDIS_PNP_WAKE_UP_MAGIC_PACKET |
|
||||
NDIS_PNP_WAKE_UP_PATTERN_MATCH |
|
||||
NDIS_PNP_WAKE_UP_LINK_CHANGE);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Status = NDIS_STATUS_INVALID_OID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Status == NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
if (InfoLength > InformationBufferLength)
|
||||
{
|
||||
*BytesWritten = 0;
|
||||
*BytesNeeded = InfoLength;
|
||||
Status = NDIS_STATUS_BUFFER_TOO_SHORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
NdisMoveMemory(InformationBuffer, InfoPtr, InfoLength);
|
||||
*BytesWritten = InfoLength;
|
||||
*BytesNeeded = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*BytesWritten = 0;
|
||||
*BytesNeeded = 0;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NDIS_STATUS
|
||||
NTAPI
|
||||
DcSetInformation(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ NDIS_OID Oid,
|
||||
_In_ PVOID InformationBuffer,
|
||||
_In_ ULONG InformationBufferLength,
|
||||
_Out_ PULONG BytesRead,
|
||||
_Out_ PULONG BytesNeeded)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
||||
ULONG GenericUlong;
|
||||
|
||||
*BytesRead = 0;
|
||||
*BytesNeeded = 0;
|
||||
|
||||
switch (Oid)
|
||||
{
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
{
|
||||
if (InformationBufferLength < sizeof(ULONG))
|
||||
{
|
||||
*BytesNeeded = sizeof(ULONG);
|
||||
Status = NDIS_STATUS_INVALID_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
*BytesRead = sizeof(ULONG);
|
||||
NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG));
|
||||
|
||||
if (GenericUlong & ~DC_PACKET_FILTERS)
|
||||
{
|
||||
Status = NDIS_STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
Status = DcApplyPacketFilter(Adapter, GenericUlong);
|
||||
break;
|
||||
}
|
||||
|
||||
case OID_802_3_MULTICAST_LIST:
|
||||
{
|
||||
ULONG Size;
|
||||
|
||||
if (InformationBufferLength % ETH_LENGTH_OF_ADDRESS)
|
||||
{
|
||||
*BytesNeeded = (InformationBufferLength / ETH_LENGTH_OF_ADDRESS) *
|
||||
ETH_LENGTH_OF_ADDRESS;
|
||||
Status = NDIS_STATUS_INVALID_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
Size = Adapter->MulticastMaxEntries * ETH_LENGTH_OF_ADDRESS;
|
||||
if (InformationBufferLength > Size)
|
||||
{
|
||||
*BytesNeeded = Size;
|
||||
Status = NDIS_STATUS_MULTICAST_FULL;
|
||||
break;
|
||||
}
|
||||
|
||||
*BytesRead = InformationBufferLength;
|
||||
NdisMoveMemory(Adapter->MulticastList, InformationBuffer, InformationBufferLength);
|
||||
|
||||
Adapter->MulticastCount = InformationBufferLength / ETH_LENGTH_OF_ADDRESS;
|
||||
|
||||
Status = DcUpdateMulticastList(Adapter);
|
||||
break;
|
||||
}
|
||||
|
||||
case OID_GEN_CURRENT_LOOKAHEAD:
|
||||
{
|
||||
if (InformationBufferLength < sizeof(ULONG))
|
||||
{
|
||||
*BytesNeeded = sizeof(ULONG);
|
||||
Status = NDIS_STATUS_INVALID_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Nothing to do */
|
||||
*BytesRead = sizeof(ULONG);
|
||||
break;
|
||||
}
|
||||
|
||||
case OID_PNP_ENABLE_WAKE_UP:
|
||||
{
|
||||
if (InformationBufferLength < sizeof(ULONG))
|
||||
{
|
||||
*BytesNeeded = sizeof(ULONG);
|
||||
Status = NDIS_STATUS_INVALID_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
|
||||
{
|
||||
return NDIS_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
*BytesRead = sizeof(ULONG);
|
||||
NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG));
|
||||
|
||||
Adapter->WakeUpFlags = GenericUlong;
|
||||
break;
|
||||
}
|
||||
|
||||
case OID_PNP_ADD_WAKE_UP_PATTERN:
|
||||
{
|
||||
if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
|
||||
{
|
||||
*BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
|
||||
Status = NDIS_STATUS_INVALID_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
|
||||
{
|
||||
return NDIS_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
*BytesRead = sizeof(NDIS_PM_PACKET_PATTERN);
|
||||
|
||||
Status = DcAddWakeUpPattern(Adapter, InformationBuffer);
|
||||
break;
|
||||
}
|
||||
|
||||
case OID_PNP_REMOVE_WAKE_UP_PATTERN:
|
||||
{
|
||||
if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
|
||||
{
|
||||
*BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
|
||||
Status = NDIS_STATUS_INVALID_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
|
||||
{
|
||||
return NDIS_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
*BytesRead = sizeof(NDIS_PM_PACKET_PATTERN);
|
||||
|
||||
Status = DcRemoveWakeUpPattern(Adapter, InformationBuffer);
|
||||
break;
|
||||
}
|
||||
|
||||
case OID_PNP_SET_POWER:
|
||||
{
|
||||
if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))
|
||||
{
|
||||
*BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
|
||||
Status = NDIS_STATUS_INVALID_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
|
||||
{
|
||||
return NDIS_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
*BytesRead = sizeof(ULONG);
|
||||
NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG));
|
||||
|
||||
if (GenericUlong < NdisDeviceStateD0 || GenericUlong > NdisDeviceStateD3)
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
Status = NDIS_STATUS_INVALID_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
DcSetPower(Adapter, GenericUlong);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Status = NDIS_STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
313
drivers/network/dd/dc21x4/send.c
Normal file
313
drivers/network/dd/dc21x4/send.c
Normal file
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Packet sending
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "dc21x4.h"
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
DcTransmitPacket(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PDC_TCB Tcb,
|
||||
_In_ PSCATTER_GATHER_LIST SgList)
|
||||
{
|
||||
PDC_TBD Tbd, NextTbd, FirstTbd, LastTbd;
|
||||
ULONG i, TbdStatus;
|
||||
|
||||
TbdStatus = 0;
|
||||
Tbd = Adapter->CurrentTbd;
|
||||
|
||||
for (i = 0; i < SgList->NumberOfElements; ++i)
|
||||
{
|
||||
ULONG Address, Length;
|
||||
|
||||
LastTbd = Tbd;
|
||||
|
||||
/* Not owned by NIC */
|
||||
ASSERT(!(((i % 2) == 0) && (Tbd->Status & DC_TBD_STATUS_OWNED)));
|
||||
|
||||
Tbd->Status = TbdStatus;
|
||||
|
||||
/* 32-bit DMA */
|
||||
ASSERT(SgList->Elements[i].Address.HighPart == 0);
|
||||
|
||||
Address = SgList->Elements[i].Address.LowPart;
|
||||
Length = SgList->Elements[i].Length;
|
||||
|
||||
/* Two data buffers per descriptor */
|
||||
if ((i % 2) == 0)
|
||||
{
|
||||
Tbd->Control &= DC_TBD_CONTROL_END_OF_RING;
|
||||
|
||||
Tbd->Control |= Length;
|
||||
Tbd->Address1 = Address;
|
||||
|
||||
NextTbd = DC_NEXT_TBD(Adapter, Tbd);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tbd->Control |= Length << DC_TBD_CONTROL_LENGTH_2_SHIFT;
|
||||
Tbd->Address2 = Address;
|
||||
|
||||
Tbd = NextTbd;
|
||||
TbdStatus = DC_TBD_STATUS_OWNED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable IRQ on last element */
|
||||
LastTbd->Control |= DC_TBD_CONTROL_LAST_FRAGMENT | DC_TBD_CONTROL_REQUEST_INTERRUPT;
|
||||
|
||||
Tcb->Tbd = LastTbd;
|
||||
|
||||
FirstTbd = Adapter->CurrentTbd;
|
||||
Adapter->CurrentTbd = NextTbd;
|
||||
|
||||
/* Not owned by NIC */
|
||||
ASSERT(!(FirstTbd->Status & DC_TBD_STATUS_OWNED));
|
||||
|
||||
FirstTbd->Control |= DC_TBD_CONTROL_FIRST_FRAGMENT;
|
||||
DC_WRITE_BARRIER();
|
||||
FirstTbd->Status = DC_TBD_STATUS_OWNED;
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
DcCopyPacket(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PNDIS_PACKET Packet,
|
||||
_In_ PDC_COALESCE_BUFFER Buffer)
|
||||
{
|
||||
PNDIS_BUFFER CurrentBuffer;
|
||||
PVOID Address;
|
||||
UINT CurrentLength, PacketLength;
|
||||
PUCHAR Destination;
|
||||
|
||||
NdisGetFirstBufferFromPacketSafe(Packet,
|
||||
&CurrentBuffer,
|
||||
&Address,
|
||||
&CurrentLength,
|
||||
&PacketLength,
|
||||
HighPagePriority);
|
||||
if (!Address)
|
||||
return FALSE;
|
||||
|
||||
Destination = Buffer->VirtualAddress;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
NdisMoveMemory(Destination, Address, CurrentLength);
|
||||
Destination += CurrentLength;
|
||||
|
||||
NdisGetNextBuffer(CurrentBuffer, &CurrentBuffer);
|
||||
if (!CurrentBuffer)
|
||||
break;
|
||||
|
||||
NdisQueryBufferSafe(CurrentBuffer,
|
||||
&Address,
|
||||
&CurrentLength,
|
||||
HighPagePriority);
|
||||
if (!Address)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
NDIS_STATUS
|
||||
DcSendPacket(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ PNDIS_PACKET Packet)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
PSCATTER_GATHER_LIST SgList;
|
||||
PDC_TCB Tcb;
|
||||
ULONG SlotsUsed;
|
||||
|
||||
if (!Adapter->TcbSlots)
|
||||
return NDIS_STATUS_RESOURCES;
|
||||
|
||||
SgList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo);
|
||||
|
||||
if (SgList->NumberOfElements > DC_FRAGMENTATION_THRESHOLD)
|
||||
{
|
||||
PDC_COALESCE_BUFFER CoalesceBuffer;
|
||||
UINT PacketLength;
|
||||
|
||||
if (!Adapter->TbdSlots || !Adapter->SendBufferList.Next)
|
||||
{
|
||||
return NDIS_STATUS_RESOURCES;
|
||||
}
|
||||
|
||||
NdisQueryPacketLength(Packet, &PacketLength);
|
||||
|
||||
CoalesceBuffer = (PDC_COALESCE_BUFFER)PopEntryList(&Adapter->SendBufferList);
|
||||
|
||||
if (!DcCopyPacket(Adapter, Packet, CoalesceBuffer))
|
||||
{
|
||||
PushEntryList(&Adapter->SendBufferList, &CoalesceBuffer->ListEntry);
|
||||
return NDIS_STATUS_RESOURCES;
|
||||
}
|
||||
|
||||
SgList = &Adapter->LocalSgList;
|
||||
SgList->Elements[0].Address.LowPart = CoalesceBuffer->PhysicalAddress;
|
||||
SgList->Elements[0].Length = PacketLength;
|
||||
SgList->NumberOfElements = 1;
|
||||
SlotsUsed = 1;
|
||||
|
||||
Tcb = Adapter->CurrentTcb;
|
||||
Tcb->SlotsUsed = 1;
|
||||
Tcb->Buffer = CoalesceBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We use two data buffers per descriptor */
|
||||
SlotsUsed = (SgList->NumberOfElements + 1) / 2;
|
||||
|
||||
if (SlotsUsed > Adapter->TbdSlots)
|
||||
return NDIS_STATUS_RESOURCES;
|
||||
|
||||
Tcb = Adapter->CurrentTcb;
|
||||
Tcb->SlotsUsed = SlotsUsed;
|
||||
Tcb->Buffer = NULL;
|
||||
}
|
||||
|
||||
--Adapter->TcbSlots;
|
||||
|
||||
Adapter->CurrentTcb = DC_NEXT_TCB(Adapter, Tcb);
|
||||
|
||||
Tcb->Packet = Packet;
|
||||
|
||||
ASSERT(Adapter->TbdSlots >= Tcb->SlotsUsed);
|
||||
Adapter->TbdSlots -= SlotsUsed;
|
||||
|
||||
DcTransmitPacket(Adapter, Tcb, SgList);
|
||||
|
||||
DC_WRITE(Adapter, DcCsr1_TxPoll, DC_TX_POLL_DOORBELL);
|
||||
|
||||
return NDIS_STATUS_PENDING;
|
||||
}
|
||||
|
||||
VOID
|
||||
DcProcessPendingPackets(
|
||||
_In_ PDC21X4_ADAPTER Adapter)
|
||||
{
|
||||
PLIST_ENTRY Entry;
|
||||
NDIS_STATUS Status;
|
||||
PNDIS_PACKET Packet;
|
||||
|
||||
ASSERT(!IsListEmpty(&Adapter->SendQueueList));
|
||||
|
||||
do
|
||||
{
|
||||
Entry = RemoveHeadList(&Adapter->SendQueueList);
|
||||
|
||||
Packet = DC_PACKET_FROM_LIST_ENTRY(Entry);
|
||||
|
||||
Status = DcSendPacket(Adapter, Packet);
|
||||
if (Status == NDIS_STATUS_RESOURCES)
|
||||
{
|
||||
InsertHeadList(&Adapter->SendQueueList, DC_LIST_ENTRY_FROM_PACKET(Packet));
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!IsListEmpty(&Adapter->SendQueueList));
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcSendPackets(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ PPNDIS_PACKET PacketArray,
|
||||
_In_ UINT NumberOfPackets)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
NDIS_STATUS Status;
|
||||
ULONG i;
|
||||
|
||||
NdisAcquireSpinLock(&Adapter->SendLock);
|
||||
|
||||
if (!(Adapter->Flags & DC_ACTIVE))
|
||||
{
|
||||
NdisReleaseSpinLock(&Adapter->SendLock);
|
||||
|
||||
for (i = 0; i < NumberOfPackets; ++i)
|
||||
{
|
||||
NdisMSendComplete(Adapter->AdapterHandle,
|
||||
PacketArray[i],
|
||||
NDIS_STATUS_NOT_ACCEPTED);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE("Send packets %u\n", NumberOfPackets);
|
||||
|
||||
for (i = 0; i < NumberOfPackets; ++i)
|
||||
{
|
||||
PNDIS_PACKET Packet = PacketArray[i];
|
||||
|
||||
Status = DcSendPacket(Adapter, Packet);
|
||||
if (Status == NDIS_STATUS_RESOURCES)
|
||||
{
|
||||
InsertTailList(&Adapter->SendQueueList, DC_LIST_ENTRY_FROM_PACKET(Packet));
|
||||
}
|
||||
}
|
||||
|
||||
NdisReleaseSpinLock(&Adapter->SendLock);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DcCancelSendPackets(
|
||||
_In_ NDIS_HANDLE MiniportAdapterContext,
|
||||
_In_ PVOID CancelId)
|
||||
{
|
||||
PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
||||
LIST_ENTRY DoneList;
|
||||
PLIST_ENTRY Entry, NextEntry;
|
||||
|
||||
TRACE("Called\n");
|
||||
|
||||
InitializeListHead(&DoneList);
|
||||
|
||||
NdisAcquireSpinLock(&Adapter->SendLock);
|
||||
|
||||
NextEntry = Adapter->SendQueueList.Flink;
|
||||
while (NextEntry != &Adapter->SendQueueList)
|
||||
{
|
||||
PNDIS_PACKET Packet;
|
||||
|
||||
Entry = NextEntry;
|
||||
NextEntry = NextEntry->Flink;
|
||||
|
||||
Packet = DC_PACKET_FROM_LIST_ENTRY(Entry);
|
||||
|
||||
if (NDIS_GET_PACKET_CANCEL_ID(Packet) == CancelId)
|
||||
{
|
||||
RemoveEntryList(DC_LIST_ENTRY_FROM_PACKET(Packet));
|
||||
|
||||
InsertTailList(&DoneList, DC_LIST_ENTRY_FROM_PACKET(Packet));
|
||||
}
|
||||
}
|
||||
|
||||
NdisReleaseSpinLock(&Adapter->SendLock);
|
||||
|
||||
while (!IsListEmpty(&DoneList))
|
||||
{
|
||||
Entry = RemoveHeadList(&DoneList);
|
||||
|
||||
NdisMSendComplete(Adapter->AdapterHandle,
|
||||
DC_PACKET_FROM_LIST_ENTRY(Entry),
|
||||
NDIS_STATUS_REQUEST_ABORTED);
|
||||
}
|
||||
}
|
115
drivers/network/dd/dc21x4/sendrcv.h
Normal file
115
drivers/network/dd/dc21x4/sendrcv.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Send and receive definitions
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define DC_LIST_ENTRY_FROM_PACKET(Packet) \
|
||||
((PLIST_ENTRY)(&(Packet)->MiniportReservedEx[0]))
|
||||
|
||||
#define DC_PACKET_FROM_LIST_ENTRY(ListEntry) \
|
||||
(CONTAINING_RECORD(ListEntry, NDIS_PACKET, MiniportReservedEx))
|
||||
|
||||
#define DC_RCB_FROM_PACKET(Packet) \
|
||||
((PDC_RCB*)&(Packet)->MiniportReservedEx[0])
|
||||
|
||||
#define DC_RBD_FROM_PACKET(Packet) \
|
||||
((PDC_RBD*)&(Packet)->MiniportReservedEx[sizeof(PVOID)])
|
||||
|
||||
typedef struct _DC_COALESCE_BUFFER
|
||||
{
|
||||
/* Must be the first entry */
|
||||
SINGLE_LIST_ENTRY ListEntry;
|
||||
|
||||
PVOID VirtualAddress;
|
||||
ULONG PhysicalAddress;
|
||||
} DC_COALESCE_BUFFER, *PDC_COALESCE_BUFFER;
|
||||
|
||||
typedef struct _DC_TCB
|
||||
{
|
||||
PDC_TBD Tbd;
|
||||
PNDIS_PACKET Packet;
|
||||
PDC_COALESCE_BUFFER Buffer;
|
||||
ULONG SlotsUsed;
|
||||
} DC_TCB, *PDC_TCB;
|
||||
|
||||
typedef struct _DC_RCB
|
||||
{
|
||||
/* Must be the first entry */
|
||||
SINGLE_LIST_ENTRY ListEntry;
|
||||
|
||||
ULONG PhysicalAddress;
|
||||
ULONG Flags;
|
||||
#define DC_RCB_FLAG_RECLAIM 0x80000000
|
||||
|
||||
PNDIS_PACKET Packet;
|
||||
PNDIS_BUFFER NdisBuffer;
|
||||
PVOID VirtualAddress;
|
||||
PVOID VirtualAddressOriginal;
|
||||
NDIS_PHYSICAL_ADDRESS PhysicalAddressOriginal;
|
||||
SINGLE_LIST_ENTRY AllocListEntry;
|
||||
} DC_RCB, *PDC_RCB;
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
DC_RELEASE_TCB(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PDC_TCB Tcb)
|
||||
{
|
||||
if (Tcb->Buffer)
|
||||
{
|
||||
PushEntryList(&Adapter->SendBufferList, &Tcb->Buffer->ListEntry);
|
||||
}
|
||||
|
||||
++Adapter->TcbSlots;
|
||||
|
||||
Adapter->TbdSlots += Tcb->SlotsUsed;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
PDC_TCB
|
||||
DC_NEXT_TCB(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PDC_TCB Tcb)
|
||||
{
|
||||
if (Tcb++ == Adapter->TailTcb)
|
||||
return Adapter->HeadTcb;
|
||||
else
|
||||
return Tcb;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
PDC_TBD
|
||||
DC_NEXT_TBD(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PDC_TBD Tbd)
|
||||
{
|
||||
if (Tbd++ == Adapter->TailTbd)
|
||||
return Adapter->HeadTbd;
|
||||
else
|
||||
return Tbd;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
PDC_RBD
|
||||
DC_NEXT_RBD(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PDC_RBD Rbd)
|
||||
{
|
||||
if (Rbd++ == Adapter->TailRbd)
|
||||
return Adapter->HeadRbd;
|
||||
else
|
||||
return Rbd;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
PDC_RCB*
|
||||
DC_GET_RCB_SLOT(
|
||||
_In_ PDC21X4_ADAPTER Adapter,
|
||||
_In_ PDC_RBD Rbd)
|
||||
{
|
||||
return Adapter->RcbArray + (((ULONG_PTR)(Rbd - Adapter->HeadRbd)));
|
||||
}
|
84
drivers/network/dd/dc21x4/util.h
Normal file
84
drivers/network/dd/dc21x4/util.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* PROJECT: ReactOS DC21x4 Driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Utility header file
|
||||
* COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pshpack1.h>
|
||||
typedef struct _ETH_HEADER
|
||||
{
|
||||
UCHAR Destination[ETH_LENGTH_OF_ADDRESS];
|
||||
UCHAR Source[ETH_LENGTH_OF_ADDRESS];
|
||||
USHORT PayloadType;
|
||||
} ETH_HEADER, *PETH_HEADER;
|
||||
#include <poppack.h>
|
||||
|
||||
#define ETH_IS_LOCALLY_ADMINISTERED(Address) \
|
||||
((BOOLEAN)(((PUCHAR)(Address))[0] & ((UCHAR)0x02)))
|
||||
|
||||
#define ETH_IS_EMPTY(Address) \
|
||||
((BOOLEAN)((((PUCHAR)(Address))[0] | ((PUCHAR)(Address))[1] | ((PUCHAR)(Address))[2] | \
|
||||
((PUCHAR)(Address))[3] | ((PUCHAR)(Address))[4] | ((PUCHAR)(Address))[5]) == 0))
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_AMD64)
|
||||
/* Strict memory model, does not reorder Write-Write operations */
|
||||
#define DC_WRITE_BARRIER() KeMemoryBarrierWithoutFence()
|
||||
#else
|
||||
#define DC_WRITE_BARRIER() KeMemoryBarrier()
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/*
|
||||
* Merge with PAGE, we don't need a new pageable section. For a small amount of data,
|
||||
* there is additional size overhead if the actual data size is smaller than section alignment.
|
||||
* GCC doesn't seem to appreciate this idea.
|
||||
*/
|
||||
#define DC_PG_DATA DATA_SEG("PAGE")
|
||||
#else
|
||||
#define DC_PG_DATA
|
||||
#endif
|
||||
|
||||
/* Access to unaligned memory */
|
||||
FORCEINLINE
|
||||
USHORT
|
||||
DcRetrieveWord(
|
||||
_In_ const VOID* Data)
|
||||
{
|
||||
#if defined(_M_IX86) || defined(_M_AMD64)
|
||||
/* Supported by ISA */
|
||||
return *(const UNALIGNED USHORT*)Data;
|
||||
#else
|
||||
USHORT Result;
|
||||
|
||||
NdisMoveMemory(&Result, Data, sizeof(Result));
|
||||
return Result;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DBG
|
||||
#define DcPopEntryList PopEntryList
|
||||
#else
|
||||
/*
|
||||
* This is an optimized version of the PopEntryList() function.
|
||||
* We assume that the next entry has already been checked for nullability
|
||||
* so we don't need to.
|
||||
*/
|
||||
FORCEINLINE
|
||||
PSINGLE_LIST_ENTRY
|
||||
DcPopEntryList(
|
||||
_Inout_ PSINGLE_LIST_ENTRY ListHead)
|
||||
{
|
||||
PSINGLE_LIST_ENTRY FirstEntry;
|
||||
|
||||
FirstEntry = ListHead->Next;
|
||||
|
||||
ASSERT(FirstEntry);
|
||||
|
||||
ListHead->Next = FirstEntry->Next;
|
||||
|
||||
return FirstEntry;
|
||||
}
|
||||
#endif
|
Loading…
Reference in a new issue