u-boot/drivers/net/rtl8019.c
Mike Frysinger d3f871482f drivers/net/: get mac address from environment
The environment is the canonical storage location of the mac address, so
we're killing off the global data location and moving everything to
querying the env directly.

The drivers that get converted here:
	3c589
	4xx_enet
	dc2114x
	dm9000x
	enc28j60
	fsl_mcdmafec
	ks8695eth
	mcffec
	rtl8019
	rtl8169
	s3c4510b_eth
	xilinx_emac
	xilinx_emaclite

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
CC: Ben Warren <biggerbadderben@gmail.com>
CC: Rolf Offermanns <rof@sysgo.de>
CC: Stefan Roese <sr@denx.de>
CC: Sascha Hauer <saschahauer@web.de>
CC: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
CC: Greg Ungerer <greg.ungerer@opengear.com>
CC: Xue Ligong <lgxue@hotmail.com>
CC: Masami Komiya <mkomiya@sonare.it>
CC: Curt Brune <curt@cucy.com>
CC: Michal SIMEK <monstr@monstr.eu>
2009-03-20 22:39:10 +01:00

271 lines
7.5 KiB
C

/*
* Realtek 8019AS Ethernet
* (C) Copyright 2002-2003
* Xue Ligong(lgxue@hotmail.com),Wang Kehao, ESLAB, whut.edu.cn
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* 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
* 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
*/
/*
* This code works in 8bit mode.
* If you need to work in 16bit mode, PLS change it!
*/
#include <common.h>
#include <command.h>
#include "rtl8019.h"
#include <net.h>
/* packet page register access functions */
static unsigned char get_reg (unsigned int regno)
{
return (*(unsigned char *) regno);
}
static void put_reg (unsigned int regno, unsigned char val)
{
*(volatile unsigned char *) regno = val;
}
static void eth_reset (void)
{
unsigned char ucTemp;
/* reset NIC */
ucTemp = get_reg (RTL8019_RESET);
put_reg (RTL8019_RESET, ucTemp);
put_reg (RTL8019_INTERRUPTSTATUS, 0xff);
udelay (2000); /* wait for 2ms */
}
void rtl8019_get_enetaddr (uchar * addr)
{
unsigned char i;
unsigned char temp;
eth_reset ();
put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);
put_reg (RTL8019_DATACONFIGURATION, 0x48);
put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00);
put_reg (RTL8019_REMOTESTARTADDRESS1, 0x00);
put_reg (RTL8019_REMOTEBYTECOUNT0, 12);
put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);
printf ("MAC: ");
for (i = 0; i < 6; i++) {
temp = get_reg (RTL8019_DMA_DATA);
*addr++ = temp;
temp = get_reg (RTL8019_DMA_DATA);
printf ("%x:", temp);
}
while ((!get_reg (RTL8019_INTERRUPTSTATUS) & 0x40));
printf ("\b \n");
put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00);
put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
}
void eth_halt (void)
{
put_reg (RTL8019_COMMAND, 0x01);
}
int eth_init (bd_t * bd)
{
uchar enetaddr[6];
eth_reset ();
put_reg (RTL8019_COMMAND, RTL8019_PAGE0STOP);
put_reg (RTL8019_DATACONFIGURATION, 0x48);
put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00);
put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
put_reg (RTL8019_RECEIVECONFIGURATION, 0x00); /*00; */
put_reg (RTL8019_TRANSMITPAGE, RTL8019_TPSTART);
put_reg (RTL8019_TRANSMITCONFIGURATION, 0x02);
put_reg (RTL8019_PAGESTART, RTL8019_PSTART);
put_reg (RTL8019_BOUNDARY, RTL8019_PSTART);
put_reg (RTL8019_PAGESTOP, RTL8019_PSTOP);
put_reg (RTL8019_INTERRUPTSTATUS, 0xff);
put_reg (RTL8019_INTERRUPTMASK, 0x11); /*b; */
put_reg (RTL8019_COMMAND, RTL8019_PAGE1STOP);
eth_getenv_enetaddr("ethaddr", enetaddr);
put_reg (RTL8019_PHYSICALADDRESS0, enetaddr[0]);
put_reg (RTL8019_PHYSICALADDRESS1, enetaddr[1]);
put_reg (RTL8019_PHYSICALADDRESS2, enetaddr[2]);
put_reg (RTL8019_PHYSICALADDRESS3, enetaddr[3]);
put_reg (RTL8019_PHYSICALADDRESS4, enetaddr[4]);
put_reg (RTL8019_PHYSICALADDRESS5, enetaddr[5]);
put_reg (RTL8019_MULTIADDRESS0, 0x00);
put_reg (RTL8019_MULTIADDRESS1, 0x00);
put_reg (RTL8019_MULTIADDRESS2, 0x00);
put_reg (RTL8019_MULTIADDRESS3, 0x00);
put_reg (RTL8019_MULTIADDRESS4, 0x00);
put_reg (RTL8019_MULTIADDRESS5, 0x00);
put_reg (RTL8019_MULTIADDRESS6, 0x00);
put_reg (RTL8019_MULTIADDRESS7, 0x00);
put_reg (RTL8019_CURRENT, RTL8019_PSTART);
put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
put_reg (RTL8019_TRANSMITCONFIGURATION, 0xe0); /*58; */
return 0;
}
static unsigned char nic_to_pc (void)
{
unsigned char rec_head_status;
unsigned char next_packet_pointer;
unsigned char packet_length0;
unsigned char packet_length1;
unsigned short rxlen = 0;
unsigned int i = 4;
unsigned char current_point;
unsigned char *addr;
/*
* The RTL8019's first 4B is packet status,page of next packet
* and packet length(2B).So we receive the fist 4B.
*/
put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY));
put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00);
put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00);
put_reg (RTL8019_REMOTEBYTECOUNT0, 0x04);
put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);
rec_head_status = get_reg (RTL8019_DMA_DATA);
next_packet_pointer = get_reg (RTL8019_DMA_DATA);
packet_length0 = get_reg (RTL8019_DMA_DATA);
packet_length1 = get_reg (RTL8019_DMA_DATA);
put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
/*Packet length is in two 8bit registers */
rxlen = packet_length1;
rxlen = (((rxlen << 8) & 0xff00) + packet_length0);
rxlen -= 4;
if (rxlen > PKTSIZE_ALIGN + PKTALIGN)
printf ("packet too big!\n");
/*Receive the packet */
put_reg (RTL8019_REMOTESTARTADDRESS0, 0x04);
put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY));
put_reg (RTL8019_REMOTEBYTECOUNT0, (rxlen & 0xff));
put_reg (RTL8019_REMOTEBYTECOUNT1, ((rxlen >> 8) & 0xff));
put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD);
for (addr = (unsigned char *) NetRxPackets[0], i = rxlen; i > 0; i--)
*addr++ = get_reg (RTL8019_DMA_DATA);
/* Pass the packet up to the protocol layers. */
NetReceive (NetRxPackets[0], rxlen);
while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40); /* wait for the op. */
/*
* To test whether the packets are all received,get the
* location of current point
*/
put_reg (RTL8019_COMMAND, RTL8019_PAGE1);
current_point = get_reg (RTL8019_CURRENT);
put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
put_reg (RTL8019_BOUNDARY, next_packet_pointer);
return current_point;
}
/* Get a data block via Ethernet */
extern int eth_rx (void)
{
unsigned char temp, current_point;
put_reg (RTL8019_COMMAND, RTL8019_PAGE0);
while (1) {
temp = get_reg (RTL8019_INTERRUPTSTATUS);
if (temp & 0x90) {
/*overflow */
put_reg (RTL8019_COMMAND, RTL8019_PAGE0STOP);
udelay (2000);
put_reg (RTL8019_REMOTEBYTECOUNT0, 0);
put_reg (RTL8019_REMOTEBYTECOUNT1, 0);
put_reg (RTL8019_TRANSMITCONFIGURATION, 2);
do {
current_point = nic_to_pc ();
} while (get_reg (RTL8019_BOUNDARY) != current_point);
put_reg (RTL8019_TRANSMITCONFIGURATION, 0xe0);
}
if (temp & 0x1) {
/*packet received */
do {
put_reg (RTL8019_INTERRUPTSTATUS, 0x01);
current_point = nic_to_pc ();
} while (get_reg (RTL8019_BOUNDARY) != current_point);
}
if (!(temp & 0x1))
return 0;
/* done and exit. */
}
}
/* Send a data block via Ethernet. */
extern int eth_send (volatile void *packet, int length)
{
volatile unsigned char *p;
unsigned int pn;
pn = length;
p = (volatile unsigned char *) packet;
while (get_reg (RTL8019_COMMAND) == RTL8019_TRANSMIT);
put_reg (RTL8019_REMOTESTARTADDRESS0, 0);
put_reg (RTL8019_REMOTESTARTADDRESS1, RTL8019_TPSTART);
put_reg (RTL8019_REMOTEBYTECOUNT0, (pn & 0xff));
put_reg (RTL8019_REMOTEBYTECOUNT1, ((pn >> 8) & 0xff));
put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMAWR);
while (pn > 0) {
put_reg (RTL8019_DMA_DATA, *p++);
pn--;
}
pn = length;
while (pn < 60) { /*Padding */
put_reg (RTL8019_DMA_DATA, 0);
pn++;
}
while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40);
put_reg (RTL8019_INTERRUPTSTATUS, 0x40);
put_reg (RTL8019_TRANSMITPAGE, RTL8019_TPSTART);
put_reg (RTL8019_TRANSMITBYTECOUNT0, (pn & 0xff));
put_reg (RTL8019_TRANSMITBYTECOUNT1, ((pn >> 8 & 0xff)));
put_reg (RTL8019_COMMAND, RTL8019_TRANSMIT);
return 0;
}