mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1913 lines
46 KiB
1913 lines
46 KiB
/*+
|
|
* 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;
|
|
}
|
|
|