📄 1
字号:
bits[clk_idx++] = MII_MDOE;
/* Shift to next lowest bit */
mask >>= 1;
}
/* Output the phy register number, msb first */
mask = (BYTE) 0x10;
for (i = 0; i < 5; ++i) {
if (phyreg & mask)
bits[clk_idx++] = MII_MDOE | MII_MDO;
else
bits[clk_idx++] = MII_MDOE;
/* Shift to next lowest bit */
mask >>= 1;
}
/* Tristate and turnaround (2 bit times) */
bits[clk_idx++] = 0;
bits[clk_idx++] = 0;
/* Write out 16 bits of data, msb first */
mask = 0x8000;
for (i = 0; i < 16; ++i) {
if (phydata & mask)
bits[clk_idx++] = MII_MDOE | MII_MDO;
else
bits[clk_idx++] = MII_MDOE;
/* Shift to next lowest bit */
mask >>= 1;
}
/* Final clock bit (tristate) */
bits[clk_idx++] = 0;
/* Save the current bank */
oldBank = ReadWord(BANKSEL_REG);
/* Select bank 3 */
WriteWord( BANKSEL_REG, BANK3 );
/* Get the current MII register value */
mii_reg = ReadWord (MII_REG);
/* Turn off all MII Interface bits */
mii_reg &= ~(MII_MDOE | MII_MCLK | MII_MDI | MII_MDO);
/* Clock all cycles */
for (i = 0; i < sizeof bits; ++i) {
/* Clock Low - output data */
WriteWord ( MII_REG, mii_reg | bits[i]);
smc_udelay (SMC_PHY_CLOCK_DELAY);
/* Clock Hi - input data */
WriteWord ( MII_REG, mii_reg | bits[i] | MII_MCLK);
smc_udelay (SMC_PHY_CLOCK_DELAY);
bits[i] |= ReadWord (MII_REG) & MII_MDI;
}
/* Return to idle state */
/* Set clock to low, data to low, and output tristated */
WriteWord ( MII_REG, mii_reg);
smc_udelay (SMC_PHY_CLOCK_DELAY);
/* Restore original bank select */
WriteWord( BANKSEL_REG, oldBank );
}
#if 1
#if 1
static void smc_wait_ms(unsigned int ms)
{
volatile int i;
unsigned int i2;
for(i2=0 ; i2 < ms ; i2++)
{
for(i=0 ; i < 1000 ; i++)
{
}
}
}
#endif
#if 1
#define RPC_REG 0x000A
#define RPC_SPEED 0x2000 /* When 1 PHY is in 100Mbps mode. */
#define RPC_DPLX 0x1000 /* When 1 PHY is in Full-Duplex Mode */
#define RPC_ANEG 0x0800 /* When 1 PHY is in Auto-Negotiate Mode */
#define RPC_LSXA_SHFT 5 /* Bits to shift LS2A,LS1A,LS0A to lsb */
#define RPC_LSXB_SHFT 2 /* Bits to get LS2B,LS1B,LS0B to lsb */
#define RPC_LED_100_10 (0x00) /* LED = 100Mbps OR's with 10Mbps link detect */
#define RPC_LED_RES (0x01) /* LED = Reserved */
#define RPC_LED_10 (0x02) /* LED = 10Mbps link detect */
#define RPC_LED_FD (0x03) /* LED = Full Duplex Mode */
#define RPC_LED_TX_RX (0x04) /* LED = TX or RX packet occurred */
#define RPC_LED_100 (0x05) /* LED = 100Mbps link dectect */
#define RPC_LED_TX (0x06) /* LED = TX packet occurred */
#define RPC_LED_RX (0x07) /* LED = RX packet occurred */
#define RPC_DEFAULT ( RPC_SPEED | RPC_DPLX | RPC_ANEG \
| (RPC_LED_100_10 << RPC_LSXA_SHFT) \
| (RPC_LED_TX_RX << RPC_LSXB_SHFT) )
#endif
static void smc_phy_configure ()
{
#if 1
int timeout;
BYTE phyaddr;
WORD my_phy_caps; /* My PHY capabilities */
WORD my_ad_caps; /* My Advertised capabilities */
WORD status = 0; /*;my status = 0 */
int failed = 0;
EdbgOutputDebugString("smc_phy_configure()\r\n");
EdbgOutputDebugString("phy cfg reg1: 0x%x\n", smc_read_phy_register(PHY_CFG1_REG) );
/* Get the detected phy address */
phyaddr = SMC_PHY_ADDR;
/* Reset the PHY, setting all other bits to zero */
smc_write_phy_register (PHY_CNTL_REG, PHY_CNTL_RST);
timeout = 6; /* Wait up to 3 seconds */
while (timeout--) {
if (!(smc_read_phy_register (PHY_CNTL_REG) & PHY_CNTL_RST)) {
/* reset complete */
break;
}
smc_wait_ms (500); /* wait 500 millisecs */
}
if (timeout < 1) {
EdbgOutputDebugString ("%s:PHY reset timed out\n", SMC_DEV_NAME);
goto smc_phy_configure_exit;
}
/* Read PHY Register 18, Status Output */
/* lp->lastPhy18 = smc_read_phy_register(PHY_INT_REG); */
/* Enable PHY Interrupts (for register 18) */
/* Interrupts listed here are disabled */
smc_write_phy_register (PHY_MASK_REG, 0x0000);
smc_wait_ms (500); /* wait 500 millisecs */
/* Configure the Receive/Phy Control register */
WriteWord( BANKSEL_REG, BANK0 );
WriteWord ( RPC_REG ,RPC_DEFAULT);
/* Copy our capabilities from PHY_STAT_REG to PHY_AD_REG */
my_phy_caps = smc_read_phy_register (PHY_STAT_REG);
my_ad_caps = PHY_AD_CSMA; /* I am CSMA capable */
if (my_phy_caps & PHY_STAT_CAP_T4) {
my_ad_caps |= PHY_AD_T4;
}
if (my_phy_caps & PHY_STAT_CAP_TXF) {
my_ad_caps |= PHY_AD_TX_FDX;
}
if (my_phy_caps & PHY_STAT_CAP_TXH) {
my_ad_caps |= PHY_AD_TX_HDX;
}
if (my_phy_caps & PHY_STAT_CAP_TF) {
my_ad_caps |= PHY_AD_10_FDX;
}
if (my_phy_caps & PHY_STAT_CAP_TH) {
my_ad_caps |= PHY_AD_10_HDX;
}
/* Update our Auto-Neg Advertisement Register */
smc_write_phy_register (PHY_AD_REG, my_ad_caps);
/* Read the register back. Without this, it appears that when */
/* auto-negotiation is restarted, sometimes it isn't ready and */
/* the link does not come up. */
smc_read_phy_register(PHY_AD_REG);
EdbgOutputDebugString ("%s:phy caps=0x%x\n", SMC_DEV_NAME, my_phy_caps); /*0x7809*/
EdbgOutputDebugString ("%s:phy advertised caps=0x%x\n", SMC_DEV_NAME, my_ad_caps); /*0x01e1*/
/* Restart auto-negotiation process in order to advertise my caps */
smc_write_phy_register (PHY_CNTL_REG, PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST);
/* Wait for the auto-negotiation to complete. This may take from */
/* 2 to 3 seconds. */
/* Wait for the reset to complete, or time out */
timeout = 20; /* Wait up to 10 seconds */
while (timeout--) {
status = smc_read_phy_register (PHY_STAT_REG);
if (status & PHY_STAT_ANEG_ACK) {
EdbgOutputDebugString ("%s:PHY auto-negotiate complete\n", SMC_DEV_NAME);
/* auto-negotiate complete */
break;
}
smc_wait_ms (500); /* wait 500 millisecs */
/* Restart auto-negotiation if remote fault */
if (status & PHY_STAT_REM_FLT) {
EdbgOutputDebugString ("%s:PHY remote fault detected\n", SMC_DEV_NAME);
/* Restart auto-negotiation */
EdbgOutputDebugString("%s:PHY restarting auto-negotiation\n",SMC_DEV_NAME);
smc_write_phy_register (PHY_CNTL_REG,
PHY_CNTL_ANEG_EN |
PHY_CNTL_ANEG_RST |
PHY_CNTL_SPEED |
PHY_CNTL_DPLX);
}
}
EdbgOutputDebugString ("%s:PHY_STAT_REG : 0x%x\n", SMC_DEV_NAME, status);
if (timeout < 1) {
EdbgOutputDebugString("%s:PHY auto-negotiate timed out\n", SMC_DEV_NAME);
EdbgOutputDebugString("%s:PHY auto-negotiate timed out\n", SMC_DEV_NAME);
failed = 1;
}
/* Fail if we detected an auto-negotiate remote fault */
if (status & PHY_STAT_REM_FLT)
{
EdbgOutputDebugString("PHY remote fault detected\n");
failed = 1;
}
/* Re-Configure the Receive/Phy Control register */
WriteWord( RPC_REG,RPC_DEFAULT);
EdbgOutputDebugString("%s:RPC_DEFAULT : 0x%x\n", SMC_DEV_NAME, RPC_DEFAULT);
#endif
smc_phy_configure_exit:
return;
}
#endif
BOOL
SMCInit( BYTE *pbBaseAddress, DWORD dwMultiplier, USHORT MacAddr[3]) {
DWORD dwStartTime;
USHORT wBSR, wConfig;
EdbgOutputDebugString ( "\r\n test1 \r\n");
if (! pbBaseAddress)
return FALSE;
pbEthernetBase = pbBaseAddress;
dwRegisterMultiplier = dwMultiplier;
// DANGER - May have to wait 750 usec after reset while EEPROM info loads (Pg 50 of the SMC91C94 spec).
// until this occurs, SMC registers are inaccessible.
EdbgOutputDebugString("+SMCInit\r\n");
WriteWord( BANKSEL_REG, BANK1 );
dwStartTime = OEMEthGetSecs();
while( ReadWord( CONTROL_REG ) & 0x0003 && OEMEthGetSecs() - dwStartTime < 2);
// Verify the I/O base. The upper byte of the BSR always reads 0x33, use this.
// For Odo, the bus cycles will time out and garbage values will be returned.
wBSR = ReadWord(BANKSEL_REG);
EdbgOutputDebugString ("==%x\n",*(volatile UINT16 *)0xA700030e);
if ((wBSR & 0xFF00) != 0x3300) {
EdbgOutputDebugString("SMC card not detected, I/O base 0x%X, BSR: 0x%X\n",pbEthernetBase,wBSR);
return FALSE;
}
EdbgOutputDebugString( "SMC Ethernet card detected at I/O base 0x%X\r\n",pbEthernetBase);
// Read the MAC address from the 91C94. This should have been read in from the EEPROM during reset
#if 0
if( NULL != MacAddr ) {
WriteWord( BANKSEL_REG, BANK1 );
MacAddr[0] = ReadWord( MACADDR_REG0 );
MacAddr[1] = ReadWord( MACADDR_REG1 );
MacAddr[2] = ReadWord( MACADDR_REG2 );
EdbgOutputDebugString("SMC Ethernet Address: %B:%B:%B:%B:%B:%B\r\n",
MacAddr[0] & 0x00FF, MacAddr[0] >> 8,
MacAddr[1] & 0x00FF, MacAddr[1] >> 8,
MacAddr[2] & 0x00FF, MacAddr[2] >> 8);
}
#endif
// Set SQUELCH bit - this changes the threshold for a valid signal from 300mV to 180mV.
// This is to attempt to fix problems we have seen with some (usually 8 port) hubs.
wConfig = ReadWord(CONFIG_REG);
wConfig |= CFG_SETSQLCH|CFG_NO_WAIT;
//khryu---------------------------------------------------------------------------------
#define CONFIG_EPH_POWER_EN 0x8000
wConfig = CONFIG_EPH_POWER_EN;
//khryu
WriteWord(CONFIG_REG, wConfig);
EdbgOutputDebugString("SMC config reg val: %X\n",wConfig);
// Initialize the control register
WriteWord( BANKSEL_REG, BANK1 );
WriteWord( CONTROL_REG, CONTROL_REG_INIT );
// Initialize memory configuration register
WriteWord( BANKSEL_REG, BANK0 );
WriteWord( MCR_REG, MCR_REG_INIT );
// Initialize transmit control register
WriteWord( BANKSEL_REG, BANK0 );
WriteWord( TCR_REG, TCR_REG_INIT );
// Initialize interrupt mask register (all ints disabled to start)
WriteWord( BANKSEL_REG, BANK2 );
WriteWord( INTERRUPT_REG, 0);
// The receive register should be the last thing initialzed so that we don't start
// getting Frames before we're ready for them.
// Initialize the Receive Control Register (Pg 39 of the SMC91C94 spec):
WriteWord( BANKSEL_REG, BANK0 );
WriteWord( RCR_REG, RCR_REG_INIT );
#define RCR_RXEN 0x0100 /* IFF this is set, we can receive packets */
#define RCR_STRIP_CRC 0x0200 /* When set strips CRC from rx packets */
WriteWord( RCR_REG, (RCR_RXEN|RCR_STRIP_CRC) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -