/*-------------------------------------------------------------------------
   Davicom DM9003EP function copy right information

   Copyright (C) 2008. Lin, Rongrong <woody@palmmicro.com>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This software 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-------------------------------------------------------------------------*/

#include "version.h"
#include "type.h"

#ifdef DM9003EP

#include "dm9000.h"
#include "apps.h"
#include "core.h"
#include "ar168.h"
#include "tcpip.h"
#include "bank2.h"

USHORT _sLenRemain;

// CE - CE1
// CMD - ADDR_A0

void _dm9000_write_reg(UCHAR iReg, UCHAR iVal)
{
	PCHAR p;

	p = (PCHAR)BANK_BASE;

	*p ++ = iReg;
	*p = iVal;
}

UCHAR _dm9000_read_reg(UCHAR iReg)
{
	PCHAR p;

	p = (PCHAR)BANK_BASE;
	*p ++ = iReg;

	return *p;
}

void dm9k_write_reg(UCHAR iReg, UCHAR iVal)
{
	EnableCE1();
	_dm9000_write_reg(iReg, iVal);
	DisableCEx();
}

UCHAR dm9k_read_reg(UCHAR iReg)
{
	UCHAR iVal;

	EnableCE1();
	iVal = _dm9000_read_reg(iReg);
	DisableCEx();

	return iVal;
}

UCHAR dm9k_read_port_reg(UCHAR iPort, UCHAR iReg)
{
	UCHAR iVal;

	EnableCE1();
	_dm9000_write_reg(SW_PINDEX, iPort);
	iVal = _dm9000_read_reg(iReg);
	DisableCEx();

	return iVal;
}

void dm9k_write_phy(UCHAR iAddr, USHORT sVal)
{
	EnableCE1();

	_dm9000_write_reg(NIC_EPDRL, (UCHAR)sVal);
	_dm9000_write_reg(NIC_EPDRH, (UCHAR)(sVal >> 8));

	_dm9000_write_reg(NIC_EPAR, 0x40 + iAddr);
	_dm9000_write_reg(NIC_EPCR, 0x0A);

	while ((_dm9000_read_reg(NIC_EPCR) & 0x01) == 0x01);
	_dm9000_write_reg(NIC_EPCR, 0x00);

	DisableCEx();
}

/*
USHORT dm9k_read_phy(UCHAR iAddr)
{
	USHORT sVal;

	EnableCE1();

	_dm9000_write_reg(NIC_EPAR, 0x40 + iAddr);
	_dm9000_write_reg(NIC_EPCR, 0x0C);

	while ((_dm9000_read_reg(NIC_EPCR) & 0x01) == 0x01);
	_dm9000_write_reg(NIC_EPCR, 0x00);

	sVal = P_MAKEWORD(_dm9000_read_reg(NIC_EPDRL), _dm9000_read_reg(NIC_EPDRH));

	DisableCEx();

	return sVal;
}
*/

/*
void Dm9000Read(PCHAR pBuf, USHORT sLen)
{
	EnableCE1();
	fixed_input(pBuf, sLen);
	DisableCEx();
	_sLenRemain -= sLen;
}
*/

void Dm9000ReadBypass(USHORT sLen)
{
	EnableCE1();
	fixed_input_bypass(sLen);
	DisableCEx();

	_sLenRemain -= sLen;
/*	if (_sLenRemain)
	{
		UdpDebugVal(_sLenRemain, 10);
	}
*/
}

void Dm9000Run()
{
	UCHAR iVal, iNum;

	EnableCE1();

	if (!(_dm9000_read_reg(NIC_ISR) & 0x01))	goto End;
	_dm9000_write_reg(NIC_ISR, 0x01);

	iNum = 0;
	do
	{
		_dm9000_read_reg(NIC_MRCMDX);	// dummy read
		iVal = _dm9000_read_reg(NIC_MRCMDX);
		if (!iVal)
		{
			_dm9000_write_reg(NIC_ISR, 0x0c);		// no packet
			break;
		}
		else if (iVal == 1)
		{
			_sLenRemain = P_MAKEWORD(_dm9000_read_reg(NIC_RXPLLR), _dm9000_read_reg(NIC_RXPLHR)) + DM9000_HEADER_SIZE;
			if (_sLenRemain >= DM9000_HEADER_SIZE + ETHERNET_MIN_SIZE + ETHERNET_CRC_SIZE && _sLenRemain <= DM9000_HEADER_SIZE + VLAN_HEADER_SIZE + ETHERNET_MAX_SIZE + ETHERNET_CRC_SIZE)
			{
				DisableCEx();
				HandlePacket();
				EnableCE1();
			}
			fixed_input_bypass(_sLenRemain);
			if ((_dm9000_read_reg(NIC_RASR) & 0x03) != 0x01)
			{	// check read status extensively
				goto Error;
			}
		}
		else
		{	// something is wrong
			goto Error;
	    }
		iNum ++;
	} while (iNum < ETHERNET_MAX_READ_PACKET);

End:
	DisableCEx();
	return;

Error:
	DisableCEx();
	dm9k_init();
}

void Dm9000Send(USHORT sLen, UCHAR iType)
{
	EnableCE1();

	if (iType == NET_SEND_NORMAL)
	{
		fixed_output(Adapter_pPacketBuf, sLen);
	}
#ifndef CALL_NONE
	else if (iType == NET_SEND_PPPOE)
	{
		fixed_output(Adapter_pPacketBuf, EP_DATA);
		fixed_output(PPPoE_pSendHead, PPPOE_INFO);
		fixed_output((PCHAR)(Adapter_pPacketBuf + EP_DATA), sLen - EP_DATA);
		sLen += PPPOE_INFO;
	}
#endif

	_dm9000_write_reg(NIC_TXPLL, (UCHAR)sLen);
	_dm9000_write_reg(NIC_TXPLH, (UCHAR)(sLen >> 8));

	_dm9000_write_reg(NIC_TCR, 0x01);
	while (!(_dm9000_read_reg(NIC_ISR) & 0x02));
	_dm9000_write_reg(NIC_ISR, 0x02);

	_dm9000_read_reg(NIC_NSR);

	DisableCEx();

/*	if ((dm9k_read_reg(NIC_NSR) & 0x04) == 0x04)
	{
		dm9k_write_reg(NIC_NSR, 0x04);
//		UdpDebugString("TSR1 send");
	}
	else
	{
		dm9k_write_reg(NIC_NSR, 0x08);
//		UdpDebugString("TSR2 send");
	}
*/
}

#endif
