X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fsmc91111.c;h=f91e4b984369fca9c75138be33a808134e779610;hb=0f2859689a283ecb0e3d29e23ff7e21dbb6abb70;hp=d0cb695c4fc477eb70f25629245edb513d08e36e;hpb=b56ddc636ddcaacf7fa497819cc1b9517d610eee;p=u-boot diff --git a/drivers/smc91111.c b/drivers/smc91111.c index d0cb695c4f..f91e4b9843 100644 --- a/drivers/smc91111.c +++ b/drivers/smc91111.c @@ -7,7 +7,7 @@ . Rolf Offermanns . . Copyright (C) 2001 Standard Microsystems Corporation (SMSC) - . Developed by Simple Network Magic Corporation (SNMC) + . Developed by Simple Network Magic Corporation (SNMC) . Copyright (C) 1996 by Erik Stahlman (ES) . . This program is free software; you can redistribute it and/or modify @@ -17,12 +17,12 @@ . . This program is distributed in the hope that it will be useful, . but WITHOUT ANY WARRANTY; without even the implied warranty of - . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the . GNU General Public License for more details. . . You should have received a copy of the GNU General Public License . along with this program; if not, write to the Free Software - . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA . . Information contained in this file was obtained from the LAN91C111 . manual from SMC. To get a copy, if you really want one, you can find @@ -36,31 +36,32 @@ . EEPROM interface for configuration . . Arguments: - . io = for the base address + . io = for the base address . irq = for the IRQ . . author: - . Erik Stahlman ( erik@vt.edu ) - . Daris A Nevil ( dnevil@snmc.com ) + . Erik Stahlman ( erik@vt.edu ) + . Daris A Nevil ( dnevil@snmc.com ) . . . Hardware multicast code from Peter Cammaert ( pc@denkart.be ) . . Sources: - . o SMSC LAN91C111 databook (www.smsc.com) - . o smc9194.c by Erik Stahlman - . o skeleton.c by Donald Becker ( becker@cesdis.gsfc.nasa.gov ) + . o SMSC LAN91C111 databook (www.smsc.com) + . o smc9194.c by Erik Stahlman + . o skeleton.c by Donald Becker ( becker@cesdis.gsfc.nasa.gov ) . . History: - . 06/19/03 Richard Woodruff Made u-boot environment aware and added mac addr checks. + . 06/19/03 Richard Woodruff Made u-boot environment aware and added mac addr checks. . 10/17/01 Marco Hasewinkel Modify for DNP/1110 - . 07/25/01 Woojung Huh Modify for ADS Bitsy - . 04/25/01 Daris A Nevil Initial public release through SMSC - . 03/16/01 Daris A Nevil Modified smc9194.c for use with LAN91C111 + . 07/25/01 Woojung Huh Modify for ADS Bitsy + . 04/25/01 Daris A Nevil Initial public release through SMSC + . 03/16/01 Daris A Nevil Modified smc9194.c for use with LAN91C111 ----------------------------------------------------------------------------*/ #include #include +#include #include "smc91111.h" #include @@ -71,10 +72,17 @@ #define NO_AUTOPROBE +#define SMC_DEBUG 0 + +#if SMC_DEBUG > 1 static const char version[] = "smc91111.c:v1.0 04/25/01 by Daris A Nevil (dnevil@snmc.com)\n"; +#endif -#define SMC_DEBUG 0 +/* Autonegotiation timeout in seconds */ +#ifndef CONFIG_SMC_AUTONEG_TIMEOUT +#define CONFIG_SMC_AUTONEG_TIMEOUT 10 +#endif /*------------------------------------------------------------------------ . @@ -111,7 +119,7 @@ static const char version[] = /*------------------------------------------------------------------------ . - . The internal workings of the driver. If you are changing anything + . The internal workings of the driver. If you are changing anything . here with the SMC stuff, you should have the datasheet and know . what you are doing. . @@ -136,7 +144,7 @@ static const char version[] = #define ETH_ZLEN 60 -#ifdef CONFIG_SMC_USE_32_BIT +#ifdef CONFIG_SMC_USE_32_BIT #define USE_32_BIT 1 #else #undef USE_32_BIT @@ -152,6 +160,9 @@ extern void eth_halt(void); extern int eth_rx(void); extern int eth_send(volatile void *packet, int length); +#ifdef SHARED_RESOURCES + extern void swap_to(int device_id); +#endif /* . This is called by register_netdev(). It is responsible for @@ -202,7 +213,7 @@ static int smc_rcv(void); . If an EEPROM is present it really should be consulted. */ int smc_get_ethaddr(bd_t *bd); -int get_rom_mac(char *v_rom_mac); +int get_rom_mac(uchar *v_rom_mac); /* ------------------------------------------------------------ @@ -212,14 +223,91 @@ int get_rom_mac(char *v_rom_mac); ------------------------------------------------------------ */ -static char smc_mac_addr[] = {0x02, 0x80, 0xad, 0x20, 0x31, 0xb8}; +#ifdef CONFIG_SMC_USE_IOFUNCS +/* + * input and output functions + * + * Implemented due to inx,outx macros accessing the device improperly + * and putting the device into an unkown state. + * + * For instance, on Sharp LPD7A400 SDK, affects were chip memory + * could not be free'd (hence the alloc failures), duplicate packets, + * packets being corrupt (shifted) on the wire, etc. Switching to the + * inx,outx functions fixed this problem. + */ +static inline word SMC_inw(dword offset); +static inline void SMC_outw(word value, dword offset); +static inline byte SMC_inb(dword offset); +static inline void SMC_outb(byte value, dword offset); +static inline void SMC_insw(dword offset, volatile uchar* buf, dword len); +static inline void SMC_outsw(dword offset, uchar* buf, dword len); + +#define barrier() __asm__ __volatile__("": : :"memory") + +static inline word SMC_inw(dword offset) +{ + word v; + v = *((volatile word*)(SMC_BASE_ADDRESS+offset)); + barrier(); *(volatile u32*)(0xc0000000); + return v; +} + +static inline void SMC_outw(word value, dword offset) +{ + *((volatile word*)(SMC_BASE_ADDRESS+offset)) = value; + barrier(); *(volatile u32*)(0xc0000000); +} + +static inline byte SMC_inb(dword offset) +{ + word _w; + + _w = SMC_inw(offset & ~((dword)1)); + return (offset & 1) ? (byte)(_w >> 8) : (byte)(_w); +} + +static inline void SMC_outb(byte value, dword offset) +{ + word _w; + + _w = SMC_inw(offset & ~((dword)1)); + if (offset & 1) + *((volatile word*)(SMC_BASE_ADDRESS+(offset & ~((dword)1)))) = (value<<8) | (_w & 0x00ff); + else + *((volatile word*)(SMC_BASE_ADDRESS+offset)) = value | (_w & 0xff00); +} + +static inline void SMC_insw(dword offset, volatile uchar* buf, dword len) +{ + volatile word *p = (volatile word *)buf; + + while (len-- > 0) { + *p++ = SMC_inw(offset); + barrier(); + *((volatile u32*)(0xc0000000)); + } +} + +static inline void SMC_outsw(dword offset, uchar* buf, dword len) +{ + volatile word *p = (volatile word *)buf; + + while (len-- > 0) { + SMC_outw(*p++, offset); + barrier(); + *(volatile u32*)(0xc0000000); + } +} +#endif /* CONFIG_SMC_USE_IOFUNCS */ + +static char unsigned smc_mac_addr[6] = {0x02, 0x80, 0xad, 0x20, 0x31, 0xb8}; /* * This function must be called before smc_open() if you want to override * the default mac address. */ -void smc_set_mac_addr(const char *addr) { +void smc_set_mac_addr(const unsigned char *addr) { int i; for (i=0; i < sizeof(smc_mac_addr); i++){ @@ -251,7 +339,7 @@ void smc_get_macaddr( byte *addr ) { #endif /* 0 */ /*********************************************** - * Show available memory * + * Show available memory * ***********************************************/ void dump_memory_info(void) { @@ -335,8 +423,8 @@ static inline void smc_wait_mmu_release_complete (void) /* . Function: smc_reset( void ) . Purpose: - . This sets the SMC91111 chip to its normal state, hopefully from whatever - . mess that any other DOS driver has put it in. + . This sets the SMC91111 chip to its normal state, hopefully from whatever + . mess that any other DOS driver has put it in. . . Maybe I should reset more registers to defaults in here? SOFTRST should . do that for me. @@ -351,7 +439,7 @@ static inline void smc_wait_mmu_release_complete (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 */ @@ -412,7 +500,7 @@ static void smc_reset (void) */ static void smc_enable() { - PRINTK2("%s:smc_enable\n", SMC_DEV_NAME); + PRINTK2("%s: smc_enable\n", SMC_DEV_NAME); SMC_SELECT_BANK( 0 ); /* see the header file for options in TCR/RCR DEFAULT*/ SMC_outw( TCR_DEFAULT, TCR_REG ); @@ -434,11 +522,11 @@ static void smc_enable() . (1) maybe utilize power down mode. . Why not yet? Because while the chip will go into power down mode, . the manual says that it will wake up in response to any I/O requests - . in the register space. Empirical results do not show this working. + . in the register space. Empirical results do not show this working. */ static void smc_shutdown() { - PRINTK2(CARDNAME ":smc_shutdown\n"); + PRINTK2(CARDNAME ": smc_shutdown\n"); /* no more interrupts for me */ SMC_SELECT_BANK( 2 ); @@ -448,6 +536,9 @@ static void smc_shutdown() SMC_SELECT_BANK( 0 ); SMC_outb( RCR_CLEAR, RCR_REG ); SMC_outb( TCR_CLEAR, TCR_REG ); +#ifdef SHARED_RESOURCES + swap_to(FLASH); +#endif } @@ -457,7 +548,7 @@ static void smc_shutdown() . This sends the actual packet to the SMC9xxx chip. . . Algorithm: - . First, see if a saved_skb is available. + . First, see if a saved_skb is available. . ( this should NOT be called if there is no 'saved_skb' . Now, find the packet number that the chip allocated . Point the data pointers at it in memory @@ -465,9 +556,9 @@ static void smc_shutdown() . Dump the packet to chip memory . Check if a last byte is needed ( odd length packet ) . if so, set the control flag right - . Tell the card to send it + . Tell the card to send it . Enable the transmit interrupt, so I know if it failed - . Free the kernel data if I actually sent it. + . Free the kernel data if I actually sent it. */ static int smc_send_packet (volatile void *packet, int packet_length) { @@ -479,9 +570,15 @@ static int smc_send_packet (volatile void *packet, int packet_length) int try = 0; int time_out; byte status; + byte saved_pnr; + word saved_ptr; + /* save PTR and PNR registers before manipulation */ + SMC_SELECT_BANK (2); + saved_pnr = SMC_inb( PN_REG ); + saved_ptr = SMC_inw( PTR_REG ); - 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; @@ -510,9 +607,9 @@ static int smc_send_packet (volatile void *packet, int packet_length) SMC_outw (MC_ALLOC | numPages, MMU_CMD_REG); /* FIXME: the ALLOC_INT bit never gets set * - * so the following will always give a * - * memory allocation error. * - * same code works in armboot though * + * so the following will always give a * + * memory allocation error. * + * same code works in armboot though * * -ro */ @@ -555,7 +652,18 @@ again: } /* we have a packet address, so tell the card to use it */ +#ifndef CONFIG_XAENIAX SMC_outb (packet_no, PN_REG); +#else + /* On Xaeniax board, we can't use SMC_outb here because that way + * the Allocate MMU command will end up written to the command register + * as well, which will lead to a problem. + */ + SMC_outl (packet_no << 16, 0); +#endif + /* do not write new ptr value if Write data fifo not empty */ + while ( saved_ptr & PTR_NOTEMPTY ) + printf ("Write data fifo not empty!\n"); /* point to the beginning of the packet */ SMC_outw (PTR_AUTOINC, PTR_REG); @@ -581,36 +689,61 @@ again: /* send the actual data . I _think_ it's faster to send the longs first, and then . mop up by sending the last word. It depends heavily - . on alignment, at least on the 486. Maybe it would be + . on alignment, at least on the 486. Maybe it would be . a good idea to check which is optimal? But that could take . almost as much time as is saved? */ #ifdef USE_32_BIT SMC_outsl (SMC91111_DATA_REG, buf, length >> 2); +#ifndef CONFIG_XAENIAX if (length & 0x2) SMC_outw (*((word *) (buf + (length & 0xFFFFFFFC))), SMC91111_DATA_REG); +#else + /* On XANEIAX, we can only use 32-bit writes, so we need to handle + * unaligned tail part specially. The standard code doesn't work. + */ + if ((length & 3) == 3) { + u16 * ptr = (u16*) &buf[length-3]; + SMC_outl((*ptr) | ((0x2000 | buf[length-1]) << 16), + SMC91111_DATA_REG); + } else if ((length & 2) == 2) { + u16 * ptr = (u16*) &buf[length-2]; + SMC_outl(*ptr, SMC91111_DATA_REG); + } else if (length & 1) { + SMC_outl((0x2000 | buf[length-1]), SMC91111_DATA_REG); + } else { + SMC_outl(0, SMC91111_DATA_REG); + } +#endif #else SMC_outsw (SMC91111_DATA_REG, buf, (length) >> 1); #endif /* USE_32_BIT */ - /* Send the last byte, if there is one. */ +#ifndef CONFIG_XAENIAX + /* Send the last byte, if there is one. */ if ((length & 1) == 0) { SMC_outw (0, SMC91111_DATA_REG); } else { SMC_outw (buf[length - 1] | 0x2000, SMC91111_DATA_REG); } +#endif /* and let the chipset deal with it */ 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)) { */ + /* poll for TX_EMPTY INT - autorelease enabled */ + if (poll4int(IM_TX_EMPTY_INT, SMC_TX_TIMEOUT)) { /* sending failed */ PRINTK2 ("%s: TX timeout, sending failed...\n", SMC_DEV_NAME); /* release packet */ - SMC_outw (MC_FREEPKT, MMU_CMD_REG); + /* no need to release, MMU does that now */ +#ifdef CONFIG_XAENIAX + SMC_outw (MC_FREEPKT, MMU_CMD_REG); +#endif /* wait for MMU getting ready (low) */ while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { @@ -623,12 +756,16 @@ again: return 0; } else { /* ack. int */ - SMC_outw (IM_TX_INT, SMC91111_INT_REG); + SMC_outb (IM_TX_EMPTY_INT, SMC91111_INT_REG); + /* SMC_outb (IM_TX_INT, SMC91111_INT_REG); */ PRINTK2 ("%s: Sent packet of length %d \n", SMC_DEV_NAME, length); /* release packet */ + /* no need to release, MMU does that now */ +#ifdef CONFIG_XAENIAX SMC_outw (MC_FREEPKT, MMU_CMD_REG); +#endif /* wait for MMU getting ready (low) */ while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { @@ -640,6 +777,18 @@ again: } + /* restore previously saved registers */ +#ifndef CONFIG_XAENIAX + SMC_outb( saved_pnr, PN_REG ); +#else + /* On Xaeniax board, we can't use SMC_outb here because that way + * the Allocate MMU command will end up written to the command register + * as well, which will lead to a problem. + */ + SMC_outl(saved_pnr << 16, 0); +#endif + SMC_outw( saved_ptr, PTR_REG ); + return length; } @@ -656,7 +805,7 @@ again: */ void smc_destructor() { - PRINTK2(CARDNAME ":smc_destructor\n"); + PRINTK2(CARDNAME ": smc_destructor\n"); } @@ -670,7 +819,7 @@ 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 (); @@ -688,7 +837,7 @@ static int smc_open (bd_t * bd) 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 */ + 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 @@ -697,11 +846,11 @@ static int smc_open (bd_t * bd) address = smc_mac_addr[i + 1] << 8; address |= smc_mac_addr[i]; - SMC_outw (address, ADDR0_REG + i); + SMC_outw (address, (ADDR0_REG + i)); } #else for (i = 0; i < 6; i++) - SMC_outb (smc_mac_addr[i], ADDR0_REG + i); + SMC_outb (smc_mac_addr[i], (ADDR0_REG + i)); #endif return 0; @@ -721,16 +870,21 @@ static int smc_open (bd_t * bd) */ static int smc_rcv() { - int packet_number; + int packet_number; word status; word packet_length; - int is_error = 0; + int is_error = 0; #ifdef USE_32_BIT dword stat_len; #endif - + byte saved_pnr; + word saved_ptr; SMC_SELECT_BANK(2); + /* save PTR and PTR registers */ + saved_pnr = SMC_inb( PN_REG ); + saved_ptr = SMC_inw( PTR_REG ); + packet_number = SMC_inw( RXFIFO_REG ); if ( packet_number & RXFIFO_REMPTY ) { @@ -738,7 +892,7 @@ static int smc_rcv() return 0; } - PRINTK3("%s:smc_rcv\n", SMC_DEV_NAME); + PRINTK3("%s: smc_rcv\n", SMC_DEV_NAME); /* start reading from the start of the packet */ SMC_outw( PTR_READ | PTR_RCV | PTR_AUTOINC, PTR_REG ); @@ -748,8 +902,8 @@ static int smc_rcv() status = stat_len & 0xffff; packet_length = stat_len >> 16; #else - status = SMC_inw( SMC91111_DATA_REG ); - packet_length = SMC_inw( SMC91111_DATA_REG ); + status = SMC_inw( SMC91111_DATA_REG ); + packet_length = SMC_inw( SMC91111_DATA_REG ); #endif packet_length &= 0x07ff; /* mask off top bits */ @@ -772,7 +926,7 @@ static int smc_rcv() /* QUESTION: Like in the TX routine, do I want to send the DWORDs or the bytes first, or some mixture. A mixture might improve already slow PIO - performance */ + performance */ SMC_insl( SMC91111_DATA_REG , NetRxPackets[0], packet_length >> 2 ); /* read the left over bytes */ if (packet_length & 3) { @@ -809,6 +963,18 @@ static int smc_rcv() while ( SMC_inw( MMU_CMD_REG ) & MC_BUSY ) udelay(1); /* Wait until not busy */ + /* restore saved registers */ +#ifndef CONFIG_XAENIAX + SMC_outb( saved_pnr, PN_REG ); +#else + /* On Xaeniax board, we can't use SMC_outb here because that way + * the Allocate MMU command will end up written to the command register + * as well, which will lead to a problem. + */ + SMC_outl( saved_pnr << 16, 0); +#endif + SMC_outw( saved_ptr, PTR_REG ); + if (!is_error) { /* Pass the packet up to the protocol layers. */ NetReceive(NetRxPackets[0], packet_length); @@ -824,13 +990,13 @@ static int smc_rcv() . smc_close . . this makes the board clean up everything that it can - . and not talk to the outside world. Caused by + . and not talk to the outside world. Caused by . an 'ifconfig ethX down' . -----------------------------------------------------*/ static int smc_close() { - PRINTK2("%s:smc_close\n", SMC_DEV_NAME); + PRINTK2("%s: smc_close\n", SMC_DEV_NAME); /* clear everything */ smc_shutdown(); @@ -1192,7 +1358,7 @@ 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 */ @@ -1223,7 +1389,7 @@ 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_MASK_REG, 0xffff); /* Configure the Receive/Phy Control register */ SMC_SELECT_BANK (0); @@ -1251,8 +1417,13 @@ static void smc_phy_configure () /* Update our Auto-Neg Advertisement Register */ 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); + /* 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); + + 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, @@ -1261,8 +1432,9 @@ static void smc_phy_configure () /* 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 */ + timeout = CONFIG_SMC_AUTONEG_TIMEOUT * 2; while (timeout--) { + status = smc_read_phy_register (PHY_STAT_REG); if (status & PHY_STAT_ANEG_ACK) { /* auto-negotiate complete */ @@ -1273,11 +1445,11 @@ static void smc_phy_configure () /* Restart auto-negotiation if remote fault */ if (status & PHY_STAT_REM_FLT) { - printf ("%s:PHY remote fault detected\n", + 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 | @@ -1288,22 +1460,20 @@ static void smc_phy_configure () } 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); + 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); + 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_phy_configure_exit: +smc_phy_configure_exit: ; } #endif /* !CONFIG_SMC91111_EXT_PHY */ @@ -1312,7 +1482,6 @@ static void smc_phy_configure () #if SMC_DEBUG > 2 static void print_packet( byte * buf, int length ) { -#if 0 int i; int remainder; int lines; @@ -1344,11 +1513,13 @@ static void print_packet( byte * buf, int length ) } printf("\n"); #endif -#endif } #endif int eth_init(bd_t *bd) { +#ifdef SHARED_RESOURCES + swap_to(ETHERNET); +#endif return (smc_open(bd)); } @@ -1368,7 +1539,8 @@ 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]; + char s_env_mac[64]; + uchar 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 */ @@ -1381,7 +1553,7 @@ int smc_get_ethaddr (bd_t * bd) s = s_env_mac; } - for (reg = 0; reg < 6; ++reg) { /* turn string into mac value */ + for (reg = 0; reg < 6; ++reg) { /* turn string into mac value */ v_env_mac[reg] = s ? simple_strtoul (s, &e, 16) : 0; if (s) s = (*e) ? e + 1 : e; @@ -1391,7 +1563,7 @@ int smc_get_ethaddr (bd_t * bd) if (!env_present) { /* if NO env */ if (rom_valid) { /* but ROM is valid */ - v_mac = v_rom_mac; + v_mac = (char *)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]); @@ -1401,14 +1573,11 @@ int smc_get_ethaddr (bd_t * bd) return (-1); } } else { /* good env, don't care ROM */ - v_mac = v_env_mac; /* always use a good env over a ROM */ + v_mac = (char *)v_env_mac; /* always use a good env over a ROM */ } - if (env_present && rom_valid) { /* if both env and ROM are good */ + 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", @@ -1421,33 +1590,34 @@ int smc_get_ethaddr (bd_t * bd) 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 */ + smc_set_mac_addr ((uchar *)v_mac); /* use old function to update smc default */ + PRINTK("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", v_mac[0], v_mac[1], + v_mac[2], v_mac[3], v_mac[4], v_mac[5]); return (0); } -int get_rom_mac (char *v_rom_mac) +int get_rom_mac (uchar *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 }; memcpy (v_rom_mac, hw_mac_addr, 6); return (1); #else - 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); - */ + int i; + int valid_mac = 0; + + SMC_SELECT_BANK (1); + for (i=0; i<6; i++) + { + v_rom_mac[i] = SMC_inb ((ADDR0_REG + i)); + valid_mac |= v_rom_mac[i]; } - memset (v_rom_mac, 0, 6); - return (0); + + return (valid_mac ? 1 : 0); #endif } #endif /* CONFIG_DRIVER_SMC91111 */