diff options
Diffstat (limited to 'private/ntos/ndis/dc21x4/miiphy.c')
-rw-r--r-- | private/ntos/ndis/dc21x4/miiphy.c | 1913 |
1 files changed, 1913 insertions, 0 deletions
diff --git a/private/ntos/ndis/dc21x4/miiphy.c b/private/ntos/ndis/dc21x4/miiphy.c new file mode 100644 index 000000000..e06d02195 --- /dev/null +++ b/private/ntos/ndis/dc21x4/miiphy.c @@ -0,0 +1,1913 @@ +/*+ + * file: miiphy.c + * + * Copyright (C) 1992-1995 by + * Digital Equipment Corporation, Maynard, Massachusetts. + * All rights reserved. + * + * This software is furnished under a license and may be used and copied + * only in accordance of the terms of such license and with the + * inclusion of the above copyright notice. This software or any other + * copies thereof may not be provided or otherwise made available to any + * other person. No title to and ownership of the software is hereby + * transferred. + * + * The information in this software is subject to change without notice + * and should not be construed as a commitment by digital equipment + * corporation. + * + * Digital assumes no responsibility for the use or reliability of its + * software on equipment which is not supplied by digital. + * + * + * Abstract: This file contains the code to support the MII protocol + * to access the PHY chip. + * This file is part of the DEC's DC21X4 Ethernet Controller + * driver + * + * Author: Claudio Hazan + * + * Revision History: + * + * 20-Nov-95 ch Initial version + * 20-Dec-95 phk Cleanup + * +-*/ + +#include <precomp.h> + + +/*+ + * + * MiiPhyInit + * + * Description : Initializes Mii PHY entry variables. + * Searches for PHY in given address, initializes it if found. + * + * Input parameters: + * + * PDC21X4_ADAPTER - Adapter The Adapter's DS + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * + * Output parameters: + * + * None. +-*/ +extern +BOOLEAN +MiiPhyInit( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr + ) +{ + + USHORT i; + +#if MII_DBG + DbgPrint("MiiPhyInit\n"); +#endif + + if ( !(FindMiiPhyDevice(Adapter, PhyInfoPtr)) ) { + return FALSE; + } + +#if MII_DBG + DbgPrint("MiiPhyDevice FOUND!\n"); +#endif + + // Reset the PHY to return it to his default values + PhyInfoPtr->PhyExtRoutines.PhyAdminControl( + Adapter, + PhyInfoPtr, + MiiGenAdminReset + ); + + // Once the PHY is reset, read the values of its + // whole registers + + if ( !(FindMiiPhyDevice(Adapter, PhyInfoPtr)) ) { + return FALSE; + } + + // get and save PHY capabilities + PhyInfoPtr->PhyCapabilities = + PhyInfoPtr->PhyRegs[PhyStatusReg] & MiiPhyCapabilitiesMask; + + switch (PhyInfoPtr->PhyId) { + + case BCM5000_0: + +#if MII_DBG + DbgPrint("Broadcom PHY...\n"); +#endif + // allow Autosense + PhyInfoPtr->PhyCapabilities |= MiiPhyNwayCapable; + break; + } +#if MII_DBG + DbgPrint("PhyCapabilities = %04x\n", PhyInfoPtr->PhyCapabilities); +#endif + + // get and save PHY's NWAY Advertisement + PhyInfoPtr->PhyIntRoutines.PhyNwayGetLocalAbility( + Adapter, + PhyInfoPtr, + &(PhyInfoPtr->PhyMediaAdvertisement) + ); +#if MII_DBG + DbgPrint("PhyMediaAdvertisement = %04x\n", PhyInfoPtr->PhyMediaAdvertisement); +#endif + + // put the PHY in operational mode + PhyInfoPtr->PhyExtRoutines.PhyAdminControl( + Adapter, + PhyInfoPtr, + MiiGenAdminOperational + ); + + /* mark that PHY entry is valid */ + PhyInfoPtr->StructValid = TRUE; + +#if MII_DBG + DbgPrint("MiiPhyInit Done\n"); +#endif + return TRUE; + +} + + +/*+ + * + * MiiPhyGetCapabilities + * + * Description : Returns the PHY capabilities. + + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * + * Output parameters: + * + * Capabilities - CAPABILITY + * + * +-*/ +extern +void +MiiPhyGetCapabilities( + PMII_PHY_INFO PhyInfoPtr, + CAPABILITY *Capabilities + ) +{ +#if MII_DBG + DbgPrint("MiiPhyGetCapabilities\n"); +#endif + *Capabilities = PhyInfoPtr->PhyCapabilities; + return; +} + + + + +/*+ + * + * MiiPhySetConnectionType + * + * Description: + * + * if (Connection == NWAY) then + * if (Advertisement != 0 ) + * Change LocalAdvertisement + * and Set RestartNway bit + * set NWAy bit On in CTRL register + * else + * Translate Media to appropriate control bits + * write CTRL reg + * and return success + * + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * Connection - USHORT + * Advertisement - USHORT + * + * Output parameters: + * + * None. + * + * On return - FALSE if PHY does not support Connection, TRUE otherwise. + * +-*/ +extern +BOOLEAN +MiiPhySetConnectionType( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr, + USHORT Connection, + USHORT Advertisement + ) +{ +#if MII_DBG + DbgPrint("MiiPhySetConnectionType\n"); +#endif + // Check if the PHY supports this connection ? + if(!CheckConnectionSupport( + PhyInfoPtr, + Connection + )){ +#if MII_DBG + DbgPrint("***The Connection %04x is not supported by the Phy\n", Connection); +#endif + return FALSE; + } + + // Convert Connection type to Control_word + ConvertConnectionToControl( + PhyInfoPtr, + &Connection + ); + + // Clear Previous Connection bits from Control_word + // (Leave only Isolate and Power-down bits) + PhyInfoPtr->PhyRegs[PhyControlReg] &= + (MiiPhyCtrlIsolate | MiiPhyCtrlPowerDown); + + // Create the new Control_word + PhyInfoPtr->PhyRegs[PhyControlReg] |= Connection; + + // If operation mode is NWAY - set its parameters + if (Connection & MiiPhyCtrlEnableNway) { + PhyInfoPtr->PhyIntRoutines.PhyNwaySetLocalAbility( + Adapter, + PhyInfoPtr, + Advertisement + ); + } + + // write the new control word +#if MII_DBG + DbgPrint("New Control_word= %04x\n", PhyInfoPtr->PhyRegs[PhyControlReg]); +#endif + PhyInfoPtr ->PhyIntRoutines.PhyWriteRegister( + Adapter, + PhyInfoPtr , + PhyControlReg, + PhyInfoPtr->PhyRegs[PhyControlReg] + ); + + // Don't save RestartNway bit ! + PhyInfoPtr ->PhyRegs[PhyControlReg] &= ~MiiPhyCtrlRestartNway; + + switch (PhyInfoPtr ->PhyId) { + + case BCM5000_0: + + // Need to be reset between 10Base to 100Base transitions +#if MII_DBG + DbgPrint("Broadcom - 10B to 100B transition\n"); +#endif + HandleBroadcomMediaChangeFrom10To100( + Adapter, + PhyInfoPtr + ); + break; + } + + return TRUE; +} + +/*+ + * + * MiiPhyGetConnectionType + * + * Description: + * + * Returns selected connection of the PHY. + * If PHY connection is not yet resolved and wait is required, + * waits for connection resolution and returns it. + * If not - returns error status. + * + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * + * Output parameters: + * + * ConnectionStatus - Status + * + * On Return + * Upon error - FALSE + * ConnectionStatus - error status + * + * Upon success - TRUE + * ConnectionStatus - selected connection. + * + *Remarks: + * + * We use the NWAY capable bit in the PHY capabilities field to + * overcome Broadcom's AutoSense issue. + * +-*/ +extern +BOOLEAN +MiiPhyGetConnectionType( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr, + PUSHORT ConnectionStatus + ) +{ + + CAPABILITY LocalAbility; + CAPABILITY PartnerAbility; + CAPABILITY Ability; + USHORT Register; + +#if MII_DBG + DbgPrint("MiiPhyGetConnectionType\n"); +#endif + switch (PhyInfoPtr->PhyId) { + + case BCM5000_0: + + if (!GetBroadcomPhyConnectionType( + Adapter, + PhyInfoPtr, + ConnectionStatus + ) + ) { + +#if MII_DBG + DbgPrint("***Connection not supported by Broadcom's Phy\n"); +#endif + *ConnectionStatus = MAC_CONN_UNKNOWN; + return FALSE; + } + else { + HandleBroadcomMediaChangeFrom10To100( + Adapter, + PhyInfoPtr + ); + return TRUE; + } + break; + + default: + + if (PhyInfoPtr->PhyRegs[PhyControlReg] & MiiPhyCtrlEnableNway) { + + // NWAY selected: + // get partner and local abilities, + // use them to retrieve the selected connection type +#if MII_DBG + DbgPrint("Not Broadcom PHY: enable NWAY\n"); +#endif + PhyInfoPtr->PhyIntRoutines.PhyNwayGetLocalAbility( + Adapter, + PhyInfoPtr, + &LocalAbility + ); + + PhyInfoPtr->PhyIntRoutines.PhyNwayGetPartnerAbility( + Adapter, + PhyInfoPtr, + &PartnerAbility + ); + + Ability = LocalAbility & PartnerAbility; +#if MII_DBG + DbgPrint("LocalAbility : %04x\n",LocalAbility); + DbgPrint("PartnerAbility : %04x\n",PartnerAbility); +#endif + + if (!Ability){ + // No common mode: +#if MII_DBG + DbgPrint("No Common Mode...\n"); +#endif + + if (PhyInfoPtr->PhyId == DP83840_0) { + + //National's Phy Speed Sensing workaround: + //read the Speed_bit in the PAR register to sense + //the connection speed + + if (PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr , + NatPhyParRegister, + &Register + )) { + + Ability = (LocalAbility & + ((Register & PAR_SPEED_10) ? MiiPhy10BaseT : MiiPhy100BaseTx) >>6); +#if MII_DBG + DbgPrint("National: Ability : %04x\n", Ability); +#endif + } + } + } + return (Ability ? + ConvertNwayToConnectionType(Ability, ConnectionStatus) : FALSE); + } + else { + + // Nway not supported or not selected, + // connection has been selected via CommandReg + + if (PhyInfoPtr->PhyRegs[PhyControlReg] & MiiPhyCtrlDuplexMode) { + + // Full Duplex Medium + + *ConnectionStatus = + (PhyInfoPtr->PhyRegs[PhyControlReg] & MiiPhyCtrlSpeed100) ? + MediumMii100BaseTxFullDuplex : MediumMii10BaseTFullDuplex; +#if MII_DBG + DbgPrint("Full Duplex Medium; ConnectionStatus= %04x\n",*ConnectionStatus); +#endif + } + else if (PhyInfoPtr->PhyRegs[PhyControlReg] & MiiPhyCtrlSpeed100) { + + *ConnectionStatus = + (PhyInfoPtr->PhyRegs[PhyStatusReg] & MiiPhy100BaseTx) ? + MediumMii100BaseTx : MediumMii100BaseT4; + } + else{ + *ConnectionStatus = MediumMii10BaseT; + } +#if MII_DBG + DbgPrint("ConnectionStatus= %04x\n",*ConnectionStatus); +#endif + return TRUE; + } + } + +} + +/*+ + * + * MiiPhyGetConnectionStatus + * + * Description: + * + * Returns the connection status of the PHY. + * Rewrites the command word read from the PHY in its entry + * in the PhysArray. + * + * Connection status has the following attributes: + * NwayAdminStatus + * MAUStatus + * + *On Entry: + * PhyInfoPtr + * + *On Return: + * ConnectionStatus : + * High byte - Nwaystatus + * Low byte - LinkStatus + * + *On return + * TRUE - on success + * FALSE - on fail, the return Connection Status is not valid + * +-*/ +extern +BOOLEAN +MiiPhyGetConnectionStatus ( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr , + PUSHORT ConnectionStatus + ) +{ + + //Init all Status bytes to UNKNOWN + CAPABILITY NwayStatus=NWAY_UNKNOWN; + CAPABILITY LinkStatus=MEDIA_STATE_UNKNOWN; + + CAPABILITY Ability; + CAPABILITY LocalAbility; + CAPABILITY PartnerAbility; + + ULONG Register; + +#if MII_DBG + DbgPrint("MiiPhyGetConnectionStatus\n"); +#endif + // Read and save Control Reg since the speed selection may be + // forced via an hardware pin causing the software selection + // to be ignored + + if (!PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr , + PhyControlReg, + &(PhyInfoPtr->PhyRegs[PhyControlReg]) + )) { + + LinkStatus = MEDIA_READ_REGISTER_FAILED; + *ConnectionStatus = NwayStatus | LinkStatus; + return FALSE; + } + +#if MII_DBG + DbgPrint("PHY's ControlReg = %04x\n",PhyInfoPtr->PhyRegs[PhyControlReg]); +#endif + + // Read & save Status word + if (!PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + PhyStatusReg, + &(PhyInfoPtr->PhyRegs[PhyStatusReg]) + )) { + LinkStatus = MEDIA_READ_REGISTER_FAILED; + *ConnectionStatus = NwayStatus | LinkStatus; + return FALSE; + } +#if MII_DBG + DbgPrint("PHY's StatusReg = %04x\n",PhyInfoPtr->PhyRegs[PhyStatusReg]); +#endif + if (PhyInfoPtr->PhyRegs[PhyStatusReg] == 0){ + LinkStatus = MEDIA_READ_REGISTER_FAILED; + *ConnectionStatus = NwayStatus | LinkStatus; + return FALSE; + } + + // Set Nway status according to Nway complete & ability bits & enable + + switch (PhyInfoPtr->PhyId) { + + case BCM5000_0: + + // Broadcom + + if (PhyInfoPtr ->PhyRegs[PhyControlReg] & MiiPhyCtrlEnableNway) { + + NwayStatus = NWAY_COMPLETE; + } + else { + + NwayStatus = NWAY_DISABLED; + } + break; + + default: + + if (PhyInfoPtr ->PhyRegs[PhyStatusReg] & MiiPhyNwayCapable) { + + if (PhyInfoPtr ->PhyRegs[PhyControlReg] & MiiPhyCtrlEnableNway) { + + if (PhyInfoPtr ->PhyRegs[PhyStatusReg] & MiiPhyNwayComplete) { + NwayStatus = NWAY_COMPLETE; + } + else { + // assume configuration not done yet + NwayStatus = NWAY_CONFIGURING; + *ConnectionStatus = NwayStatus | LinkStatus; + return FALSE; + } + } + else { + NwayStatus = NWAY_DISABLED; + } + } + else { + NwayStatus = NWAY_NOT_SUPPORTED; + } + } + + // Set link status according to link bit. + // Since LinkStatus bit latches Link-Fail status + // the link status is find as follows: + // + // If Status Reg indicate LinkPass then + // LinkStatus=LINK_PASS + // else + // Read Status Register + // If Status Reg indicate LinkPass then + // LinkStatus=LINK_PASS_WITH_PF + // else + // LinkStatus=LINK_FAIL + // endif + // endif + + + // Check if the Link status indicates a + // PHY's supported medium + // Only if the Phy is NWAY's Capable or NWAY is enabled + + if (NwayStatus == NWAY_COMPLETE) { + + PhyInfoPtr->PhyIntRoutines.PhyNwayGetLocalAbility( + Adapter, + PhyInfoPtr, + &LocalAbility + ); + + PhyInfoPtr->PhyIntRoutines.PhyNwayGetPartnerAbility( + Adapter, + PhyInfoPtr, + &PartnerAbility + ); + + if (PhyInfoPtr->PhyId == DP83840_0) { + + //National's Phy Speed Sensing workaround: + //read the Speed_bit in the PAR register to sense + //the connection speed + + if (PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr , + NatPhyParRegister, + &Register + )) { + + Ability = (LocalAbility & + ((Register & PAR_SPEED_10) ? MiiPhy10BaseT : MiiPhy100BaseTx ) >>6); +#if MII_DBG + DbgPrint("National: Speed sense -> %s\n", + (Register & PAR_SPEED_10) ? "10Mbps" : "100Mbps" ); +#endif + } + } + else { + Ability = LocalAbility & PartnerAbility; + } + + if (!(Ability)) { + LinkStatus = MEDIA_LINK_FAIL; + *ConnectionStatus = NwayStatus | LinkStatus; + return FALSE; + } + } + + if (!(PhyInfoPtr->PhyRegs[PhyStatusReg] & MiiPhyLinkStatus)) { + + // Link fail: Read again Status Reg + if (!PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + PhyStatusReg, + &(PhyInfoPtr->PhyRegs[PhyStatusReg]) + )) { + return FALSE; + } + + if (!(PhyInfoPtr->PhyRegs[PhyStatusReg] & MiiPhyLinkStatus)) { + + // Link bit is still in Fail state + LinkStatus = MEDIA_LINK_FAIL; + } + else { +#if MII_DBG + DbgPrint("LinkPass with Previous Failure\n"); +#endif + LinkStatus = MEDIA_LINK_PASS_WITH_PF; + } + } + else { + LinkStatus = MEDIA_LINK_PASS; + } + + *ConnectionStatus = NwayStatus | LinkStatus; + return (LinkStatus != MEDIA_LINK_FAIL); + +} + +/*+ + * + * MiiPhyAdminControl + * + * Description: + * + * Performs the Control command on the specified Phy. + * Control command can be one of the following: + * Reset - reset the PHY (returns it to defaults) + * PowerDown + * StandBy + * Operational + * + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to MII_PHY_INFO + * Control - MII_STATUS + * + * AdminControlConversionTable - used in this routine + * + * Output parameters: + * + * None. + * +-*/ +extern +void +MiiPhyAdminControl( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr, + MII_STATUS Control + ) +{ + MII_STATUS Status = MiiGenAdminReset; + INT i = 0; + +#if MII_DBG + DbgPrint("MiiPhyAdminControl\n"); +#endif + + switch (Control) { + + case MiiGenAdminForce10: + case MiiGenAdminForce10Fd: + + PhyInfoPtr->PreviousControl = PhyInfoPtr->PhyRegs[PhyControlReg]; + PhyInfoPtr->PhyRegs[PhyControlReg] &= MiiPhyCtrlForce10; + Adapter->Force10 = TRUE; + break; + + case MiiGenAdminRelease10: + + PhyInfoPtr->PhyRegs[PhyControlReg] = PhyInfoPtr->PreviousControl; + Adapter->Force10 = FALSE; + break; + + default: + // Clear previous Control bits + PhyInfoPtr->PhyRegs[PhyControlReg] &= ~(MiiPhyCtrlReset | + MiiPhyCtrlPowerDown | + MiiPhyCtrlIsolate); + } + + // Write Control register +#if MII_DBG + DbgPrint("Write ControlReg = %04x\n",(PhyInfoPtr->PhyRegs[PhyControlReg]| + AdminControlConversionTable[Control])); +#endif + PhyInfoPtr->PhyIntRoutines.PhyWriteRegister( + Adapter, + PhyInfoPtr, + PhyControlReg, + (PhyInfoPtr->PhyRegs[PhyControlReg] | AdminControlConversionTable[Control]) + ); + + if (Control == MiiGenAdminReset) { + // Delay until reset done and chip stabilizes +#if MII_DBG + DbgPrint("Control = Reset; Delay until done and chip stabilizes\n"); +#endif + while ( (i++) < RESET_DELAY ) { + PhyInfoPtr->PhyExtRoutines.PhyAdminStatus( + Adapter, + PhyInfoPtr, + &Status + ); + if ( Status != MiiGenAdminReset ) { + break; + } + + } +#if MII_DBG + DbgPrint("Control = %x after Delay \n", Status); +#endif + } + + return; + +} + + +/*+ + * + * MiiPhyAdminStatus + * + * Description: + * + * Returns PHY admin status, which can be one of the following: + * Reset - reset process is in progress (not completed yet) + * PowerDown - Chip is in Power Down mode + * StandBy - Chip listening but not accessing mii data lines + * Operational - Chip is fully active + * + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to MII_PHY_INFO + * + * Output parameters: + * + * Status - MII_STATUS + * + * + * Note: Interrupts are disabled. + * +-*/ +extern +void +MiiPhyAdminStatus( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr, + PMII_STATUS Status + ) +{ + + USHORT RegVal = 0; + SHORT i = 3; + +#if MII_DBG + DbgPrint("MiiPhyAdminStatus\n"); +#endif + // Reads 3 times to garanty that 0 is a real value + while (i--) { + PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + PhyControlReg, + &RegVal + ); + if (RegVal) { + break; + } + } + + switch (RegVal) { + + case MiiPhyCtrlReset: + + *Status = MiiGenAdminReset; + break; + + case MiiPhyCtrlPowerDown: + + *Status = MiiGenAdminPowerDown; + break; + + case MiiPhyCtrlIsolate: + + *Status = MiiGenAdminStandBy; + break; + + default: + + *Status = MiiGenAdminOperational; + } +#if _DBG + DbgPrint("AdminStatus = %x\n", Status); +#endif + + return; +} + + + +//*************************************************************************** +//* Mii PHY Internal Routines * +//*************************************************************************** +/*+ + * + * MiiPhyReadRegister + * + * Description: + * + * Reads contents of register RegNum into *Register. + * + * Input parameters: + * + * PDC21X4_ADAPTER - Adapter The Adapter DS. + * PhyInfoPtr - PMII_PHY_INFO pointer to MII_PHY_INFO + * RegNum - USHORT # of register to be read + * + * Output parameters: + * + * *Register - USHORT contents of RegNum + * + * On return - TRUE if reading completed successfully, FALSE otherwise. + * + * + * + * +-----------------------------------------------------------------------+ + * | Management frame fields | + * +------+-------+----+----+-------+-------+----+------------------+------+ + * | | PRE | ST | OP | PHYAD | REGAD | TA | DATA | IDLE | + * +------+-------+----+----+-------+-------+----+------------------+------+ + * |Read | 1...1 | 01 | 10 | AAAAA | RRRRR | Z0 | DDDDDDDDDDDDDDDD | Z | + * +------+-------+----+----+-------+-------+----+------------------+------+ + * + * Note: Interrupts are disabled. + * +-*/ +extern +BOOLEAN +MiiPhyReadRegister( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr, + USHORT RegNum, + PUSHORT RegDat + ) +{ + ULONG CommandWord; + ULONG Tmp = 0; + USHORT Data = 0; + INT i; + INT SizeOfUshort = ((sizeof(USHORT))*8); + BOOLEAN Succeed=TRUE; + +#if _DBG + DbgPrint("MiiPhyReadRegister\n"); +#endif + // Write Preamble + WriteMii(Adapter, PRE, 2*SizeOfUshort); + + // Prepare command word + CommandWord = PhyInfoPtr->PhyAddress << PHY_ADDR_ALIGN; + CommandWord |= (RegNum << REG_ADDR_ALIGN); + CommandWord |= MII_READ_FRAME; +#if _DBG + DbgPrint("CommandWord=%08x\n", CommandWord); +#endif + WriteMii(Adapter, CommandWord, SizeOfUshort-2); + + MiiOutThreeState(Adapter); + + // Check that the PHY chip generated a zero bit the 2nd clock + DC21X4_READ_PORT( + DC21X4_IDPROM, + &Tmp + ); + + if (Tmp & MII_READ_DATA_MASK) { +#if _DBG + DbgPrint("***No Zero bit generated after 3 states\n"); +#endif + Succeed = FALSE; + } + + // read data WORD + (*RegDat) = 0; + for (i=0; i<SizeOfUshort; i++) { + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + MII_READ + ); + DELAY(MII_DELAY); + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + (MII_READ | MII_CLK) + ); + DELAY(MII_DELAY); + DC21X4_READ_PORT( + DC21X4_IDPROM, + &Tmp + ); + DELAY(MII_DELAY); + Data = (USHORT) ((Tmp >> MII_MDI_BIT_POSITION) & 0x0001); + (*RegDat) = ((*RegDat) << 1) | Data; + } + +#if _DBG + DbgPrint("&RegData=%08x Reg[%d]=%04x\n", RegDat, RegNum, *RegDat); +#endif + MiiOutThreeState(Adapter); + + // clear reserved bits + (*RegDat) &= ~PhyRegsReservedBitsMasks[RegNum]; +#if _DBG + DbgPrint("After Mask, Reg[%d]=%04x\n", RegNum, *RegDat); +#endif + + return Succeed; +} + + + + +/*+ + * + * MiiPhyWriteRegister + * + * Description: + * + * Writes contents of Register to register number RegNum. + * + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to MII_PHY_INFO + * RegNum - USHORT + * Register - USHORT + * + * Output parameters: + * + * None. + * + * + * +-----------------------------------------------------------------------+ + * | Management frame fields | + * +------+-------+----+----+-------+-------+----+------------------+------+ + * | | PRE | ST | OP | PHYAD | REGAD | TA | DATA | IDLE | + * +------+-------+----+----+-------+-------+----+------------------+------+ + * |Write | 1...1 | 01 | 01 | AAAAA | RRRRR | 10 | DDDDDDDDDDDDDDDD | Z | + * +------+-------+----+----+-------+-------+----+------------------+------+ + * + * Note: Interrupts are disabled. + * +-*/ +extern +void +MiiPhyWriteRegister( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr, + USHORT RegNum, + USHORT Register + ) +{ + + ULONG CommandWord; + INT SizeOfUshort = ((sizeof(USHORT))*8); + +#if _DBG + DbgPrint("MiiPhyWriteRegister\n"); +#endif + // Clear reserved bits + Register &= ~PhyRegsReservedBitsMasks[RegNum]; + + WriteMii(Adapter, PRE, 2*SizeOfUshort); + + // Prepare command word + CommandWord = (PhyInfoPtr->PhyAddress << PHY_ADDR_ALIGN); + CommandWord |= (RegNum << REG_ADDR_ALIGN); + CommandWord |= (MII_WRITE_FRAME | Register); + +#if _DBG + DbgPrint("CommandWord to write: %08x\n", CommandWord); +#endif + WriteMii(Adapter, CommandWord, 2*SizeOfUshort); + + MiiOutThreeState(Adapter); + return; +} + + + + +/*+ + * + * MiiPhyNwayGetLocalAbility + * + * Description: + * + * Returns local abilities of the PHY according to the value + * written in Nway Local Abilities register. + * + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to MII_PHY_INFO + * + * Output parameters + * + * *Ability - NwayCapacity + * + * +-*/ +extern +void +MiiPhyNwayGetLocalAbility( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr, + PCAPABILITY Ability + ) +{ + +#if MII_DBG + DbgPrint("MiiPhyNwayGetLocalAbility\n"); +#endif + + switch (PhyInfoPtr->PhyId) { + + case BCM5000_0: + + // Broadcom's PHY + *Ability = (PhyInfoPtr->PhyCapabilities >> 6); + break; + + default: + + if (PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + PhyNwayAdvertisement, + &(PhyInfoPtr->PhyRegs[PhyNwayAdvertisement]) + ) + ) { + + *Ability = PhyInfoPtr->PhyRegs[PhyNwayAdvertisement] & MiiPhyNwayCapabilitiesMask; + } + else { + *Ability = 0; + } + } + return; + +} + + + + +/*+ + * + * MiiPhyNwaySetLocalAbility + * + * Description: + * + * Modifies the local PHY Local abilities Advertisement register value + * for the purpose of limiting the media connections to be negotiated + * (/sent) to the link partner. + * + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO + * MediaBits - USHORT + * + * Output parameters: + * + * None. + * + * +-*/ +extern +void +MiiPhyNwaySetLocalAbility( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr, + USHORT MediaBits + ) +{ + +#if MII_DBG + DbgPrint("MiiPhyNwaySetLocalAbility\n"); +#endif + + if (PhyInfoPtr->PhyId != BCM5000_0){ + PhyInfoPtr->PhyRegs[PhyNwayAdvertisement] = + (PhyInfoPtr->PhyMediaAdvertisement & MediaBits) | + NWAY_802_3_Selector; + +#if MII_DBG + DbgPrint("PhyInfoPtr->PhyRegs[PhyNwayAdvertisement] = %04x\n", PhyInfoPtr->PhyRegs[PhyNwayAdvertisement]); + DbgPrint("SROM Advertisement = %04x\n", MediaBits); +#endif + PhyInfoPtr->PhyIntRoutines.PhyWriteRegister( + Adapter, + PhyInfoPtr, + PhyNwayAdvertisement, + PhyInfoPtr->PhyRegs[PhyNwayAdvertisement] + ); + } + return; +} + + + + + + +/*+ + * + * MiiPhyNwayGetPartnerAbility + * + * Description: + * + * Returns link partner abilities as written in the link partner + * abilities register (which reflects link partner's Advertisement + * register). + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * + * Output parameters: + * + * *Ability - NWayAbility pointer to partner abilities + * + * + * A value of 0 will be returned If link partner is not Nway capable or + * does not support any known medium. + * +-*/ +extern +void +MiiPhyNwayGetPartnerAbility( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr, + PCAPABILITY Ability + ) +{ + +#if MII_DBG + DbgPrint("MiiPhyNwayGetPartnerAbility\n"); +#endif + if (PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + PhyNwayLinkPartnerAbility, + &(PhyInfoPtr->PhyRegs[PhyNwayLinkPartnerAbility]) + ) + ) { + + PhyInfoPtr->PhyRegs[PhyNwayLinkPartnerAbility] &= MiiPhyNwayCapabilitiesMask; + *Ability = PhyInfoPtr->PhyRegs[PhyNwayLinkPartnerAbility]; + } + else { + *Ability = 0; + } + return; + +} + + + +/*+ + * + * FindMiiPhyDevice + * + * Description: + * + * Receives MII PHY address and checks if a PHY exists there. + * PhyInfotPtr->PhyAddress holds the PHY address + * + * Input parameter: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * + * Return value: + * + * FALSE - if no such PHY is found + * TRUE - otherwise + * + *****************************************************************************/ +extern +BOOLEAN +FindMiiPhyDevice( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr + ) +{ + USHORT RegOffset; + USHORT RegData; + +#if MII_DBG + DbgPrint("FindMiiPhyDevice\n"); +#endif + + // Read PHY's Registers + + //The first two registers are mandatory + for (RegOffset=0; RegOffset<=PhyStatusReg; RegOffset++) { + if(PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + RegOffset, + &RegData + ) ){ + PhyInfoPtr->PhyRegs[RegOffset] = RegData; + } + else { + return FALSE; + } + } + + // Read the Phy's Id Registers + for (; RegOffset<=PhyId_2; RegOffset++) { + if(PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + RegOffset, + &RegData + ) ){ + PhyInfoPtr->PhyRegs[RegOffset] = RegData; + } + else { + break; + } + } + if (RegOffset > PhyId_2) { + PhyInfoPtr->PhyId = + (PhyInfoPtr->PhyRegs[PhyId_1] <<16) | PhyInfoPtr->PhyRegs[PhyId_2]; + } + + + //Read the remaining registers + for (RegOffset=PhyNwayAdvertisement; RegOffset<MAX_PHY_REGS; RegOffset++) { + if(PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + RegOffset, + &RegData + ) ){ + PhyInfoPtr->PhyRegs[RegOffset] = RegData; + } + else { + break; + } + } + + //Check if the required number of registers have been read + //successfully + + switch (PhyInfoPtr->PhyId) { + + case BCM5000_0 : + case DP83840_0 : + + if (RegOffset < MAX_PHY_REGS) { + return FALSE; + } + break; + + default: + + if ( ( (PhyInfoPtr->PhyRegs[PhyStatusReg] | MiiPhyNwayCapable) + && (RegOffset <= PhyNwayLinkPartnerAbility) + ) + || ( (PhyInfoPtr->PhyRegs[PhyNwayAdvertisement] | MiiPhyNwayNextPageAble) + && (RegOffset <= PhyNwayExpansion ) + ) + ){ + return FALSE; + } + break; + } + +#if MII_DBG + DbgPrint("Device PhyId= %08x\n", PhyInfoPtr->PhyId); + DbgPrint("PhyStatusReg= %04x\n", PhyInfoPtr->PhyRegs[PhyStatusReg]); +#endif + + //return FALSE if the Status Register is all 0's + //otherwise return TRUE; + + return (PhyInfoPtr->PhyRegs[PhyStatusReg] !=0); + +} + + +/*+ + * + * WriteMii + * + * Description: + * + * Writes the data size bits from the MiiData to the Mii control lines. + * + * Input parameters + * MiiData - The data to be written + * DataSize - The number of bits to write + * + * Output parameters + * None. + * + * Return Value + * TRUE if success, FALSE if hardware failure encountered. + * +-*/ +extern +void +WriteMii( + PDC21X4_ADAPTER Adapter, + ULONG MiiData, + int DataSize + ) +{ + + INT i; + ULONG Dbit; + +#if _DBG + DbgPrint("WriteMii\n"); + DbgPrint("PHY: Data to write = %08x\n", MiiData); +#endif + + // Write the data to the PHY + + for (i = DataSize; i> 0; i--) { + + Dbit = ((MiiData >> (31-MII_MDO_BIT_POSITION)) & MII_MDO_MASK); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + MII_WRITE | Dbit + ); + + DELAY(MII_DELAY); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + MII_WRITE | MII_CLK | Dbit + ); + + DELAY(MII_DELAY); + + MiiData = MiiData << 1; + } + + +} + + + + +/*+************************************************************************** + * + * MiiOutThreeState + * + * Description: + * + * Puts the MDIO port in threestate for the turn around bits + * in MII read and at end of MII management sequence. + * + * Parameters + * None. + * +-*/ +extern +void +MiiOutThreeState( + PDC21X4_ADAPTER Adapter + ) +{ + +#if _DBG + DbgPrint("MiiOutThreeState\n"); +#endif + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + MII_WRITE_TS + ); + DELAY(MII_DELAY); + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + (MII_WRITE_TS | MII_CLK) + ); + DELAY(MII_DELAY); + + return; +} + +/*+ + * + * InitPhyInfoEntries + * + * Description: + * + * Initializes the MII PHY struct by directing pointers of struct + * routines to routines addresses. + * (these addresses cannot be resolved at compile time). + * + * Parameter: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * + * +-*/ +extern +void +InitPhyInfoEntries( + PMII_PHY_INFO PhyInfoPtr + ) +{ + NDIS_STATUS NdisStatus; + +#if MII_DBG + DbgPrint("InitPhyInfoEntries\n"); +#endif + + PhyInfoPtr->PhyExtRoutines.PhyInit = (void *)MiiPhyInit; + PhyInfoPtr->PhyExtRoutines.PhyGetCapabilities = (void *)MiiPhyGetCapabilities; + PhyInfoPtr->PhyExtRoutines.PhySetConnectionType = (void *)MiiPhySetConnectionType; + PhyInfoPtr->PhyExtRoutines.PhyGetConnectionType = (void *)MiiPhyGetConnectionType; + PhyInfoPtr->PhyExtRoutines.PhyGetConnectionStatus = (void *)MiiPhyGetConnectionStatus; + PhyInfoPtr->PhyExtRoutines.PhyAdminControl = (void *)MiiPhyAdminControl; + PhyInfoPtr->PhyExtRoutines.PhyAdminStatus = (void *)MiiPhyAdminStatus; + + PhyInfoPtr->PhyIntRoutines.PhyReadRegister = (void *)MiiPhyReadRegister; + PhyInfoPtr->PhyIntRoutines.PhyWriteRegister = (void *)MiiPhyWriteRegister; + PhyInfoPtr->PhyIntRoutines.PhyNwayGetLocalAbility = (void *)MiiPhyNwayGetLocalAbility; + PhyInfoPtr->PhyIntRoutines.PhyNwaySetLocalAbility = (void *)MiiPhyNwaySetLocalAbility; + PhyInfoPtr->PhyIntRoutines.PhyNwayGetPartnerAbility = (void *)MiiPhyNwayGetPartnerAbility; + + return; +} + +/*+ + * + * ConvertConnectionToControl + * + * Input parameters + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * Connection - ConnectionType + * + * Output parameters + * Converted Connection - ConnectionType + * + * Note: Interrupts are disabled. + * +-*/ +extern +void +ConvertConnectionToControl( + PMII_PHY_INFO PhyInfotPtr, + PUSHORT Connection + ) +{ + + USHORT OM_bits = ((*Connection) & CONTROL_MASK); + +#if MII_DBG + DbgPrint("ConvertConnectionToControl\n"); + DbgPrint("Before Conversion: Connection = %04x\n", *Connection); +#endif + // Convert Media Type to control bits + + *Connection = MediaToCommandConversionTable[*Connection & MEDIA_MASK]; + + // Check if Nway bits are also needed + + if (( OM_bits & (MEDIA_NWAY | MEDIA_AUTOSENSE))) { + + // Autosense or Nway are required: + + switch (PhyInfotPtr->PhyId) { + + default: + + *Connection |= MiiPhyCtrlRestartNway; + + case BCM5000_0: + + *Connection |= MiiPhyCtrlEnableNway; + } + + } + +#if MII_DBG + DbgPrint("After Conversion: Connection = %04x\n", *Connection); +#endif + + return; + +} + + +/*+ + * + * ConvertMediaTypeToNwayLocalAbility + * + * Input parameters + * MediaType - USHORT (in SROM format) + * + * Output parameters + * NwayLocalAbility - CAPABILITY + * +-*/ +extern +void +ConvertMediaTypeToNwayLocalAbility( + USHORT MediaType, + PCAPABILITY NwayLocalAbility + ) +{ + +#if MII_DBG + DbgPrint("ConvertMediaTypeToNwayLocalAbility\n"); + DbgPrint("MediaType = %04x\n", MediaType); +#endif + + // Convert MediaType to Nway Advertisement bits + + *NwayLocalAbility = MediaToNwayConversionTable[(MediaType & MEDIA_MASK)]; +#if MII_DBG + DbgPrint("NwayLocalAbility = %04x\n", *NwayLocalAbility); +#endif + return; + +} + +/*+ + * + * ConvertNwayToConnectionType + * + * Description: + * + * Returns highest precedence media type whose bit is set in Nway + * word, according to the following table: + * +----+---------------------------+--------+ + * |Bit | Technology |Priority| + * +----+---------------------------+--------+ + * | A0 | 10Base-T (Half-Duplex) | 5(LSP) | + * +----+---------------------------+--------+ + * | A1 | 10Base-T Full-Duplex | 4 | + * +----+---------------------------+--------+ + * | A2 | 100Base-TX (Half-Duplex) | 3 | + * +----+---------------------------+--------+ + * | A3 | 100Base-TX Full-Duplex | 1(MSP) | + * +----+---------------------------+--------+ + * | A4 | 100Base-T4 | 2 | + * +----+---------------------------+--------+ + * + *On Entry: + * NwayReg - Nway register bits (in Advertisement format). + *On Return: + * NwayReg - The converted ConnectionType + * + *Return Value + * FALSE - No Media Found + * TRUE - Media found and returned in NwayReg + * +-*/ +extern +BOOLEAN +ConvertNwayToConnectionType( + CAPABILITY NwayReg, + PUSHORT Connection + ) +{ + +#if MII_DBG + DbgPrint("ConvertNwayToConnectionType\n"); +#endif + if (NwayReg & MiiPhyNway100BaseTxFD) { + // 100BaseTx FD + *Connection = (MediumMii100BaseTxFullDuplex | MediaAutoSense); + } + else if (NwayReg & MiiPhyNway100BaseT4) { + // 100BaseT4 + *Connection = (MediumMii100BaseT4 | MediaAutoSense); + } + else if (NwayReg & MiiPhyNway100BaseTx) { + // 100BaseTx + *Connection = (MediumMii100BaseTx | MediaAutoSense); + } + else if (NwayReg & MiiPhyNway10BaseTFD) { + // 10BaseT FD + *Connection = (MediumMii10BaseTFullDuplex | MediaAutoSense); + } + else if (NwayReg & MiiPhyNway10BaseT) { + // 10BaseT + *Connection = (MediumMii10BaseT | MediaAutoSense); + } + else { + // No media found + return FALSE; + } + return TRUE; +} + + +/*+ + * + * CheckConnectionSupport + * + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * MiiMediaCapable - Mii Media capability mask from the SROM + * ConCommand - Connection command bits (in SROM format) + * + * Return value: + * + * FALSE - Connection NOT supported + * TRUE - Connection supported + * +-*/ +extern +BOOLEAN +CheckConnectionSupport( + PMII_PHY_INFO PhyInfoPtr, + USHORT ConCommand + ) +{ + USHORT StatusBits; + +#if MII_DBG + DbgPrint("CheckConnectionSupport\n"); +#endif + + if ((ConCommand & (MEDIA_NWAY | MEDIA_AUTOSENSE))){ + //NWAY or AutoSense are required +#if MII_DBG + DbgPrint("NWAY or AutoSensing\n"); +#endif + return ((PhyInfoPtr->PhyCapabilities & MiiPhyNwayCapable) != 0); + } + + //Convert media to status bits + + StatusBits = MediaToStatusConversionTable[(ConCommand & MEDIA_MASK)]; +#if MII_DBG + DbgPrint("Before Conversion: ConCommand = %04x\n", ConCommand); + DbgPrint("After Conversion: StatusBits = %04x\n", StatusBits); +#endif + + //Return TRUE if the requested medium is supported by the PHY + + return ((StatusBits & PhyInfoPtr->PhyCapabilities) != 0); + +} + + + + + + + + + + +//**************************************************************************** +//* Broadcom support routines * +//**************************************************************************** + +/*+ + *Broadcom extended register (address 16) + *--------------------------------------- + * + * +-----+----------------+---------------------------+-----------------------------+ + * | Bit | Name | Description | Comments | + * +-----+----------------+---------------------------+-----------------------------+ + * | 15 | JABDIS |1=Jubber Disabled | Default 0 (R/W) | + * | | |1=Jubber Enabled | | + * +-----+----------------+---------------------------+-----------------------------+ + * | 14 | LINKDIS |1=Link test Disabled | Default 0 (R/W) | + * | | |0=Link test Enabled | | + * +-----+----------------+---------------------------+-----------------------------+ + * |13-9 | reserved | |Write as 0, Ignore on read | + * +-----+----------------+---------------------------+-----------------------------+ + * | 8 |FORCEFAIL_EN |1=Force fail enabled | Default 1 (R/W) | + * | | |0=Force fail disabled | | + * +-----+----------------+---------------------------+-----------------------------+ + * | 7-5 |RV_CNTR |Revision control indicator | Value is 000 (RO) | + * +-----+----------------+---------------------------+-----------------------------+ + * | 4-3 |HSQ:LSQ |Defines the squelch mode of|10=High squelch, 00=Normal | + * | | |the carrier sense mechanism|01=Low Squelch,11=Not allowed| + * | | | |Default 00 (R/W) | + * +-----+----------------+---------------------------+-----------------------------+ + * | 2 |TXDAC power mode| |Default 0 (R/W) | + * +-----+----------------+---------------------------+-----------------------------+ + * | 1 |Speed Indication|1 = 100Mbps mode |Default 0 RO | + * | | |0 = 10Mbps mode | | + * +-----+----------------+---------------------------+-----------------------------+ + * | 0 |reserved | | | + * +-----+----------------+---------------------------+-----------------------------+ +-*/ + + + + + +/*+ + * + * HandleBroadcomMediaChangeFrom10To100 + * + * Description: + * + * Handle Broadcom special requirements for speed change from 10 to 100 Mbps + * + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * + * Output parameters: + * + * None. + * + * +-*/ +extern +void +HandleBroadcomMediaChangeFrom10To100( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr + ) +{ + + USHORT Register; + +#if MII_DBG + DbgPrint("HandleBroadcomMediaChangeFrom10To100\n"); +#endif + PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + MII_BROADCOM_EXTENDED_REG_ADDRESS, + &Register + ); + + if ( (Register != PhyInfoPtr->PhyRegs[MII_BROADCOM_EXTENDED_REG_ADDRESS]) + && (Register & BROADCOM_EXT_REG_FORCE_FAIL_EN_MASK) + && (Register & BROADCOM_EXT_REG_SPEED_MASK) + && !( PhyInfoPtr->PhyRegs[MII_BROADCOM_EXTENDED_REG_ADDRESS] + & BROADCOM_EXT_REG_SPEED_MASK + ) + ) { + // Speed has changed : + // reset the PHY and restore the old control value +#if MII_DBG + DbgPrint("Speed has changed; reset PHY and restore old ctrl value\n"); +#endif + PhyInfoPtr->PhyExtRoutines.PhyAdminControl( + Adapter, + PhyInfoPtr, + MiiGenAdminReset + ); + PhyInfoPtr->PhyIntRoutines.PhyWriteRegister( + Adapter, + PhyInfoPtr, + PhyControlReg, + PhyInfoPtr->PhyRegs[PhyControlReg] + ); + } + PhyInfoPtr->PhyRegs[MII_BROADCOM_EXTENDED_REG_ADDRESS] = Register; + + return; +} + + + + + + +/*+ + * + * GetBroadcomPhyConnectionType + * + * Description: + * + * Returns connection type, which may be one of the following: + * T4 + * Tp + * TpFD + * + * Input parameters: + * + * PhyInfoPtr - PMII_PHY_INFO pointer to struct with PHY info + * + * Output parameters: + * + * Connection - ConnectionType + * + * On return + * Returns TRUE if + * +-*/ +extern +BOOLEAN +GetBroadcomPhyConnectionType( + PDC21X4_ADAPTER Adapter, + PMII_PHY_INFO PhyInfoPtr, + PUSHORT Connection + ) +{ + + USHORT Register; + +#if MII_DBG + DbgPrint("GetBroadcomPhyConnectionType\n"); +#endif + if (!PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + MII_BROADCOM_EXTENDED_REG_ADDRESS, + &Register + )) { + return FALSE; + } + + if ((Register & BROADCOM_EXT_REG_FORCE_FAIL_EN_MASK) == 0){ + return FALSE; + } + + if (!PhyInfoPtr->PhyIntRoutines.PhyReadRegister( + Adapter, + PhyInfoPtr, + PhyControlReg, + &(PhyInfoPtr->PhyRegs[PhyControlReg]) + )) { + return FALSE; + } + + if (Register & BROADCOM_EXT_REG_SPEED_MASK){ + // Speed is 100Mbps + *Connection = MediumMii100BaseT4; + } + else { + // Speed is 10Mbps + *Connection = + (PhyInfoPtr->PhyRegs[PhyControlReg] & MiiPhyCtrlDuplexMode) ? + MediumMii10BaseTFullDuplex : MediumMii10BaseT; + } + + if (PhyInfoPtr->PhyRegs[PhyControlReg] & MiiPhyCtrlEnableNway) { + *Connection |= (MEDIA_AUTOSENSE | MEDIA_NWAY); + } +#if MII_DBG + DbgPrint("ConnectionType= %04x\n", *Connection); +#endif + + return TRUE; +} + |