|
|
|
@ -295,23 +295,23 @@ static void smc_write_phy_register(byte phyreg, word phydata); |
|
|
|
|
#endif /* !CONFIG_SMC91111_EXT_PHY */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int poll4int( byte mask, int timeout ) { |
|
|
|
|
int tmo = get_timer(0) + timeout * CFG_HZ; |
|
|
|
|
static int poll4int (byte mask, int timeout) |
|
|
|
|
{ |
|
|
|
|
int tmo = get_timer (0) + timeout * CFG_HZ; |
|
|
|
|
int is_timeout = 0; |
|
|
|
|
word old_bank = SMC_inw(BSR_REG); |
|
|
|
|
word old_bank = SMC_inw (BSR_REG); |
|
|
|
|
|
|
|
|
|
PRINTK2("Polling...\n"); |
|
|
|
|
SMC_SELECT_BANK(2); |
|
|
|
|
while((SMC_inw(SMC91111_INT_REG) & mask) == 0) |
|
|
|
|
{ |
|
|
|
|
if (get_timer(0) >= tmo) { |
|
|
|
|
PRINTK2 ("Polling...\n"); |
|
|
|
|
SMC_SELECT_BANK (2); |
|
|
|
|
while ((SMC_inw (SMC91111_INT_REG) & mask) == 0) { |
|
|
|
|
if (get_timer (0) >= tmo) { |
|
|
|
|
is_timeout = 1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* restore old bank selection */ |
|
|
|
|
SMC_SELECT_BANK(old_bank); |
|
|
|
|
SMC_SELECT_BANK (old_bank); |
|
|
|
|
|
|
|
|
|
if (is_timeout) |
|
|
|
|
return 1; |
|
|
|
@ -320,13 +320,15 @@ static int poll4int( byte mask, int timeout ) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Only one release command at a time, please */ |
|
|
|
|
static inline void smc_wait_mmu_release_complete(void) |
|
|
|
|
static inline void smc_wait_mmu_release_complete (void) |
|
|
|
|
{ |
|
|
|
|
int count = 0; |
|
|
|
|
|
|
|
|
|
/* assume bank 2 selected */ |
|
|
|
|
while ( SMC_inw(MMU_CMD_REG) & MC_BUSY ) { |
|
|
|
|
udelay(1); /* Wait until not busy */ |
|
|
|
|
if( ++count > 200) break; |
|
|
|
|
while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { |
|
|
|
|
udelay (1); /* Wait until not busy */ |
|
|
|
|
if (++count > 200) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -347,57 +349,57 @@ static inline void smc_wait_mmu_release_complete(void) |
|
|
|
|
. 5. clear all interrupts |
|
|
|
|
. |
|
|
|
|
*/ |
|
|
|
|
static void smc_reset( void ) |
|
|
|
|
static void smc_reset (void) |
|
|
|
|
{ |
|
|
|
|
PRINTK2("%s:smc_reset\n", SMC_DEV_NAME); |
|
|
|
|
PRINTK2 ("%s:smc_reset\n", SMC_DEV_NAME); |
|
|
|
|
|
|
|
|
|
/* This resets the registers mostly to defaults, but doesn't
|
|
|
|
|
affect EEPROM. That seems unnecessary */ |
|
|
|
|
SMC_SELECT_BANK( 0 ); |
|
|
|
|
SMC_outw( RCR_SOFTRST, RCR_REG ); |
|
|
|
|
SMC_SELECT_BANK (0); |
|
|
|
|
SMC_outw (RCR_SOFTRST, RCR_REG); |
|
|
|
|
|
|
|
|
|
/* Setup the Configuration Register */ |
|
|
|
|
/* This is necessary because the CONFIG_REG is not affected */ |
|
|
|
|
/* by a soft reset */ |
|
|
|
|
|
|
|
|
|
SMC_SELECT_BANK( 1 ); |
|
|
|
|
SMC_SELECT_BANK (1); |
|
|
|
|
#if defined(CONFIG_SMC91111_EXT_PHY) |
|
|
|
|
SMC_outw( CONFIG_DEFAULT | CONFIG_EXT_PHY, CONFIG_REG); |
|
|
|
|
SMC_outw (CONFIG_DEFAULT | CONFIG_EXT_PHY, CONFIG_REG); |
|
|
|
|
#else |
|
|
|
|
SMC_outw( CONFIG_DEFAULT, CONFIG_REG); |
|
|
|
|
SMC_outw (CONFIG_DEFAULT, CONFIG_REG); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Release from possible power-down state */ |
|
|
|
|
/* Configuration register is not affected by Soft Reset */ |
|
|
|
|
SMC_outw( SMC_inw( CONFIG_REG ) | CONFIG_EPH_POWER_EN, CONFIG_REG ); |
|
|
|
|
SMC_outw (SMC_inw (CONFIG_REG) | CONFIG_EPH_POWER_EN, CONFIG_REG); |
|
|
|
|
|
|
|
|
|
SMC_SELECT_BANK( 0 ); |
|
|
|
|
SMC_SELECT_BANK (0); |
|
|
|
|
|
|
|
|
|
/* this should pause enough for the chip to be happy */ |
|
|
|
|
udelay(10); |
|
|
|
|
udelay (10); |
|
|
|
|
|
|
|
|
|
/* Disable transmit and receive functionality */ |
|
|
|
|
SMC_outw( RCR_CLEAR, RCR_REG ); |
|
|
|
|
SMC_outw( TCR_CLEAR, TCR_REG ); |
|
|
|
|
SMC_outw (RCR_CLEAR, RCR_REG); |
|
|
|
|
SMC_outw (TCR_CLEAR, TCR_REG); |
|
|
|
|
|
|
|
|
|
/* set the control register */ |
|
|
|
|
SMC_SELECT_BANK( 1 ); |
|
|
|
|
SMC_outw( CTL_DEFAULT, CTL_REG ); |
|
|
|
|
SMC_SELECT_BANK (1); |
|
|
|
|
SMC_outw (CTL_DEFAULT, CTL_REG); |
|
|
|
|
|
|
|
|
|
/* Reset the MMU */ |
|
|
|
|
SMC_SELECT_BANK( 2 ); |
|
|
|
|
smc_wait_mmu_release_complete(); |
|
|
|
|
SMC_outw( MC_RESET, MMU_CMD_REG ); |
|
|
|
|
while ( SMC_inw( MMU_CMD_REG ) & MC_BUSY ) |
|
|
|
|
udelay(1); /* Wait until not busy */ |
|
|
|
|
SMC_SELECT_BANK (2); |
|
|
|
|
smc_wait_mmu_release_complete (); |
|
|
|
|
SMC_outw (MC_RESET, MMU_CMD_REG); |
|
|
|
|
while (SMC_inw (MMU_CMD_REG) & MC_BUSY) |
|
|
|
|
udelay (1); /* Wait until not busy */ |
|
|
|
|
|
|
|
|
|
/* Note: It doesn't seem that waiting for the MMU busy is needed here,
|
|
|
|
|
but this is a place where future chipsets _COULD_ break. Be wary |
|
|
|
|
of issuing another MMU command right after this */ |
|
|
|
|
|
|
|
|
|
/* Disable all interrupts */ |
|
|
|
|
SMC_outb( 0, IM_REG ); |
|
|
|
|
SMC_outb (0, IM_REG); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -467,11 +469,11 @@ static void smc_shutdown() |
|
|
|
|
. Enable the transmit interrupt, so I know if it failed |
|
|
|
|
. Free the kernel data if I actually sent it. |
|
|
|
|
*/ |
|
|
|
|
static int smc_send_packet(volatile void *packet, int packet_length) |
|
|
|
|
static int smc_send_packet (volatile void *packet, int packet_length) |
|
|
|
|
{ |
|
|
|
|
byte packet_no; |
|
|
|
|
unsigned long ioaddr; |
|
|
|
|
byte * buf; |
|
|
|
|
byte *buf; |
|
|
|
|
int length; |
|
|
|
|
int numPages; |
|
|
|
|
int try = 0; |
|
|
|
@ -479,7 +481,7 @@ static int smc_send_packet(volatile void *packet, int packet_length) |
|
|
|
|
byte status; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PRINTK3("%s:smc_hardware_send_packet\n", SMC_DEV_NAME); |
|
|
|
|
PRINTK3 ("%s:smc_hardware_send_packet\n", SMC_DEV_NAME); |
|
|
|
|
|
|
|
|
|
length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN; |
|
|
|
|
|
|
|
|
@ -498,14 +500,14 @@ static int smc_send_packet(volatile void *packet, int packet_length) |
|
|
|
|
numPages = ((length & 0xfffe) + 6); |
|
|
|
|
numPages >>= 8; /* Divide by 256 */ |
|
|
|
|
|
|
|
|
|
if (numPages > 7 ) { |
|
|
|
|
printf("%s: Far too big packet error. \n", SMC_DEV_NAME); |
|
|
|
|
if (numPages > 7) { |
|
|
|
|
printf ("%s: Far too big packet error. \n", SMC_DEV_NAME); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* now, try to allocate the memory */ |
|
|
|
|
SMC_SELECT_BANK( 2 ); |
|
|
|
|
SMC_outw( MC_ALLOC | numPages, MMU_CMD_REG ); |
|
|
|
|
SMC_SELECT_BANK (2); |
|
|
|
|
SMC_outw (MC_ALLOC | numPages, MMU_CMD_REG); |
|
|
|
|
|
|
|
|
|
/* FIXME: the ALLOC_INT bit never gets set *
|
|
|
|
|
* so the following will always give a * |
|
|
|
@ -518,16 +520,16 @@ again: |
|
|
|
|
try++; |
|
|
|
|
time_out = MEMORY_WAIT_TIME; |
|
|
|
|
do { |
|
|
|
|
status = SMC_inb( SMC91111_INT_REG ); |
|
|
|
|
if ( status & IM_ALLOC_INT ) { |
|
|
|
|
status = SMC_inb (SMC91111_INT_REG); |
|
|
|
|
if (status & IM_ALLOC_INT) { |
|
|
|
|
/* acknowledge the interrupt */ |
|
|
|
|
SMC_outb( IM_ALLOC_INT, SMC91111_INT_REG ); |
|
|
|
|
SMC_outb (IM_ALLOC_INT, SMC91111_INT_REG); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} while ( -- time_out ); |
|
|
|
|
} while (--time_out); |
|
|
|
|
|
|
|
|
|
if ( !time_out ) { |
|
|
|
|
PRINTK2("%s: memory allocation, try %d failed ...\n", |
|
|
|
|
if (!time_out) { |
|
|
|
|
PRINTK2 ("%s: memory allocation, try %d failed ...\n", |
|
|
|
|
SMC_DEV_NAME, try); |
|
|
|
|
if (try < SMC_ALLOC_MAX_TRY) |
|
|
|
|
goto again; |
|
|
|
@ -535,47 +537,45 @@ again: |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PRINTK2("%s: memory allocation, try %d succeeded ...\n", |
|
|
|
|
SMC_DEV_NAME, |
|
|
|
|
try); |
|
|
|
|
PRINTK2 ("%s: memory allocation, try %d succeeded ...\n", |
|
|
|
|
SMC_DEV_NAME, try); |
|
|
|
|
|
|
|
|
|
/* I can send the packet now.. */ |
|
|
|
|
|
|
|
|
|
ioaddr = SMC_BASE_ADDRESS; |
|
|
|
|
|
|
|
|
|
buf = (byte *)packet; |
|
|
|
|
buf = (byte *) packet; |
|
|
|
|
|
|
|
|
|
/* If I get here, I _know_ there is a packet slot waiting for me */ |
|
|
|
|
packet_no = SMC_inb( AR_REG ); |
|
|
|
|
if ( packet_no & AR_FAILED ) { |
|
|
|
|
packet_no = SMC_inb (AR_REG); |
|
|
|
|
if (packet_no & AR_FAILED) { |
|
|
|
|
/* or isn't there? BAD CHIP! */ |
|
|
|
|
printf("%s: Memory allocation failed. \n", |
|
|
|
|
SMC_DEV_NAME); |
|
|
|
|
printf ("%s: Memory allocation failed. \n", SMC_DEV_NAME); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* we have a packet address, so tell the card to use it */ |
|
|
|
|
SMC_outb( packet_no, PN_REG ); |
|
|
|
|
SMC_outb (packet_no, PN_REG); |
|
|
|
|
|
|
|
|
|
/* point to the beginning of the packet */ |
|
|
|
|
SMC_outw( PTR_AUTOINC , PTR_REG ); |
|
|
|
|
SMC_outw (PTR_AUTOINC, PTR_REG); |
|
|
|
|
|
|
|
|
|
PRINTK3("%s: Trying to xmit packet of length %x\n", |
|
|
|
|
PRINTK3 ("%s: Trying to xmit packet of length %x\n", |
|
|
|
|
SMC_DEV_NAME, length); |
|
|
|
|
|
|
|
|
|
#if SMC_DEBUG > 2 |
|
|
|
|
printf("Transmitting Packet\n"); |
|
|
|
|
print_packet( buf, length ); |
|
|
|
|
printf ("Transmitting Packet\n"); |
|
|
|
|
print_packet (buf, length); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* send the packet length ( +6 for status, length and ctl byte )
|
|
|
|
|
and the status word ( set to zeros ) */ |
|
|
|
|
#ifdef USE_32_BIT |
|
|
|
|
SMC_outl( (length +6 ) << 16 , SMC91111_DATA_REG ); |
|
|
|
|
SMC_outl ((length + 6) << 16, SMC91111_DATA_REG); |
|
|
|
|
#else |
|
|
|
|
SMC_outw( 0, SMC91111_DATA_REG ); |
|
|
|
|
/* send the packet length ( +6 for status words, length, and ctl*/ |
|
|
|
|
SMC_outw( (length+6), SMC91111_DATA_REG ); |
|
|
|
|
SMC_outw (0, SMC91111_DATA_REG); |
|
|
|
|
/* send the packet length ( +6 for status words, length, and ctl */ |
|
|
|
|
SMC_outw ((length + 6), SMC91111_DATA_REG); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* send the actual data
|
|
|
|
@ -586,57 +586,56 @@ again: |
|
|
|
|
. almost as much time as is saved? |
|
|
|
|
*/ |
|
|
|
|
#ifdef USE_32_BIT |
|
|
|
|
SMC_outsl(SMC91111_DATA_REG, buf, length >> 2 ); |
|
|
|
|
if ( length & 0x2 ) |
|
|
|
|
SMC_outw(*((word *)(buf + (length & 0xFFFFFFFC))), SMC91111_DATA_REG); |
|
|
|
|
SMC_outsl (SMC91111_DATA_REG, buf, length >> 2); |
|
|
|
|
if (length & 0x2) |
|
|
|
|
SMC_outw (*((word *) (buf + (length & 0xFFFFFFFC))), |
|
|
|
|
SMC91111_DATA_REG); |
|
|
|
|
#else |
|
|
|
|
SMC_outsw(SMC91111_DATA_REG , buf, (length ) >> 1); |
|
|
|
|
SMC_outsw (SMC91111_DATA_REG, buf, (length) >> 1); |
|
|
|
|
#endif /* USE_32_BIT */ |
|
|
|
|
|
|
|
|
|
/* Send the last byte, if there is one. */ |
|
|
|
|
if ( (length & 1) == 0 ) { |
|
|
|
|
SMC_outw( 0, SMC91111_DATA_REG ); |
|
|
|
|
if ((length & 1) == 0) { |
|
|
|
|
SMC_outw (0, SMC91111_DATA_REG); |
|
|
|
|
} else { |
|
|
|
|
SMC_outw( buf[length -1 ] | 0x2000, SMC91111_DATA_REG ); |
|
|
|
|
SMC_outw (buf[length - 1] | 0x2000, SMC91111_DATA_REG); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* and let the chipset deal with it */ |
|
|
|
|
SMC_outw( MC_ENQUEUE , MMU_CMD_REG ); |
|
|
|
|
SMC_outw (MC_ENQUEUE, MMU_CMD_REG); |
|
|
|
|
|
|
|
|
|
/* poll for TX INT */ |
|
|
|
|
if (poll4int(IM_TX_INT, SMC_TX_TIMEOUT)) { |
|
|
|
|
if (poll4int (IM_TX_INT, SMC_TX_TIMEOUT)) { |
|
|
|
|
/* sending failed */ |
|
|
|
|
PRINTK2("%s: TX timeout, sending failed...\n", |
|
|
|
|
SMC_DEV_NAME); |
|
|
|
|
PRINTK2 ("%s: TX timeout, sending failed...\n", SMC_DEV_NAME); |
|
|
|
|
|
|
|
|
|
/* release packet */ |
|
|
|
|
SMC_outw(MC_FREEPKT, MMU_CMD_REG); |
|
|
|
|
SMC_outw (MC_FREEPKT, MMU_CMD_REG); |
|
|
|
|
|
|
|
|
|
/* wait for MMU getting ready (low) */ |
|
|
|
|
while (SMC_inw(MMU_CMD_REG) & MC_BUSY) |
|
|
|
|
{ |
|
|
|
|
udelay(10); |
|
|
|
|
while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { |
|
|
|
|
udelay (10); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PRINTK2("MMU ready\n"); |
|
|
|
|
PRINTK2 ("MMU ready\n"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} else { |
|
|
|
|
/* ack. int */ |
|
|
|
|
SMC_outw(IM_TX_INT, SMC91111_INT_REG); |
|
|
|
|
PRINTK2("%s: Sent packet of length %d \n", SMC_DEV_NAME, length); |
|
|
|
|
SMC_outw (IM_TX_INT, SMC91111_INT_REG); |
|
|
|
|
PRINTK2 ("%s: Sent packet of length %d \n", SMC_DEV_NAME, |
|
|
|
|
length); |
|
|
|
|
|
|
|
|
|
/* release packet */ |
|
|
|
|
SMC_outw(MC_FREEPKT, MMU_CMD_REG); |
|
|
|
|
SMC_outw (MC_FREEPKT, MMU_CMD_REG); |
|
|
|
|
|
|
|
|
|
/* wait for MMU getting ready (low) */ |
|
|
|
|
while (SMC_inw(MMU_CMD_REG) & MC_BUSY) |
|
|
|
|
{ |
|
|
|
|
udelay(10); |
|
|
|
|
while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { |
|
|
|
|
udelay (10); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PRINTK2("MMU ready\n"); |
|
|
|
|
PRINTK2 ("MMU ready\n"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
@ -667,64 +666,47 @@ void smc_destructor() |
|
|
|
|
* Set up everything, reset the card, etc .. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
static int smc_open(bd_t *bd) |
|
|
|
|
static int smc_open (bd_t * bd) |
|
|
|
|
{ |
|
|
|
|
int i, err; |
|
|
|
|
|
|
|
|
|
PRINTK2("%s:smc_open\n", SMC_DEV_NAME); |
|
|
|
|
PRINTK2 ("%s:smc_open\n", SMC_DEV_NAME); |
|
|
|
|
|
|
|
|
|
/* reset the hardware */ |
|
|
|
|
smc_reset(); |
|
|
|
|
smc_enable(); |
|
|
|
|
smc_reset (); |
|
|
|
|
smc_enable (); |
|
|
|
|
|
|
|
|
|
/* Configure the PHY */ |
|
|
|
|
#ifndef CONFIG_SMC91111_EXT_PHY |
|
|
|
|
smc_phy_configure(); |
|
|
|
|
smc_phy_configure (); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* conservative setting (10Mbps, HalfDuplex, no AutoNeg.) */ |
|
|
|
|
/* SMC_SELECT_BANK(0); */ |
|
|
|
|
/* SMC_outw(0, RPC_REG); */ |
|
|
|
|
SMC_SELECT_BANK(1); |
|
|
|
|
SMC_SELECT_BANK (1); |
|
|
|
|
|
|
|
|
|
err = smc_get_ethaddr(bd); /* set smc_mac_addr, and sync it with u-boot globals */ |
|
|
|
|
if(err < 0){ |
|
|
|
|
memset(bd->bi_enetaddr, 0, 6); /* hack to make error stick! upper code will abort if not set*/ |
|
|
|
|
return(-1); /* upper code ignores this, but NOT bi_enetaddr */ |
|
|
|
|
err = smc_get_ethaddr (bd); /* set smc_mac_addr, and sync it with u-boot globals */ |
|
|
|
|
if (err < 0) { |
|
|
|
|
memset (bd->bi_enetaddr, 0, 6); /* hack to make error stick! upper code will abort if not set */ |
|
|
|
|
return (-1); /* upper code ignores this, but NOT bi_enetaddr */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef USE_32_BIT |
|
|
|
|
for ( i = 0; i < 6; i += 2 ) { |
|
|
|
|
for (i = 0; i < 6; i += 2) { |
|
|
|
|
word address; |
|
|
|
|
|
|
|
|
|
address = smc_mac_addr[ i + 1 ] << 8 ; |
|
|
|
|
address |= smc_mac_addr[ i ]; |
|
|
|
|
SMC_outw( address, ADDR0_REG + i ); |
|
|
|
|
address = smc_mac_addr[i + 1] << 8; |
|
|
|
|
address |= smc_mac_addr[i]; |
|
|
|
|
SMC_outw (address, ADDR0_REG + i); |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
for ( i = 0; i < 6; i ++ ) |
|
|
|
|
SMC_outb( smc_mac_addr[i], ADDR0_REG + i ); |
|
|
|
|
for (i = 0; i < 6; i++) |
|
|
|
|
SMC_outb (smc_mac_addr[i], ADDR0_REG + i); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if 0 /* dead code? -- wd */
|
|
|
|
|
#ifdef USE_32_BIT |
|
|
|
|
void |
|
|
|
|
insl32(r,b,l) |
|
|
|
|
{ |
|
|
|
|
int __i ; |
|
|
|
|
dword *__b2; |
|
|
|
|
|
|
|
|
|
__b2 = (dword *) b; |
|
|
|
|
for (__i = 0; __i < l; __i++) { |
|
|
|
|
*(__b2 + __i) = *(dword *)(r+0x10000300); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------
|
|
|
|
|
. |
|
|
|
|
. smc_rcv - receive a packet from the card |
|
|
|
@ -920,44 +902,40 @@ static int smc_get_reg(int bank, int ioaddr, int reg) |
|
|
|
|
/*------------------------------------------------------------
|
|
|
|
|
. Debugging function for viewing MII Management serial bitstream |
|
|
|
|
.-------------------------------------------------------------*/ |
|
|
|
|
static void smc_dump_mii_stream(byte* bits, int size) |
|
|
|
|
static void smc_dump_mii_stream (byte * bits, int size) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
printf("BIT#:"); |
|
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
|
{ |
|
|
|
|
printf("%d", i%10); |
|
|
|
|
printf ("BIT#:"); |
|
|
|
|
for (i = 0; i < size; ++i) { |
|
|
|
|
printf ("%d", i % 10); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("\nMDOE:"); |
|
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
|
{ |
|
|
|
|
printf ("\nMDOE:"); |
|
|
|
|
for (i = 0; i < size; ++i) { |
|
|
|
|
if (bits[i] & MII_MDOE) |
|
|
|
|
printf("1"); |
|
|
|
|
printf ("1"); |
|
|
|
|
else |
|
|
|
|
printf("0"); |
|
|
|
|
printf ("0"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("\nMDO :"); |
|
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
|
{ |
|
|
|
|
printf ("\nMDO :"); |
|
|
|
|
for (i = 0; i < size; ++i) { |
|
|
|
|
if (bits[i] & MII_MDO) |
|
|
|
|
printf("1"); |
|
|
|
|
printf ("1"); |
|
|
|
|
else |
|
|
|
|
printf("0"); |
|
|
|
|
printf ("0"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("\nMDI :"); |
|
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
|
{ |
|
|
|
|
printf ("\nMDI :"); |
|
|
|
|
for (i = 0; i < size; ++i) { |
|
|
|
|
if (bits[i] & MII_MDI) |
|
|
|
|
printf("1"); |
|
|
|
|
printf ("1"); |
|
|
|
|
else |
|
|
|
|
printf("0"); |
|
|
|
|
printf ("0"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("\n"); |
|
|
|
|
printf ("\n"); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
@ -965,7 +943,7 @@ static void smc_dump_mii_stream(byte* bits, int size) |
|
|
|
|
. Reads a register from the MII Management serial interface |
|
|
|
|
.-------------------------------------------------------------*/ |
|
|
|
|
#ifndef CONFIG_SMC91111_EXT_PHY |
|
|
|
|
static word smc_read_phy_register(byte phyreg) |
|
|
|
|
static word smc_read_phy_register (byte phyreg) |
|
|
|
|
{ |
|
|
|
|
int oldBank; |
|
|
|
|
int i; |
|
|
|
@ -990,9 +968,8 @@ static word smc_read_phy_register(byte phyreg) |
|
|
|
|
bits[clk_idx++] = MII_MDOE; |
|
|
|
|
|
|
|
|
|
/* Output the PHY address, msb first */ |
|
|
|
|
mask = (byte)0x10; |
|
|
|
|
for (i = 0; i < 5; ++i) |
|
|
|
|
{ |
|
|
|
|
mask = (byte) 0x10; |
|
|
|
|
for (i = 0; i < 5; ++i) { |
|
|
|
|
if (phyaddr & mask) |
|
|
|
|
bits[clk_idx++] = MII_MDOE | MII_MDO; |
|
|
|
|
else |
|
|
|
@ -1003,9 +980,8 @@ static word smc_read_phy_register(byte phyreg) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Output the phy register number, msb first */ |
|
|
|
|
mask = (byte)0x10; |
|
|
|
|
for (i = 0; i < 5; ++i) |
|
|
|
|
{ |
|
|
|
|
mask = (byte) 0x10; |
|
|
|
|
for (i = 0; i < 5; ++i) { |
|
|
|
|
if (phyreg & mask) |
|
|
|
|
bits[clk_idx++] = MII_MDOE | MII_MDO; |
|
|
|
|
else |
|
|
|
@ -1030,43 +1006,41 @@ static word smc_read_phy_register(byte phyreg) |
|
|
|
|
bits[clk_idx++] = 0; |
|
|
|
|
|
|
|
|
|
/* Save the current bank */ |
|
|
|
|
oldBank = SMC_inw( BANK_SELECT ); |
|
|
|
|
oldBank = SMC_inw (BANK_SELECT); |
|
|
|
|
|
|
|
|
|
/* Select bank 3 */ |
|
|
|
|
SMC_SELECT_BANK( 3 ); |
|
|
|
|
SMC_SELECT_BANK (3); |
|
|
|
|
|
|
|
|
|
/* Get the current MII register value */ |
|
|
|
|
mii_reg = SMC_inw( MII_REG ); |
|
|
|
|
mii_reg = SMC_inw (MII_REG); |
|
|
|
|
|
|
|
|
|
/* Turn off all MII Interface bits */ |
|
|
|
|
mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO); |
|
|
|
|
mii_reg &= ~(MII_MDOE | MII_MCLK | MII_MDI | MII_MDO); |
|
|
|
|
|
|
|
|
|
/* Clock all 64 cycles */ |
|
|
|
|
for (i = 0; i < sizeof bits; ++i) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < sizeof bits; ++i) { |
|
|
|
|
/* Clock Low - output data */ |
|
|
|
|
SMC_outw( mii_reg | bits[i], MII_REG ); |
|
|
|
|
udelay(SMC_PHY_CLOCK_DELAY); |
|
|
|
|
SMC_outw (mii_reg | bits[i], MII_REG); |
|
|
|
|
udelay (SMC_PHY_CLOCK_DELAY); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Clock Hi - input data */ |
|
|
|
|
SMC_outw( mii_reg | bits[i] | MII_MCLK, MII_REG ); |
|
|
|
|
udelay(SMC_PHY_CLOCK_DELAY); |
|
|
|
|
bits[i] |= SMC_inw( MII_REG ) & MII_MDI; |
|
|
|
|
SMC_outw (mii_reg | bits[i] | MII_MCLK, MII_REG); |
|
|
|
|
udelay (SMC_PHY_CLOCK_DELAY); |
|
|
|
|
bits[i] |= SMC_inw (MII_REG) & MII_MDI; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Return to idle state */ |
|
|
|
|
/* Set clock to low, data to low, and output tristated */ |
|
|
|
|
SMC_outw( mii_reg, MII_REG ); |
|
|
|
|
udelay(SMC_PHY_CLOCK_DELAY); |
|
|
|
|
SMC_outw (mii_reg, MII_REG); |
|
|
|
|
udelay (SMC_PHY_CLOCK_DELAY); |
|
|
|
|
|
|
|
|
|
/* Restore original bank select */ |
|
|
|
|
SMC_SELECT_BANK( oldBank ); |
|
|
|
|
SMC_SELECT_BANK (oldBank); |
|
|
|
|
|
|
|
|
|
/* Recover input data */ |
|
|
|
|
phydata = 0; |
|
|
|
|
for (i = 0; i < 16; ++i) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < 16; ++i) { |
|
|
|
|
phydata <<= 1; |
|
|
|
|
|
|
|
|
|
if (bits[input_idx++] & MII_MDI) |
|
|
|
@ -1074,19 +1048,19 @@ static word smc_read_phy_register(byte phyreg) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if (SMC_DEBUG > 2 ) |
|
|
|
|
printf("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", |
|
|
|
|
printf ("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", |
|
|
|
|
phyaddr, phyreg, phydata); |
|
|
|
|
smc_dump_mii_stream(bits, sizeof bits); |
|
|
|
|
smc_dump_mii_stream (bits, sizeof bits); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
return(phydata); |
|
|
|
|
return (phydata); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------
|
|
|
|
|
. Writes a register to the MII Management serial interface |
|
|
|
|
.-------------------------------------------------------------*/ |
|
|
|
|
static void smc_write_phy_register(byte phyreg, word phydata) |
|
|
|
|
static void smc_write_phy_register (byte phyreg, word phydata) |
|
|
|
|
{ |
|
|
|
|
int oldBank; |
|
|
|
|
int i; |
|
|
|
@ -1109,9 +1083,8 @@ static void smc_write_phy_register(byte phyreg, word phydata) |
|
|
|
|
bits[clk_idx++] = MII_MDOE | MII_MDO; |
|
|
|
|
|
|
|
|
|
/* Output the PHY address, msb first */ |
|
|
|
|
mask = (byte)0x10; |
|
|
|
|
for (i = 0; i < 5; ++i) |
|
|
|
|
{ |
|
|
|
|
mask = (byte) 0x10; |
|
|
|
|
for (i = 0; i < 5; ++i) { |
|
|
|
|
if (phyaddr & mask) |
|
|
|
|
bits[clk_idx++] = MII_MDOE | MII_MDO; |
|
|
|
|
else |
|
|
|
@ -1122,9 +1095,8 @@ static void smc_write_phy_register(byte phyreg, word phydata) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Output the phy register number, msb first */ |
|
|
|
|
mask = (byte)0x10; |
|
|
|
|
for (i = 0; i < 5; ++i) |
|
|
|
|
{ |
|
|
|
|
mask = (byte) 0x10; |
|
|
|
|
for (i = 0; i < 5; ++i) { |
|
|
|
|
if (phyreg & mask) |
|
|
|
|
bits[clk_idx++] = MII_MDOE | MII_MDO; |
|
|
|
|
else |
|
|
|
@ -1140,8 +1112,7 @@ static void smc_write_phy_register(byte phyreg, word phydata) |
|
|
|
|
|
|
|
|
|
/* Write out 16 bits of data, msb first */ |
|
|
|
|
mask = 0x8000; |
|
|
|
|
for (i = 0; i < 16; ++i) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < 16; ++i) { |
|
|
|
|
if (phydata & mask) |
|
|
|
|
bits[clk_idx++] = MII_MDOE | MII_MDO; |
|
|
|
|
else |
|
|
|
@ -1155,43 +1126,42 @@ static void smc_write_phy_register(byte phyreg, word phydata) |
|
|
|
|
bits[clk_idx++] = 0; |
|
|
|
|
|
|
|
|
|
/* Save the current bank */ |
|
|
|
|
oldBank = SMC_inw( BANK_SELECT ); |
|
|
|
|
oldBank = SMC_inw (BANK_SELECT); |
|
|
|
|
|
|
|
|
|
/* Select bank 3 */ |
|
|
|
|
SMC_SELECT_BANK( 3 ); |
|
|
|
|
SMC_SELECT_BANK (3); |
|
|
|
|
|
|
|
|
|
/* Get the current MII register value */ |
|
|
|
|
mii_reg = SMC_inw( MII_REG ); |
|
|
|
|
mii_reg = SMC_inw (MII_REG); |
|
|
|
|
|
|
|
|
|
/* Turn off all MII Interface bits */ |
|
|
|
|
mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO); |
|
|
|
|
mii_reg &= ~(MII_MDOE | MII_MCLK | MII_MDI | MII_MDO); |
|
|
|
|
|
|
|
|
|
/* Clock all cycles */ |
|
|
|
|
for (i = 0; i < sizeof bits; ++i) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < sizeof bits; ++i) { |
|
|
|
|
/* Clock Low - output data */ |
|
|
|
|
SMC_outw( mii_reg | bits[i], MII_REG ); |
|
|
|
|
udelay(SMC_PHY_CLOCK_DELAY); |
|
|
|
|
SMC_outw (mii_reg | bits[i], MII_REG); |
|
|
|
|
udelay (SMC_PHY_CLOCK_DELAY); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Clock Hi - input data */ |
|
|
|
|
SMC_outw( mii_reg | bits[i] | MII_MCLK, MII_REG ); |
|
|
|
|
udelay(SMC_PHY_CLOCK_DELAY); |
|
|
|
|
bits[i] |= SMC_inw( MII_REG ) & MII_MDI; |
|
|
|
|
SMC_outw (mii_reg | bits[i] | MII_MCLK, MII_REG); |
|
|
|
|
udelay (SMC_PHY_CLOCK_DELAY); |
|
|
|
|
bits[i] |= SMC_inw (MII_REG) & MII_MDI; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Return to idle state */ |
|
|
|
|
/* Set clock to low, data to low, and output tristated */ |
|
|
|
|
SMC_outw( mii_reg, MII_REG ); |
|
|
|
|
udelay(SMC_PHY_CLOCK_DELAY); |
|
|
|
|
SMC_outw (mii_reg, MII_REG); |
|
|
|
|
udelay (SMC_PHY_CLOCK_DELAY); |
|
|
|
|
|
|
|
|
|
/* Restore original bank select */ |
|
|
|
|
SMC_SELECT_BANK( oldBank ); |
|
|
|
|
SMC_SELECT_BANK (oldBank); |
|
|
|
|
|
|
|
|
|
#if (SMC_DEBUG > 2 ) |
|
|
|
|
printf("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", |
|
|
|
|
printf ("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", |
|
|
|
|
phyaddr, phyreg, phydata); |
|
|
|
|
smc_dump_mii_stream(bits, sizeof bits); |
|
|
|
|
smc_dump_mii_stream (bits, sizeof bits); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
#endif /* !CONFIG_SMC91111_EXT_PHY */ |
|
|
|
@ -1213,7 +1183,7 @@ static void smc_wait_ms(unsigned int ms) |
|
|
|
|
. smc_phy_fixed() if the user has requested a certain config. |
|
|
|
|
.-------------------------------------------------------------*/ |
|
|
|
|
#ifndef CONFIG_SMC91111_EXT_PHY |
|
|
|
|
static void smc_phy_configure() |
|
|
|
|
static void smc_phy_configure () |
|
|
|
|
{ |
|
|
|
|
int timeout; |
|
|
|
|
byte phyaddr; |
|
|
|
@ -1222,32 +1192,29 @@ static void smc_phy_configure() |
|
|
|
|
word status = 0; /*;my status = 0 */ |
|
|
|
|
int failed = 0; |
|
|
|
|
|
|
|
|
|
PRINTK3("%s:smc_program_phy()\n", SMC_DEV_NAME); |
|
|
|
|
PRINTK3 ("%s:smc_program_phy()\n", SMC_DEV_NAME); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 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); |
|
|
|
|
smc_write_phy_register (PHY_CNTL_REG, PHY_CNTL_RST); |
|
|
|
|
|
|
|
|
|
/* Wait for the reset to complete, or time out */ |
|
|
|
|
timeout = 6; /* Wait up to 3 seconds */ |
|
|
|
|
while (timeout--) |
|
|
|
|
{ |
|
|
|
|
if (!(smc_read_phy_register(PHY_CNTL_REG) |
|
|
|
|
& PHY_CNTL_RST)) |
|
|
|
|
{ |
|
|
|
|
while (timeout--) { |
|
|
|
|
if (!(smc_read_phy_register (PHY_CNTL_REG) |
|
|
|
|
& PHY_CNTL_RST)) { |
|
|
|
|
/* reset complete */ |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
smc_wait_ms(500); /* wait 500 millisecs */ |
|
|
|
|
smc_wait_ms (500); /* wait 500 millisecs */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (timeout < 1) |
|
|
|
|
{ |
|
|
|
|
printf("%s:PHY reset timed out\n", SMC_DEV_NAME); |
|
|
|
|
if (timeout < 1) { |
|
|
|
|
printf ("%s:PHY reset timed out\n", SMC_DEV_NAME); |
|
|
|
|
goto smc_phy_configure_exit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1256,14 +1223,14 @@ static void smc_phy_configure() |
|
|
|
|
|
|
|
|
|
/* Enable PHY Interrupts (for register 18) */ |
|
|
|
|
/* Interrupts listed here are disabled */ |
|
|
|
|
smc_write_phy_register(PHY_INT_REG, 0xffff); |
|
|
|
|
smc_write_phy_register (PHY_INT_REG, 0xffff); |
|
|
|
|
|
|
|
|
|
/* Configure the Receive/Phy Control register */ |
|
|
|
|
SMC_SELECT_BANK( 0 ); |
|
|
|
|
SMC_outw( RPC_DEFAULT, RPC_REG ); |
|
|
|
|
SMC_SELECT_BANK (0); |
|
|
|
|
SMC_outw (RPC_DEFAULT, RPC_REG); |
|
|
|
|
|
|
|
|
|
/* Copy our capabilities from PHY_STAT_REG to PHY_AD_REG */ |
|
|
|
|
my_phy_caps = smc_read_phy_register(PHY_STAT_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) |
|
|
|
@ -1282,62 +1249,59 @@ static void smc_phy_configure() |
|
|
|
|
my_ad_caps |= PHY_AD_10_HDX; |
|
|
|
|
|
|
|
|
|
/* Update our Auto-Neg Advertisement Register */ |
|
|
|
|
smc_write_phy_register( PHY_AD_REG, my_ad_caps); |
|
|
|
|
smc_write_phy_register (PHY_AD_REG, my_ad_caps); |
|
|
|
|
|
|
|
|
|
PRINTK2("%s:phy caps=%x\n", SMC_DEV_NAME, my_phy_caps); |
|
|
|
|
PRINTK2("%s:phy advertised caps=%x\n", SMC_DEV_NAME, my_ad_caps); |
|
|
|
|
PRINTK2 ("%s:phy caps=%x\n", SMC_DEV_NAME, my_phy_caps); |
|
|
|
|
PRINTK2 ("%s:phy advertised caps=%x\n", SMC_DEV_NAME, my_ad_caps); |
|
|
|
|
|
|
|
|
|
/* 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 ); |
|
|
|
|
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) |
|
|
|
|
{ |
|
|
|
|
while (timeout--) { |
|
|
|
|
status = smc_read_phy_register (PHY_STAT_REG); |
|
|
|
|
if (status & PHY_STAT_ANEG_ACK) { |
|
|
|
|
/* auto-negotiate complete */ |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
smc_wait_ms(500); /* wait 500 millisecs */ |
|
|
|
|
smc_wait_ms (500); /* wait 500 millisecs */ |
|
|
|
|
|
|
|
|
|
/* Restart auto-negotiation if remote fault */ |
|
|
|
|
if (status & PHY_STAT_REM_FLT) |
|
|
|
|
{ |
|
|
|
|
printf("%s:PHY remote fault detected\n", SMC_DEV_NAME); |
|
|
|
|
if (status & PHY_STAT_REM_FLT) { |
|
|
|
|
printf ("%s:PHY remote fault detected\n", |
|
|
|
|
SMC_DEV_NAME); |
|
|
|
|
|
|
|
|
|
/* Restart auto-negotiation */ |
|
|
|
|
printf("%s:PHY restarting auto-negotiation\n", |
|
|
|
|
printf ("%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); |
|
|
|
|
smc_write_phy_register (PHY_CNTL_REG, |
|
|
|
|
PHY_CNTL_ANEG_EN | |
|
|
|
|
PHY_CNTL_ANEG_RST | |
|
|
|
|
PHY_CNTL_SPEED | |
|
|
|
|
PHY_CNTL_DPLX); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (timeout < 1) |
|
|
|
|
{ |
|
|
|
|
printf("%s:PHY auto-negotiate timed out\n", |
|
|
|
|
SMC_DEV_NAME); |
|
|
|
|
printf("%s:PHY auto-negotiate timed out\n", SMC_DEV_NAME); |
|
|
|
|
if (timeout < 1) { |
|
|
|
|
printf ("%s:PHY auto-negotiate timed out\n", SMC_DEV_NAME); |
|
|
|
|
printf ("%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) |
|
|
|
|
{ |
|
|
|
|
printf( "%s:PHY remote fault detected\n", SMC_DEV_NAME); |
|
|
|
|
printf("%s:PHY remote fault detected\n", SMC_DEV_NAME); |
|
|
|
|
if (status & PHY_STAT_REM_FLT) { |
|
|
|
|
printf ("%s:PHY remote fault detected\n", SMC_DEV_NAME); |
|
|
|
|
printf ("%s:PHY remote fault detected\n", SMC_DEV_NAME); |
|
|
|
|
failed = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Re-Configure the Receive/Phy Control register */ |
|
|
|
|
SMC_outw( RPC_DEFAULT, RPC_REG ); |
|
|
|
|
SMC_outw (RPC_DEFAULT, RPC_REG); |
|
|
|
|
|
|
|
|
|
smc_phy_configure_exit: |
|
|
|
|
|
|
|
|
@ -1400,19 +1364,19 @@ int eth_send(volatile void *packet, int length) { |
|
|
|
|
return smc_send_packet(packet, length); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int smc_get_ethaddr(bd_t *bd) |
|
|
|
|
int smc_get_ethaddr (bd_t * bd) |
|
|
|
|
{ |
|
|
|
|
int env_size, rom_valid, env_present = 0, reg; |
|
|
|
|
char *s = NULL, *e, *v_mac, es[] = "11:22:33:44:55:66"; |
|
|
|
|
uchar s_env_mac[64], v_env_mac[6], v_rom_mac[6]; |
|
|
|
|
|
|
|
|
|
env_size = getenv_r ("ethaddr", s_env_mac, sizeof (s_env_mac)); |
|
|
|
|
if ((env_size > 0) && (env_size < sizeof(es))) { /* exit if env is bad */ |
|
|
|
|
printf("\n*** ERROR: ethaddr is not set properly!!\n"); |
|
|
|
|
return(-1); |
|
|
|
|
if ((env_size > 0) && (env_size < sizeof (es))) { /* exit if env is bad */ |
|
|
|
|
printf ("\n*** ERROR: ethaddr is not set properly!!\n"); |
|
|
|
|
return (-1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(env_size > 0){ |
|
|
|
|
if (env_size > 0) { |
|
|
|
|
env_present = 1; |
|
|
|
|
s = s_env_mac; |
|
|
|
|
} |
|
|
|
@ -1423,51 +1387,67 @@ int smc_get_ethaddr(bd_t *bd) |
|
|
|
|
s = (*e) ? e + 1 : e; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
rom_valid = get_rom_mac(v_rom_mac); /* get ROM mac value if any */ |
|
|
|
|
rom_valid = get_rom_mac (v_rom_mac); /* get ROM mac value if any */ |
|
|
|
|
|
|
|
|
|
if(!env_present){ /* if NO env */ |
|
|
|
|
if(rom_valid){ /* but ROM is valid */ |
|
|
|
|
if (!env_present) { /* if NO env */ |
|
|
|
|
if (rom_valid) { /* but ROM is valid */ |
|
|
|
|
v_mac = v_rom_mac; |
|
|
|
|
sprintf (s_env_mac, "%02X:%02X:%02X:%02X:%02X:%02X", v_mac[0], |
|
|
|
|
v_mac[1] ,v_mac[2], v_mac[3],v_mac[4], v_mac[5]) ; |
|
|
|
|
sprintf (s_env_mac, "%02X:%02X:%02X:%02X:%02X:%02X", |
|
|
|
|
v_mac[0], v_mac[1], v_mac[2], v_mac[3], |
|
|
|
|
v_mac[4], v_mac[5]); |
|
|
|
|
setenv ("ethaddr", s_env_mac); |
|
|
|
|
}else{ /* no env, bad ROM */ |
|
|
|
|
printf("\n*** ERROR: ethaddr is NOT set !!\n"); |
|
|
|
|
return(-1); |
|
|
|
|
} else { /* no env, bad ROM */ |
|
|
|
|
printf ("\n*** ERROR: ethaddr is NOT set !!\n"); |
|
|
|
|
return (-1); |
|
|
|
|
} |
|
|
|
|
}else /* good env, don't care ROM */ |
|
|
|
|
} else { /* good env, don't care ROM */ |
|
|
|
|
v_mac = v_env_mac; /* always use a good env over a ROM */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(env_present && rom_valid) /* if both env and ROM are good */ |
|
|
|
|
if(memcmp(v_env_mac, v_rom_mac, 6) != 0){ |
|
|
|
|
printf("\n*** Warning: Environment and ROM MAC addresses don't match\n"); |
|
|
|
|
printf("*** Using Environment MAC\n"); |
|
|
|
|
if (env_present && rom_valid) { /* if both env and ROM are good */ |
|
|
|
|
if (memcmp (v_env_mac, v_rom_mac, 6) != 0) { |
|
|
|
|
printf ("\n*** Warning: Environment and ROM MAC addresses don't match\n"); |
|
|
|
|
printf ("*** Using Environment MAC\n"); |
|
|
|
|
----- |
|
|
|
|
printf ("\nWarning: MAC addresses don't match:\n"); |
|
|
|
|
printf ("\tHW MAC address: " |
|
|
|
|
"%02X:%02X:%02X:%02X:%02X:%02X\n", |
|
|
|
|
v_rom_mac[0], v_rom_mac[1], |
|
|
|
|
v_rom_mac[2], v_rom_mac[3], |
|
|
|
|
v_rom_mac[4], v_rom_mac[5] ); |
|
|
|
|
printf ("\t\"ethaddr\" value: " |
|
|
|
|
"%02X:%02X:%02X:%02X:%02X:%02X\n", |
|
|
|
|
v_env_mac[0], v_env_mac[1], |
|
|
|
|
v_env_mac[2], v_env_mac[3], |
|
|
|
|
v_env_mac[4], v_env_mac[5]) ; |
|
|
|
|
debug ("### Set MAC addr from environment\n"); |
|
|
|
|
memcpy (addr, env_enetaddr, 6); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
memcpy (bd->bi_enetaddr, v_mac, 6); /* update global address to match env (allows env changing) */ |
|
|
|
|
smc_set_mac_addr(v_mac); /* use old function to update smc default */ |
|
|
|
|
return(0); |
|
|
|
|
smc_set_mac_addr (v_mac); /* use old function to update smc default */ |
|
|
|
|
return (0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int get_rom_mac(char *v_rom_mac) |
|
|
|
|
int get_rom_mac (char *v_rom_mac) |
|
|
|
|
{ |
|
|
|
|
int is_rom_present = 0; |
|
|
|
|
|
|
|
|
|
#ifdef HARDCODE_MAC /* used for testing or to supress run time warnings */ |
|
|
|
|
char hw_mac_addr[] = {0x02, 0x80, 0xad, 0x20, 0x31, 0xb8}; |
|
|
|
|
char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 }; |
|
|
|
|
|
|
|
|
|
memcpy (v_rom_mac, hw_mac_addr, 6); |
|
|
|
|
return(1); |
|
|
|
|
return (1); |
|
|
|
|
#else |
|
|
|
|
if(is_rom_present) |
|
|
|
|
{ |
|
|
|
|
if (is_rom_present) { |
|
|
|
|
/* if eeprom contents are valid
|
|
|
|
|
* extract mac address into hw_mac_addr, 8 or 16 bit accesses |
|
|
|
|
* memcpy (v_rom_mac, hc_mac_addr, 6); |
|
|
|
|
* return(1); |
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|
memset(v_rom_mac, 0, 6); |
|
|
|
|
return(0); |
|
|
|
|
memset (v_rom_mac, 0, 6); |
|
|
|
|
return (0); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif /* CONFIG_DRIVER_SMC91111 */ |
|
|
|
|