/*
* Copyright (C) 2001-2002 by egnite Software GmbH. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgement:
*
* This product includes software developed by egnite Software GmbH
* and its contributors.
*
* THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
* SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* For additional information see http://www.ethernut.de/
*
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* $Log: ether.c,v $
* Revision 1.1 2002/08/01 17:34:30 harald
* First check in
*
*/
#include <string.h>
#include <io.h>
#include "rtlregs.h"
#include "util.h"
#include "eboot.h"
#include "arp.h"
#include "ether.h"
/*!
* \addtogroup xgStack
*/
/*@{*/
#define NIC_PAGE_SIZE 0x100
#define NIC_START_PAGE 0x40
#define NIC_STOP_PAGE 0x60
#define NIC_TX_PAGES 6
#define NIC_TX_BUFFERS 2
#define NIC_FIRST_TX_PAGE NIC_START_PAGE
#define NIC_FIRST_RX_PAGE (NIC_FIRST_TX_PAGE + NIC_TX_PAGES * NIC_TX_BUFFERS)
#define TX_PAGES 12
u_char mac[6] = { 0x00,0x06,0x98,0x00,0x00,0x00 };
volatile u_char *base = (u_char *)0x8300;
/*!
* Realtek packet header.
*/
struct nic_pkt_header {
u_char ph_status; /*!< \brief Status, contents of RSR register */
u_char ph_nextpg; /*!< \brief Page for next packet */
u_short ph_size; /*!< \brief Size of header and packet in octets */
};
/*!
* \brief Reset the NIC.
*
* \return 0 on success, -1 otherwise.
*/
static int NicReset(void)
{
u_char i;
u_char j;
for(j = 0; j < 20; j++) {
i = nic_read(NIC_RESET);
Delay(500);
nic_write(NIC_RESET, i);
for(i = 0; i < 20; i++) {
Delay(5000);
if(nic_read(NIC_PG0_ISR) & NIC_ISR_RST)
return 0;
}
}
return -1;
}
/*!
* \brief Initialize the NIC.
*
* For further description of the initialization
* please refer to the original Ethernut code.
*/
void NicInit(void)
{
u_short i;
/*
* Enable external data and address
* bus.
*/
outp(BV(SRE) | BV(SRW), MCUCR);
if(NicReset())
return;
nic_write(NIC_PG0_IMR, 0);
nic_write(NIC_PG0_ISR, 0xff);
nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
nic_write(NIC_PG3_EECR, NIC_EECR_EEM0 | NIC_EECR_EEM1);
nic_write(NIC_PG3_CONFIG3, 0);
nic_write(NIC_PG3_CONFIG2, NIC_CONFIG2_BSELB);
nic_write(NIC_PG3_EECR, 0);
Delay(50000);
nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
nic_write(NIC_PG0_DCR, NIC_DCR_LS | NIC_DCR_FT1);
nic_write(NIC_PG0_RBCR0, 0);
nic_write(NIC_PG0_RBCR1, 0);
nic_write(NIC_PG0_RCR, NIC_RCR_MON);
nic_write(NIC_PG0_TCR, NIC_TCR_LB0);
nic_write(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
nic_write(NIC_PG0_BNRY, NIC_STOP_PAGE - 1);
nic_write(NIC_PG0_PSTART, NIC_FIRST_RX_PAGE);
nic_write(NIC_PG0_PSTOP, NIC_STOP_PAGE);
nic_write(NIC_PG0_ISR, 0xff);
nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);
for(i = 0; i < 6; i++)
nic_write(NIC_PG1_PAR0 + i, mac[i]);
for(i = 0; i < 8; i++)
nic_write(NIC_PG1_MAR0 + i, 0);
nic_write(NIC_PG1_CURR, NIC_START_PAGE + TX_PAGES);
nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
nic_write(NIC_PG0_RCR, NIC_RCR_AB);
nic_write(NIC_PG0_ISR, 0xff);
nic_write(NIC_PG0_IMR, 0);
nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
nic_write(NIC_PG0_TCR, 0);
Delay(2000000);
}
/*!
* \brief Send an Ethernet frame.
*
* \param dmac Destination MAC address.
* \param type Frame type.
* \param len Frame size.
*
* \return 0 on success, -1 otherwise.
*/
int EtherOutput(u_char *dmac, u_short type, u_short len)
{
u_short i;
u_short sz;
u_char *cp;
ETHERHDR *eh;
#if 0
u_char isr;
#endif
if(type == ETHERTYPE_ARP) {
eh = &arpframe.eth_hdr;
cp = (u_char *)&arpframe;
}
else {
eh = &sframe.eth_hdr;
cp = (u_char *)&sframe;
}
for(i = 0; i < 6; i++)
eh->ether_shost[i] = mac[i];
if(dmac) {
for(i = 0; i < 6; i++)
eh->ether_dhost[i] = dmac[i];
}
else {
for(i = 0; i < 6; i++)
eh->ether_dhost[i] = 0xFF;
}
eh->ether_type = type;
if((len += sizeof(ETHERHDR)) < 60)
sz = 60;
else
sz = len;
nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
nic_write(NIC_PG0_RBCR0, (u_char)sz);
nic_write(NIC_PG0_RBCR1, (u_char)(sz >> 8));
nic_write(NIC_PG0_RSAR0, 0);
nic_write(NIC_PG0_RSAR1, NIC_FIRST_TX_PAGE);
nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD1);
/*
* Transfer frame.
*/
for(i = 0; i < len; i++, cp++)
nic_write(NIC_IOPORT, *cp);
for(i = len; i < sz; i++)
nic_write(NIC_IOPORT, 0);
/*
* Complete remote dma.
*/
nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
for(i = 0; i <= 20; i++)
if(nic_read(NIC_PG0_ISR) & NIC_ISR_RDC)
break;
nic_write(NIC_PG0_ISR, NIC_ISR_RDC);
/*
* Number of bytes to be transmitted.
*/
nic_write(NIC_PG0_TBCR0, (sz & 0xff));
nic_write(NIC_PG0_TBCR1, ((sz >> 8) & 0xff));
/*
* First page of packet to be transmitted.
*/
nic_write(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
/*
* Start transmission.
*/
nic_write(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);
/*
* Wait until transmission is completed or aborted