/*
 * 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;
}
