reactos/drivers/network/dd/dc21x4/media.c
Joachim Henze 3e6f65ffcd
[DC21X4] Fix uninitialized variable read (#6984)
This is the network driver which is used for MSVPC 2007.

I spotted it during a WIP-backport-experiment of the driver, when compiling with GCC4.7.2, which warned about it.
GCC8.4.0 unfortunately is blind to that on master head, for unknown reasons. Not good.
MSVC github buildbot is also blind to that on master head, for unknown reasons. Not good.
We later found that at least Clang did also warn about it on master head.
2024-06-13 21:24:23 +02:00

637 lines
19 KiB
C

/*
* 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, 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
{
ULONG MiiAdvertising, MiiControl;
Adapter->DefaultMedia = MEDIA_MII;
switch (MediaNumber)
{
case MEDIA_10T:
MiiAdvertising = MII_ADV_10T_HD;
MiiControl = 0;
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;
MiiControl = 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;
}
}