summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/dc21x4/miiphy.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/dc21x4/miiphy.c')
-rw-r--r--private/ntos/ndis/dc21x4/miiphy.c1913
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;
+}
+