OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/orpsocv2/boards/xilinx/ml501/sw
    from Rev 67 to Rev 69
    Reverse comparison

Rev 67 → Rev 69

/eth/eth.c
0,0 → 1,935
//////////////////////////////////////////////////////////////////////
//// ////
//// Interrupt-driven Ethernet test code ////
//// ////
//// Description ////
//// ORPSoC test software ////
//// ////
//// To Do: ////
//// - It's a simple test for now, but could be adapted for ////
//// standalone use. ////
//// ////
//// Author(s): ////
//// - jb, jb@orsoc.se, with parts taken from Linux kernel ////
//// open_eth driver. ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file 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 source 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 source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
#include "support.h"
#include "board.h"
#include "spr_defs.h"
#include "int.h"
#include "uart.h"
#include "open_eth.h"
#include "mii.h"
 
/* Dummy exception functions */
void buserr_except(){}
void dpf_except(){}
void ipf_except(){}
void lpint_except(){}
void align_except(){}
void illegal_except(){}
void hpint_except(){}
void dtlbmiss_except(){}
void itlbmiss_except(){}
void range_except(){}
void syscall_except(){}
void fpu_except(){}
void trap_except(){}
void res2_except(){}
 
volatile unsigned tx_done;
 
/* Functions in this file */
void ethmac_setup(void);
void oeth_printregs(void);
void ethphy_init(void);
void oeth_dump_bds();
/* Interrupt functions */
void oeth_interrupt(void);
static void oeth_rx(void);
static void oeth_tx(void);
 
/* Defining RTLSIM turns off use of real printf'ing to save time in simulation */
//#define RTLSIM
 
#ifdef RTLSIM
#define printk
#else
#define printk printf
#endif
 
/* Let the ethernet packets use a space beginning here for buffering */
#define ETH_BUFF_BASE 0x01000000
 
 
#define RXBUFF_PREALLOC 1
#define TXBUFF_PREALLOC 1
//#undef RXBUFF_PREALLOC
//#undef TXBUFF_PREALLOC
 
/* The transmitter timeout
*/
#define TX_TIMEOUT (2*HZ)
 
/* Buffer number (must be 2^n)
*/
#define OETH_RXBD_NUM 8
#define OETH_TXBD_NUM 8
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1)
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1)
 
/* Buffer size
*/
#define OETH_RX_BUFF_SIZE 2048
#define OETH_TX_BUFF_SIZE 2048
 
/* OR32 Page size def */
#define PAGE_SHIFT 13
#define PAGE_SIZE (1UL << PAGE_SHIFT)
 
/* How many buffers per page
*/
#define OETH_RX_BUFF_PPGAE (PAGE_SIZE/OETH_RX_BUFF_SIZE)
#define OETH_TX_BUFF_PPGAE (PAGE_SIZE/OETH_TX_BUFF_SIZE)
 
/* How many pages is needed for buffers
*/
#define OETH_RX_BUFF_PAGE_NUM (OETH_RXBD_NUM/OETH_RX_BUFF_PPGAE)
#define OETH_TX_BUFF_PAGE_NUM (OETH_TXBD_NUM/OETH_TX_BUFF_PPGAE)
 
/* Buffer size (if not XXBUF_PREALLOC
*/
#define MAX_FRAME_SIZE 1518
 
/* The buffer descriptors track the ring buffers.
*/
struct oeth_private {
//struct sk_buff* rx_skbuff[OETH_RXBD_NUM];
//struct sk_buff* tx_skbuff[OETH_TXBD_NUM];
 
unsigned short tx_next; /* Next buffer to be sent */
unsigned short tx_last; /* Next buffer to be checked if packet sent */
unsigned short tx_full; /* Buffer ring fuul indicator */
unsigned short rx_cur; /* Next buffer to be checked if packet received */
oeth_regs *regs; /* Address of controller registers. */
oeth_bd *rx_bd_base; /* Address of Rx BDs. */
oeth_bd *tx_bd_base; /* Address of Tx BDs. */
// struct net_device_stats stats;
};
/*
void * memcpy(char* dest, char* src, int size)
{
int i;
for (i=0;i<size;i++) dest[i] = src[i];
return (void*) dest;
}
*/
void oeth_printregs(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
printk("Oeth regs: Mode Register : 0x%lx\n",(unsigned long) regs->moder); /* Mode Register */
printk("Oeth regs: Interrupt Source Register 0x%lx\n", (unsigned long) regs->int_src); /* Interrupt Source Register */
printk("Oeth regs: Interrupt Mask Register 0x%lx\n",(unsigned long) regs->int_mask); /* Interrupt Mask Register */
printk("Oeth regs: Back to Bak Inter Packet Gap Register 0x%lx\n",(unsigned long) regs->ipgt); /* Back to Bak Inter Packet Gap Register */
printk("Oeth regs: Non Back to Back Inter Packet Gap Register 1 0x%lx\n",(unsigned long) regs->ipgr1); /* Non Back to Back Inter Packet Gap Register 1 */
printk("Oeth regs: Non Back to Back Inter Packet Gap Register 2 0x%lx\n",(unsigned long) regs->ipgr2); /* Non Back to Back Inter Packet Gap Register 2 */
printk("Oeth regs: Packet Length Register (min. and max.) 0x%lx\n",(unsigned long) regs->packet_len); /* Packet Length Register (min. and max.) */
printk("Oeth regs: Collision and Retry Configuration Register 0x%lx\n",(unsigned long) regs->collconf); /* Collision and Retry Configuration Register */
printk("Oeth regs: Transmit Buffer Descriptor Number Register 0x%lx\n",(unsigned long) regs->tx_bd_num); /* Transmit Buffer Descriptor Number Register */
printk("Oeth regs: Control Module Mode Register 0x%lx\n",(unsigned long) regs->ctrlmoder); /* Control Module Mode Register */
printk("Oeth regs: MII Mode Register 0x%lx\n",(unsigned long) regs->miimoder); /* MII Mode Register */
printk("Oeth regs: MII Command Register 0x%lx\n",(unsigned long) regs->miicommand); /* MII Command Register */
printk("Oeth regs: MII Address Register 0x%lx\n",(unsigned long) regs->miiaddress); /* MII Address Register */
printk("Oeth regs: MII Transmit Data Register 0x%lx\n",(unsigned long) regs->miitx_data); /* MII Transmit Data Register */
printk("Oeth regs: MII Receive Data Register 0x%lx\n",(unsigned long) regs->miirx_data); /* MII Receive Data Register */
printk("Oeth regs: MII Status Register 0x%lx\n",(unsigned long) regs->miistatus); /* MII Status Register */
printk("Oeth regs: MAC Individual Address Register 0 0x%lx\n",(unsigned long) regs->mac_addr0); /* MAC Individual Address Register 0 */
printk("Oeth regs: MAC Individual Address Register 1 0x%lx\n",(unsigned long) regs->mac_addr1); /* MAC Individual Address Register 1 */
printk("Oeth regs: Hash Register 0 0x%lx\n",(unsigned long) regs->hash_addr0); /* Hash Register 0 */
printk("Oeth regs: Hash Register 1 0x%lx\n",(unsigned long) regs->hash_addr1); /* Hash Register 1 */
}
 
static int last_char;
 
void spin_cursor(void)
{
#ifdef RTLSIM
return;
#endif
volatile unsigned int i; // So the loop doesn't get optimised away
printk(" \r");
if (last_char == 0)
printk("/");
else if (last_char == 1)
printk("-");
else if (last_char == 2)
printk("\\");
else if (last_char == 3)
printk("|");
else if (last_char == 4)
printk("/");
else if (last_char == 5)
printk("-");
else if (last_char == 6)
printk("\\");
else if (last_char == 7)
{
printk("|");
last_char=-1;
}
last_char++;
for(i=0;i<20000;i++);
 
}
 
#define PHYNUM 0
 
/* Scan the MIIM bus for PHYs */
void scan_ethphys(void)
{
unsigned int phynum,regnum, i;
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
regs->miitx_data = 0;
for(phynum=0;phynum<32;phynum++)
{
for (regnum=0;regnum<8;regnum++)
{
printk("scan_ethphys: phy %d r%d ",phynum, regnum);
/* Now actually perform the read on the MIIM bus*/
regs->miiaddress = (regnum << 8) | phynum; /* Basic Control Register */
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY);
printk("%x\n",regs->miirx_data);
}
}
}
 
void ethmac_scanstatus(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
//printk("Oeth: regs->miistatus %x regs->miirx_data %x\n",regs->miistatus, regs->miirx_data);
regs->miiaddress = 0;
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_SCANSTAT;
//printk("Oeth: regs->miiaddress %x regs->miicommand %x\n",regs->miiaddress, regs->miicommand);
//regs->miicommand = 0;
volatile int i; for(i=0;i<1000;i++);
while(regs->miistatus & OETH_MIISTATUS_BUSY) ;
//spin_cursor();
//printk("\r");
or32_exit(0);
}
void
eth_mii_write(char phynum, short regnum, short data)
{
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE);
regs->miiaddress = (regnum << 8) | phynum;
regs->miitx_data = data;
regs->miicommand = OETH_MIICOMMAND_WCTRLDATA;
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY);
}
 
short
eth_mii_read(char phynum, short regnum)
{
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE);
regs->miiaddress = (regnum << 8) | phynum;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY);
return regs->miirx_data;
}
 
 
void ethphy_init(void)
{
/* Init the Alaska 88E1111 Phy */
char alaska88e1111_ml501_phynum = 0x7;
 
/* Init, reset */
short ctl = eth_mii_read(alaska88e1111_ml501_phynum, MII_BMCR);
ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
ctl |= BMCR_SPEED100; // 100MBit
ctl |= BMCR_FULLDPLX; // Full duplex
eth_mii_write(alaska88e1111_ml501_phynum, MII_BMCR, ctl);
 
// Setup Autoneg
short adv = eth_mii_read(alaska88e1111_ml501_phynum, MII_ADVERTISE);
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_1000XFULL
|ADVERTISE_1000XHALF | ADVERTISE_1000XPAUSE |
ADVERTISE_1000XPSE_ASYM);
adv |= ADVERTISE_10HALF;
adv |= ADVERTISE_10FULL;
adv |= ADVERTISE_100HALF;
adv |= ADVERTISE_100FULL;
eth_mii_write(alaska88e1111_ml501_phynum, MII_ADVERTISE, adv);
// Disable gigabit
adv = eth_mii_read(alaska88e1111_ml501_phynum, MII_CTRL1000);
adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
eth_mii_write(alaska88e1111_ml501_phynum, MII_CTRL1000, adv);
 
// Restart autoneg
printk("Resetting phy...\n");
ctl = eth_mii_read(alaska88e1111_ml501_phynum, MII_BMCR);
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
eth_mii_write(alaska88e1111_ml501_phynum, MII_BMCR, ctl);
 
printk("\nOeth: PHY control reg: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_BMCR));
printk("Oeth: PHY control reg: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_BMSR));
printk("Oeth: PHY id0: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_PHYSID1));
printk("Oeth: PHY id1: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_PHYSID2));
printk("Oeth: PHY adv: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_ADVERTISE));
printk("Oeth: PHY lpa: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_LPA));
printk("Oeth: PHY physpec: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_M1011_PHY_SPEC_CONTROL));
printk("Oeth: PHY expansion: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_EXPANSION ));
printk("Oeth: PHY ctrl1000: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_CTRL1000));
printk("Oeth: PHY stat1000: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_STAT1000));
printk("Oeth: PHY estatus: 0x%.4x\n",eth_mii_read(alaska88e1111_ml501_phynum, MII_ESTATUS));
 
}
 
 
void ethmac_setup(void)
{
// from arch/or32/drivers/open_eth.c
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
/*printk("\nbefore reset\n\n");
oeth_printregs();*/
 
/* Reset MII mode module */
regs->miimoder = OETH_MIIMODER_RST; /* MII Reset ON */
regs->miimoder &= ~OETH_MIIMODER_RST; /* MII Reset OFF */
regs->miimoder = 0x64; /* Clock divider for MII Management interface */
/* Reset the controller.
*/
regs->moder = OETH_MODER_RST; /* Reset ON */
regs->moder &= ~OETH_MODER_RST; /* Reset OFF */
//printk("\nafter reset\n\n");
//oeth_printregs();
/* Setting TXBD base to OETH_TXBD_NUM.
*/
regs->tx_bd_num = OETH_TXBD_NUM;
/* Set min/max packet length
*/
regs->packet_len = 0x00400600;
/* Set IPGT register to recomended value
*/
regs->ipgt = 0x12;
/* Set IPGR1 register to recomended value
*/
regs->ipgr1 = 0x0000000c;
/* Set IPGR2 register to recomended value
*/
regs->ipgr2 = 0x00000012;
/* Set COLLCONF register to recomended value
*/
regs->collconf = 0x000f003f;
/* Set control module mode
*/
#if 0
regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW;
#else
regs->ctrlmoder = 0;
#endif
/* Clear MIIM registers */
regs->miitx_data = 0;
regs->miiaddress = 0;
regs->miicommand = 0;
regs->mac_addr1 = ETH_MACADDR0 << 8 | ETH_MACADDR1;
regs->mac_addr0 = ETH_MACADDR2 << 24 | ETH_MACADDR3 << 16 | ETH_MACADDR4 << 8 | ETH_MACADDR5;
/* Clear all pending interrupts
*/
regs->int_src = 0xffffffff;
/* Promisc, IFG, CRCEn
*/
regs->moder |= OETH_MODER_PRO | OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN | OETH_MODER_FULLD;
/* Enable interrupt sources.
*/
 
regs->int_mask = OETH_INT_MASK_TXB |
OETH_INT_MASK_TXE |
OETH_INT_MASK_RXF |
OETH_INT_MASK_RXE |
OETH_INT_MASK_BUSY |
OETH_INT_MASK_TXC |
OETH_INT_MASK_RXC;
printk("\nafter config\n\n");
oeth_printregs();
 
// Buffer setup stuff
volatile oeth_bd *tx_bd, *rx_bd;
int i,j,k;
/* Initialize TXBD pointer
*/
tx_bd = (volatile oeth_bd *)OETH_BD_BASE;
/* Initialize RXBD pointer
*/
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
/* Preallocated ethernet buffer setup */
unsigned long mem_addr = ETH_BUFF_BASE; /* Defined at top */
 
/* Setup for TX buffers*/
for(i = 0, k = 0; i < OETH_TX_BUFF_PAGE_NUM; i++) {
for(j = 0; j < OETH_TX_BUFF_PPGAE; j++, k++) {
//tx_bd[k].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ;
tx_bd[k].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC;
tx_bd[k].addr = mem_addr;
mem_addr += OETH_TX_BUFF_SIZE;
}
}
tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP;
 
/* Setup for RX buffers */
for(i = 0, k = 0; i < OETH_RX_BUFF_PAGE_NUM; i++) {
for(j = 0; j < OETH_RX_BUFF_PPGAE; j++, k++) {
rx_bd[k].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; /* Enable interrupt */
rx_bd[k].addr = mem_addr;
mem_addr += OETH_RX_BUFF_SIZE;
}
}
rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP; /* Final buffer has wrap bit set */
 
/* Enable receiver and transmiter
*/
regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN;
 
return;
}
 
/* Find the next available transmit buffer */
struct oeth_bd* get_next_tx_bd()
{
int i;
volatile oeth_bd *tx_bd;
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/
/* Go through the TX buffs, search for unused one */
for(i = 0; i < OETH_TXBD_NUM; i++) {
if(!(tx_bd[i].len_status & OETH_TX_BD_READY)) /* Looking for buffer NOT ready for transmit. ie we can manipulate it */
{
printk("Oeth: Using TX_bd at 0x%lx\n",(unsigned long)&tx_bd[i]);
return (struct oeth_bd*) &tx_bd[i];
}
}
 
printk("No free tx buffers\n");
/* Set to null our returned buffer */
tx_bd = (volatile oeth_bd *) 0;
return (struct oeth_bd*) tx_bd;
}
 
 
/* print packet contents */
static void
oeth_print_packet(unsigned long add, int len)
{
int i;
printk("ipacket: add = %lx len = %d\n", add, len);
for(i = 0; i < len; i++) {
if(!(i % 16))
printk("\n");
printk(" %.2x", *(((unsigned char *)add) + i));
}
printk("\n");
}
 
/* Setup buffer descriptors with data */
/* length is in BYTES */
void tx_packet(void* data, int length)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
volatile oeth_bd *tx_bd;
volatile int i;
if((tx_bd = (volatile oeth_bd *) get_next_tx_bd()) == NULL)
{
printk("No more TX buffers available\n");
return;
}
printk("Oeth: TX_bd buffer address: 0x%lx\n",(unsigned long) tx_bd->addr);
/* Clear all of the status flags.
*/
tx_bd->len_status &= ~OETH_TX_BD_STATS;
/* If the frame is short, tell CPM to pad it.
*/
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
if (length <= ETH_ZLEN)
tx_bd->len_status |= OETH_TX_BD_PAD;
else
tx_bd->len_status &= ~OETH_TX_BD_PAD;
printk("Oeth: Copying %d bytes from 0x%lx to TX_bd buffer at 0x%lx\n",length,(unsigned long) data,(unsigned long) tx_bd->addr);
/* Copy the data into the transmit buffer, byte at a time */
char* data_p = (char*) data;
char* data_b = (char*) tx_bd->addr;
for(i=0;i<length;i++)
{
*(data_b+i) = *(data_p+i);
}
printk("Oeth: Data copied to buffer\n");
/* Set the length of the packet's data in the buffer descriptor */
tx_bd->len_status = (tx_bd->len_status & 0x0000ffff) |
((length&0xffff) << 16);
 
//oeth_print_packet(tx_bd->addr, (tx_bd->len_status >> 16));
 
/* Send it on its way. Tell controller its ready, interrupt when sent
* and to put the CRC on the end.
*/
tx_bd->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_CRC | OETH_TX_BD_IRQ);
 
oeth_dump_bds();
 
printk("Oeth: MODER addr: 0x%x\n", regs->moder);
 
printk("Oeth: TXBD Status 0x%x\n", tx_bd->len_status);
i=0;
 
/* Wait for BD READY bit to be cleared, indicating it's been sent */
/* Not if we've got interrupts enabled. */
/*
while (OETH_TX_BD_READY & tx_bd->len_status)
{
#ifndef RTLSIM
//for(i=0;i<40000;i++);
//printk("Oeth: TXBD Status 0x%x\n", tx_bd->len_status);
//oeth_printregs();
spin_cursor();
if (i++%64==63) {oeth_dump_bds();}
#endif
}
*/
 
return;
 
 
}
 
/* enable RX, loop waiting for arrived packets and print them out */
void oeth_monitor_rx(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
/* Set RXEN in MAC MODER */
regs->moder = OETH_MODER_RXEN | regs->moder;
 
volatile oeth_bd *rx_bd;
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
 
volatile int i;
while (1)
{
for(i=0;i<OETH_RXBD_NUM;i++)
{
if (!(rx_bd[i].len_status & OETH_RX_BD_EMPTY)) /* Not empty */
{
// Something in this buffer!
printk("Oeth: RX in buf %d - len_status: 0x%lx\n",i, rx_bd[i].len_status);
oeth_print_packet(rx_bd[i].addr, rx_bd[i].len_status >> 16);
/* Clear recieved bit */
rx_bd[i].len_status |= OETH_RX_BD_EMPTY;
printk("\t end of packet\n\n");
}
}
}
}
 
/* Print out all buffer descriptors */
void oeth_dump_bds()
{
unsigned long* bd_base = (unsigned long*) OETH_BD_BASE;
 
int i;
for(i=0;i<OETH_TXBD_NUM;i++)
{
printk("oeth: tx_bd%d: len_status: %lx ",i,*bd_base++);
printk("addr: %lx\n", *bd_base++);
}
 
for(i=0;i<OETH_RXBD_NUM;i++)
{
printk("oeth: rx_bd%d: len_status: %lx ",i,*bd_base++);
printk("addr: %lx\n", *bd_base++);
}
}
 
 
 
void send_packet()
{
/* This should be 98 bytes big */
char ping_packet[] = {
0x00, 0x24, 0xe8, 0x91, 0x7c, 0x0d, /*DST MAC*/
0x00, 0xe0, 0x18, 0x73, 0x1d, 0x05, /*SRC MAC*/
0x08, 0x00, /*TYPE*/
/* IP */
0x45, /* Version, header length*/
0x00, /* Differentiated services field */
0x00, 0x54, /* Total length */
0x00, 0x00, /* Identification */
0x40, /* Flags */
0x00, /* Fragment offset */
0x40, /* Time to live */
0x01, /* Protocol (0x01 = ICMP */
0xef, 0xf3, /* Header checksum */
0xc0, 0xa8, 0x64, 0xfb, /* Source IP */
0xc0, 0xa8, 0x64, 0x69, /* Dest. IP */
/* ICMP Message body */
0x08, 0x00, 0x9a, 0xd4, 0xc8, 0x18, 0x00, 0x01, 0xd9, 0x8c, 0x54,
0x4a, 0x7b, 0x37, 0x01, 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
};
 
/*Send packet */
tx_packet((void*) ping_packet, 98);
 
}
 
void printstring(char* string)
{
while (*string) uart_putc(*string++);
}
 
 
 
/* The interrupt handler.
*/
void
oeth_interrupt(void)
{
 
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
uint int_events;
int serviced;
serviced = 0;
 
#ifndef RTLSIM
printk(".");
printk("\n=tx_ | %x | %x | %x | %x | %x | %x | %x | %x\n",
((oeth_bd *)(OETH_BD_BASE))->len_status,
((oeth_bd *)(OETH_BD_BASE+8))->len_status,
((oeth_bd *)(OETH_BD_BASE+16))->len_status,
((oeth_bd *)(OETH_BD_BASE+24))->len_status,
((oeth_bd *)(OETH_BD_BASE+32))->len_status,
((oeth_bd *)(OETH_BD_BASE+40))->len_status,
((oeth_bd *)(OETH_BD_BASE+48))->len_status,
((oeth_bd *)(OETH_BD_BASE+56))->len_status);
printk("=rx_ | %x | %x | %x | %x | %x | %x | %x | %x\n",
((oeth_bd *)(OETH_BD_BASE+64))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+8))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+16))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+24))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+32))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+40))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+48))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+56))->len_status);
#endif
/* Get the interrupt events that caused us to be here.
*/
int_events = regs->int_src;
regs->int_src = int_events;
 
/* Handle receive event in its own function.
*/
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) {
serviced |= 0x1;
oeth_rx();
}
 
/* Handle transmit event in its own function.
*/
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) {
serviced |= 0x2;
oeth_tx();
}
 
/* Check for receive busy, i.e. packets coming but no place to
* put them.
*/
if (int_events & OETH_INT_BUSY) {
serviced |= 0x4;
#ifndef RTLSIM
printk("b");
#endif
if (!(int_events & (OETH_INT_RXF | OETH_INT_RXE)))
oeth_rx();
}
 
 
#if 0
if (serviced == 0) {
void die(const char * str, struct pt_regs * regs, long err);
int show_stack(unsigned long *esp);
printk("!");
// printk("unserviced irq\n");
// show_stack(NULL);
// die("unserviced irq\n", regs, 801);
}
#endif
 
if (serviced == 0)
#ifdef RTLSIM
report(0);
#else
printk("\neth interrupt called but nothing serviced\n");
#endif
else /* Something happened ... either RX or TX */
#ifdef RTLSIM
report(0xdeaddead);
#else
printk(" | serviced 0x%x\n", serviced);
#endif
 
return;
}
 
 
 
static void
oeth_rx(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
volatile oeth_bd *rx_bdp;
int pkt_len, i;
int bad = 0;
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
printk("r");
/* Find RX buffers marked as having received data */
for(i = 0; i < OETH_RXBD_NUM; i++)
{
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ /* Looking for NOT empty buffers desc. */
/* Check status for errors.
*/
if (rx_bdp[i].len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) {
bad = 1;
}
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) {
bad = 1;
}
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) {
bad = 1;
}
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) {
bad = 1;
}
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) {
}
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) {
bad = 1;
}
if (bad) {
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS;
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY;
 
continue;
}
else {
/* Process the incoming frame.
*/
pkt_len = rx_bdp[i].len_status >> 16;
/* Do something here with the data - copy it into userspace, perhaps. */
 
#ifdef RTLSIM
report(pkt_len);
#else
oeth_print_packet(rx_bdp[i].addr, rx_bdp[i].len_status >> 16);
printk("\t end of packet\n\n");
#endif
/* finish up */
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; /* Clear stats */
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; /* Mark RX BD as empty */
}
}
}
}
 
 
 
static void
oeth_tx(void)
{
volatile oeth_bd *tx_bd;
int i;
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/
/* Go through the TX buffs, search for one that was just sent */
for(i = 5; i < OETH_TXBD_NUM; i++)
{
/* Looking for buffer NOT ready for transmit. and IRQ enabled */
if( (!(tx_bd[i].len_status & (OETH_TX_BD_READY))) && (tx_bd[i].len_status & (OETH_TX_BD_IRQ)) )
{
/* Single threaded so no chance we have detected a buffer that has had its IRQ bit set but not its BD_READ flag. Maybe this won't work in linux */
tx_bd[i].len_status &= ~OETH_TX_BD_IRQ;
 
/* Probably good to check for TX errors here */
/* set our test variable */
tx_done = 1;
 
printk("T%d",i);
}
}
return;
}
 
 
 
int main ()
{
/* Install interrupt handler */
excpt_int = (unsigned long)int_main;
 
/* Initialise handler vector */
int_init();
 
/* Install ethernet interrupt handler, it is enabled here too */
int_add(IRQ_ETH_0, oeth_interrupt, 0);
 
/* Enable interrupts in supervisor register */
mtspr (SPR_SR, mfspr (SPR_SR) | SPR_SR_IEE);
last_char=0; /* Variable init for spin_cursor() */
 
#ifndef RTLSIM
uart_init(); // init the UART before we can printf
printf("\n\teth interrupts test\n\n");
#endif
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX in MODER */
//scan_ethphys(); /* Scan MIIM bus for PHYs */
#ifndef RTLSIM
ethphy_init(); /* Attempt reset and configuration of PHY via MIIM */
#endif
//ethmac_scanstatus(); /* Enable scanning of status register via MIIM */
 
//oeth_monitor_rx();
#ifdef RTLSIM
/* clear tx_done, the tx interrupt handler will set it when it's been transmitted */
tx_done = 0;
 
send_packet();
 
while(tx_done==0);
 
report(0xdeaddead);
or32_exit(0);
#else
while(1)
spin_cursor();
#endif
 
}
/eth/eth_reset.S
0,0 → 1,110
/* Reset function for ml501 board */
#include "spr_defs.h"
#include "board.h"
 
.section .stack
.space 0x30
_stack:
 
.section .reset, "ax"
 
/* .org 0x100*/
.org 0
_reset_vector:
l.addi r2,r0,0x0
l.addi r3,r0,0x0
l.addi r4,r0,0x0
l.addi r5,r0,0x0
l.addi r6,r0,0x0
l.addi r7,r0,0x0
l.addi r8,r0,0x0
l.addi r9,r0,0x0
l.addi r10,r0,0x0
l.addi r11,r0,0x0
l.addi r12,r0,0x0
l.addi r13,r0,0x0
l.addi r14,r0,0x0
l.addi r15,r0,0x0
l.addi r16,r0,0x0
l.addi r17,r0,0x0
l.addi r18,r0,0x0
l.addi r19,r0,0x0
l.addi r20,r0,0x0
l.addi r21,r0,0x0
l.addi r22,r0,0x0
l.addi r23,r0,0x0
l.addi r24,r0,0x0
l.addi r25,r0,0x0
l.addi r26,r0,0x0
l.addi r27,r0,0x0
l.addi r28,r0,0x0
l.addi r29,r0,0x0
l.addi r30,r0,0x0
l.addi r31,r0,0x0
 
l.movhi r3,hi(_start)
l.ori r3,r3,lo(_start)
l.jr r3
l.nop
 
.org 0x100
/* Jump to 0 .. where the real reset vector is*/
l.jr r0
l.nop
.section .text
 
_start:
 
.if IC | DC
/* Flush IC and/or DC */
l.addi r10,r0,0
l.addi r11,r0,0
l.addi r12,r0,0
.if IC
l.addi r11,r0,IC_SIZE
.endif
.if DC
l.addi r12,r0,DC_SIZE
.endif
l.sfleu r12,r11
l.bf loop
l.nop
l.add r11,r0,r12
loop:
.if IC
l.mtspr r0,r10,SPR_ICBIR
.endif
.if DC
l.mtspr r0,r10,SPR_DCBIR
.endif
l.sfne r10,r11
l.bf loop
l.addi r10,r10,16
 
/* Enable IC and/or DC */
l.addi r10,r0,(SPR_SR_SM)
.if IC
l.ori r10,r10,(SPR_SR_ICE)
.endif
.if DC
l.ori r10,r10,(SPR_SR_DCE)
.endif
l.mtspr r0,r10,SPR_SR
l.nop
l.nop
l.nop
l.nop
l.nop
.endif
 
/* Set stack pointer */
l.movhi r1,hi(_stack)
l.ori r1,r1,lo(_stack)
 
/* Jump to main */
l.movhi r2,hi(_main)
l.ori r2,r2,lo(_main)
l.jr r2
l.nop
 
/eth/mii.h
0,0 → 1,145
/* Generic MII registers. */
 
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_CTRL1000 0x09 /* 1000BASE-T control */
#define MII_STAT1000 0x0a /* 1000BASE-T status */
#define MII_ESTATUS 0x0f /* Extended Status */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
#define MII_SREVISION 0x16 /* Silicon revision */
#define MII_RESV1 0x17 /* Reserved... */
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19 /* PHY address */
#define MII_RESV2 0x1a /* Reserved... */
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
#define MII_NCONFIG 0x1c /* Network interface config */
 
/* Basic mode control register. */
#define BMCR_SPD2 0x0040 /* Gigabit enable? (bcm5411) */
#define BMCR_RESV 0x003f /* Unused... */
#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
#define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
 
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x00c0 /* Unused... */
#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
 
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
#define ADVERTISE_RESV 0x1000 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
 
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
ADVERTISE_CSMA)
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
ADVERTISE_100HALF | ADVERTISE_100FULL)
 
/* Link partner ability register. */
#define LPA_SLCT 0x001f /* Same as advertise selector */
#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
#define LPA_PAUSE_CAP 0x0400 /* Can pause */
#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
#define LPA_RESV 0x1000 /* Unused... */
#define LPA_RFAULT 0x2000 /* Link partner faulted */
#define LPA_LPACK 0x4000 /* Link partner acked us */
#define LPA_NPAGE 0x8000 /* Next page bit */
 
#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
 
/* Expansion register for auto-negotiation. */
#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
#define EXPANSION_RESV 0xffe0 /* Unused... */
 
#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
 
/* N-way test register. */
#define NWAYTEST_RESV1 0x00ff /* Unused... */
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
#define NWAYTEST_RESV2 0xfe00 /* Unused... */
 
/* 1000BASE-T Control register */
#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
 
/* 1000BASE-T Status register */
#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */
#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
#define LPA_1000HALF 0x0400 /* Link partner 1000BASE-T half duplex */
 
/* 1000BT control (Marvell & BCM54xx at least) */
#define MII_1000BASETCONTROL 0x09
#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200
#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100
 
/* Marvell 88E1011 PHY control */
#define MII_M1011_PHY_SPEC_CONTROL 0x10
#define MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX 0x20
#define MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX 0x40
 
/* Marvell 88E1011 PHY status */
#define MII_M1011_PHY_SPEC_STATUS 0x11
#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000
#define MII_M1011_PHY_SPEC_STATUS_100 0x4000
#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000
#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000
#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800
#define MII_M1011_PHY_SPEC_STATUS_TX_PAUSE 0x0008
#define MII_M1011_PHY_SPEC_STATUS_RX_PAUSE 0x0004
/eth/open_eth.h
0,0 → 1,147
 
typedef unsigned int uint;
 
/* Ethernet configuration registers */
typedef struct _oeth_regs {
uint moder; /* Mode Register */
uint int_src; /* Interrupt Source Register */
uint int_mask; /* Interrupt Mask Register */
uint ipgt; /* Back to Bak Inter Packet Gap Register */
uint ipgr1; /* Non Back to Back Inter Packet Gap Register 1 */
uint ipgr2; /* Non Back to Back Inter Packet Gap Register 2 */
uint packet_len; /* Packet Length Register (min. and max.) */
uint collconf; /* Collision and Retry Configuration Register */
uint tx_bd_num; /* Transmit Buffer Descriptor Number Register */
uint ctrlmoder; /* Control Module Mode Register */
uint miimoder; /* MII Mode Register */
uint miicommand; /* MII Command Register */
uint miiaddress; /* MII Address Register */
uint miitx_data; /* MII Transmit Data Register */
uint miirx_data; /* MII Receive Data Register */
uint miistatus; /* MII Status Register */
uint mac_addr0; /* MAC Individual Address Register 0 */
uint mac_addr1; /* MAC Individual Address Register 1 */
uint hash_addr0; /* Hash Register 0 */
uint hash_addr1; /* Hash Register 1 */
} oeth_regs;
 
/* Ethernet buffer descriptor */
typedef struct _oeth_bd {
#if 0
ushort len; /* Buffer length */
ushort status; /* Buffer status */
#else
uint len_status;
#endif
uint addr; /* Buffer address */
} oeth_bd;
 
 
#define OETH_REG_BASE ETH_0_BASE
#define OETH_BD_BASE (ETH_0_BASE + 0x400)
#define OETH_TOTAL_BD 128
#define OETH_MAXBUF_LEN 0x600
/* Tx BD */
#define OETH_TX_BD_READY 0x8000 /* Tx BD Ready */
#define OETH_TX_BD_IRQ 0x4000 /* Tx BD IRQ Enable */
#define OETH_TX_BD_WRAP 0x2000 /* Tx BD Wrap (last BD) */
#define OETH_TX_BD_PAD 0x1000 /* Tx BD Pad Enable */
#define OETH_TX_BD_CRC 0x0800 /* Tx BD CRC Enable */
#define OETH_TX_BD_UNDERRUN 0x0100 /* Tx BD Underrun Status */
#define OETH_TX_BD_RETRY 0x00F0 /* Tx BD Retry Status */
#define OETH_TX_BD_RETLIM 0x0008 /* Tx BD Retransmission Limit Status */
#define OETH_TX_BD_LATECOL 0x0004 /* Tx BD Late Collision Status */
#define OETH_TX_BD_DEFER 0x0002 /* Tx BD Defer Status */
#define OETH_TX_BD_CARRIER 0x0001 /* Tx BD Carrier Sense Lost Status */
#define OETH_TX_BD_STATS (OETH_TX_BD_UNDERRUN | \
OETH_TX_BD_RETRY | \
OETH_TX_BD_RETLIM | \
OETH_TX_BD_LATECOL | \
OETH_TX_BD_DEFER | \
OETH_TX_BD_CARRIER)
/* Rx BD */
#define OETH_RX_BD_EMPTY 0x8000 /* Rx BD Empty */
#define OETH_RX_BD_IRQ 0x4000 /* Rx BD IRQ Enable */
#define OETH_RX_BD_WRAP 0x2000 /* Rx BD Wrap (last BD) */
#define OETH_RX_BD_MISS 0x0080 /* Rx BD Miss Status */
#define OETH_RX_BD_OVERRUN 0x0040 /* Rx BD Overrun Status */
#define OETH_RX_BD_INVSIMB 0x0020 /* Rx BD Invalid Symbol Status */
#define OETH_RX_BD_DRIBBLE 0x0010 /* Rx BD Dribble Nibble Status */
#define OETH_RX_BD_TOOLONG 0x0008 /* Rx BD Too Long Status */
#define OETH_RX_BD_SHORT 0x0004 /* Rx BD Too Short Frame Status */
#define OETH_RX_BD_CRCERR 0x0002 /* Rx BD CRC Error Status */
#define OETH_RX_BD_LATECOL 0x0001 /* Rx BD Late Collision Status */
#define OETH_RX_BD_STATS (OETH_RX_BD_MISS | \
OETH_RX_BD_OVERRUN | \
OETH_RX_BD_INVSIMB | \
OETH_RX_BD_DRIBBLE | \
OETH_RX_BD_TOOLONG | \
OETH_RX_BD_SHORT | \
OETH_RX_BD_CRCERR | \
OETH_RX_BD_LATECOL)
 
/* MODER Register */
#define OETH_MODER_RXEN 0x00000001 /* Receive Enable */
#define OETH_MODER_TXEN 0x00000002 /* Transmit Enable */
#define OETH_MODER_NOPRE 0x00000004 /* No Preamble */
#define OETH_MODER_BRO 0x00000008 /* Reject Broadcast */
#define OETH_MODER_IAM 0x00000010 /* Use Individual Hash */
#define OETH_MODER_PRO 0x00000020 /* Promiscuous (receive all) */
#define OETH_MODER_IFG 0x00000040 /* Min. IFG not required */
#define OETH_MODER_LOOPBCK 0x00000080 /* Loop Back */
#define OETH_MODER_NOBCKOF 0x00000100 /* No Backoff */
#define OETH_MODER_EXDFREN 0x00000200 /* Excess Defer */
#define OETH_MODER_FULLD 0x00000400 /* Full Duplex */
#define OETH_MODER_RST 0x00000800 /* Reset MAC */
#define OETH_MODER_DLYCRCEN 0x00001000 /* Delayed CRC Enable */
#define OETH_MODER_CRCEN 0x00002000 /* CRC Enable */
#define OETH_MODER_HUGEN 0x00004000 /* Huge Enable */
#define OETH_MODER_PAD 0x00008000 /* Pad Enable */
#define OETH_MODER_RECSMALL 0x00010000 /* Receive Small */
/* Interrupt Source Register */
#define OETH_INT_TXB 0x00000001 /* Transmit Buffer IRQ */
#define OETH_INT_TXE 0x00000002 /* Transmit Error IRQ */
#define OETH_INT_RXF 0x00000004 /* Receive Frame IRQ */
#define OETH_INT_RXE 0x00000008 /* Receive Error IRQ */
#define OETH_INT_BUSY 0x00000010 /* Busy IRQ */
#define OETH_INT_TXC 0x00000020 /* Transmit Control Frame IRQ */
#define OETH_INT_RXC 0x00000040 /* Received Control Frame IRQ */
 
/* Interrupt Mask Register */
#define OETH_INT_MASK_TXB 0x00000001 /* Transmit Buffer IRQ Mask */
#define OETH_INT_MASK_TXE 0x00000002 /* Transmit Error IRQ Mask */
#define OETH_INT_MASK_RXF 0x00000004 /* Receive Frame IRQ Mask */
#define OETH_INT_MASK_RXE 0x00000008 /* Receive Error IRQ Mask */
#define OETH_INT_MASK_BUSY 0x00000010 /* Busy IRQ Mask */
#define OETH_INT_MASK_TXC 0x00000020 /* Transmit Control Frame IRQ Mask */
#define OETH_INT_MASK_RXC 0x00000040 /* Received Control Frame IRQ Mask */
/* Control Module Mode Register */
#define OETH_CTRLMODER_PASSALL 0x00000001 /* Pass Control Frames */
#define OETH_CTRLMODER_RXFLOW 0x00000002 /* Receive Control Flow Enable */
#define OETH_CTRLMODER_TXFLOW 0x00000004 /* Transmit Control Flow Enable */
/* MII Mode Register */
#define OETH_MIIMODER_CLKDIV 0x000000FF /* Clock Divider */
#define OETH_MIIMODER_NOPRE 0x00000100 /* No Preamble */
#define OETH_MIIMODER_RST 0x00000200 /* MIIM Reset */
/* MII Command Register */
#define OETH_MIICOMMAND_SCANSTAT 0x00000001 /* Scan Status */
#define OETH_MIICOMMAND_RSTAT 0x00000002 /* Read Status */
#define OETH_MIICOMMAND_WCTRLDATA 0x00000004 /* Write Control Data */
/* MII Address Register */
#define OETH_MIIADDRESS_FIAD 0x0000001F /* PHY Address */
#define OETH_MIIADDRESS_RGAD 0x00001F00 /* RGAD Address */
/* MII Status Register */
#define OETH_MIISTATUS_LINKFAIL 0x00000001 /* Link Fail */
#define OETH_MIISTATUS_BUSY 0x00000002 /* MII Busy */
#define OETH_MIISTATUS_NVALID 0x00000004 /* Data in MII Status Register is invalid */
 
/eth/except.S
0,0 → 1,183
#include "spr_defs.h"
#include "board.h"
 
// Linked from 0x200, so add 0x200 to the .org for the physical address
.section .vectors, "ax"
 
/*
.org 0x100
_reset:
l.nop
l.j _reset_except
l.nop
*/
.org 0x000
_except_200:
l.nop
l.j _buserr_except
l.nop
 
.org 0x100
_except_300:
l.nop
l.j _dpf_except
l.nop
 
.org 0x200
_except_400:
l.nop
l.j _ipf_except
l.nop
 
.org 0x300
_except_500:
l.nop
l.j _lpint_except
l.nop
 
.org 0x400
_except_600:
l.nop
l.j _align_except
l.nop
 
.org 0x500
_except_700:
l.nop
l.j _illegal_except
l.nop
 
.org 0x600
 
_int_vector:
l.nop
l.addi r1,r1,-116
l.sw 0x18(r1),r9
l.jal store_regs
l.nop
 
l.movhi r9,hi(end_except)
l.ori r9,r9,lo(end_except)
l.movhi r10,hi(_excpt_int)
l.ori r10,r10,lo(_excpt_int)
l.lwz r10,0(r10)
l.jr r10
l.nop
 
.org 0x700
_except_900:
l.nop
l.j _dtlbmiss_except
l.nop
 
.org 0x800
_except_a00:
l.nop
l.j _itlbmiss_except
l.nop
 
.org 0x900
_except_b00:
l.nop
l.j _range_except
l.nop
 
.org 0xa00
_except_c00:
l.nop
l.j _syscall_except
l.nop
 
.org 0xb00
_except_d00:
l.nop
l.j _fpu_except
l.nop
 
 
.org 0xc00
_except_e00:
l.nop
l.j _trap_except
l.nop
 
 
store_regs:
l.sw 0x00(r1),r3
l.sw 0x04(r1),r4
l.sw 0x08(r1),r5
l.sw 0x0c(r1),r6
l.sw 0x10(r1),r7
l.sw 0x14(r1),r8
l.sw 0x1c(r1),r10
l.sw 0x20(r1),r11
l.sw 0x24(r1),r12
l.sw 0x28(r1),r13
l.sw 0x2c(r1),r14
l.sw 0x30(r1),r15
l.sw 0x34(r1),r16
l.sw 0x38(r1),r17
l.sw 0x3c(r1),r18
l.sw 0x40(r1),r19
l.sw 0x44(r1),r20
l.sw 0x48(r1),r21
l.sw 0x4c(r1),r22
l.sw 0x50(r1),r23
l.sw 0x54(r1),r24
l.sw 0x58(r1),r25
l.sw 0x5c(r1),r26
l.sw 0x60(r1),r27
l.sw 0x64(r1),r28
l.sw 0x68(r1),r29
l.sw 0x6c(r1),r30
l.sw 0x70(r1),r31
l.jr r9
l.nop
 
end_except:
l.lwz r3,0x00(r1)
l.lwz r4,0x04(r1)
l.lwz r5,0x08(r1)
l.lwz r6,0x0c(r1)
l.lwz r7,0x10(r1)
l.lwz r8,0x14(r1)
l.lwz r9,0x18(r1)
l.lwz r10,0x1c(r1)
l.lwz r11,0x20(r1)
l.lwz r12,0x24(r1)
l.lwz r13,0x28(r1)
l.lwz r14,0x2c(r1)
l.lwz r15,0x30(r1)
l.lwz r16,0x34(r1)
l.lwz r17,0x38(r1)
l.lwz r18,0x3c(r1)
l.lwz r19,0x40(r1)
l.lwz r20,0x44(r1)
l.lwz r21,0x48(r1)
l.lwz r22,0x4c(r1)
l.lwz r23,0x50(r1)
l.lwz r24,0x54(r1)
l.lwz r25,0x58(r1)
l.lwz r26,0x5c(r1)
l.lwz r27,0x60(r1)
l.lwz r28,0x64(r1)
l.lwz r29,0x68(r1)
l.lwz r30,0x6c(r1)
l.lwz r31,0x70(r1)
l.addi r1,r1,116
l.mtspr r0,r9,SPR_EPCR_BASE
l.rfe
l.nop
/eth/Makefile
0,0 → 1,61
PROJECT_ROOT=../../../../..
 
MAIN_SW_DIR=$(PROJECT_ROOT)/sw
 
 
 
 
SUPPORT_SOURCES=uart.c uart.h spr_defs.h support.h int.h time.h support.c syscall.c int.c vfnprintf.c time.c vfnprintf.h
SUPPORT_C_SOURCES=$(shell for src in $(SUPPORT_SOURCES); do echo $$src | grep \.c; done)
 
# Some extra options, if we're going to compile the software for it to be pulled in by the synthesis tool
ifeq ($(SYNTHESIS), 1)
SW_SYNTHESIS_OPTS=-DUART_PRINTF
VMEM_SYNTHESIS_OPTS=-synfmt
else
SW_SYNTHESIS_OPTS=-DRTLSIM
endif
 
 
CROSS_PREFIX=or32-elf-
CROSS_CC=$(CROSS_PREFIX)gcc
CROSS_OBJCOPY=$(CROSS_PREFIX)objcopy
 
APP=eth
 
all: clean
 
.PHONY: $(APP)
$(APP): prepare-sw prepare-links $(APP).vmem
 
 
$(APP).vmem: $(APP).bin
$(MAIN_SW_DIR)/utils/bin2vmem $? $(VMEM_SYNTHESIS_OPTS) > $@
 
$(APP).bin: $(APP).or32
$(CROSS_OBJCOPY) -O binary $? $@
 
$(APP).or32: $(APP)_reset.o $(APP).[cS] $(SUPPORT_C_SOURCES) except.o
$(CROSS_CC) $? -mhard-mul -g -I../. -O2 $(SW_SYNTHESIS_OPTS) -T$(APP).ld -o $@
 
$(APP)_reset.o: $(APP)_reset.S
$(CROSS_CC) -c -o $@ $? -I../.
 
prepare-links:
for src in $(SUPPORT_SOURCES); do if [ ! -e $$src ]; then ln -s $(MAIN_SW_DIR)/support/$$src; fi; done
 
unprepare-links:
for src in $(SUPPORT_SOURCES); do if [ -e $$src ]; then unlink $$src; fi; done
 
prepare-sw:
@$(MAKE) -C $(MAIN_SW_DIR)/utils all
 
%.o: %.S
$(CROSS_CC) -I../. $(SW_SYNTHESIS_OPTS) -O2 -g -c -Wall $< -o $@
 
$(MAIN_SW_DIR)/support/libsupport.a:
$(MAKE) -C $(MAIN_SW_DIR)/support all
 
clean: unprepare-links
@rm -vf *.o *.bin *.or32 *.vmem
 
/eth/eth.ld
0,0 → 1,59
 
MEMORY
{
reset : ORIGIN = 0x00000000, LENGTH = 0x00000200
vectors : ORIGIN = 0x00000200, LENGTH = 0x00001E00
ram : ORIGIN = 0x00002000, LENGTH = 0x0FFFE000
}
 
SECTIONS
{
.reset :
{
*(.reset)
} > reset
 
.vectors :
{
_vec_start = .;
*(.vectors)
_vec_end = .;
} > vectors
 
.text :
{
*(.text)
} > ram
 
.rodata :
{
*(.rodata)
*(.rodata.*)
} > ram
.icm :
{
_icm_start = .;
*(.icm)
_icm_end = .;
} > ram
 
.data :
{
_dst_beg = .;
*(.data)
_dst_end = .;
} > ram
.bss :
{
*(.bss)
} > ram
.stack (NOLOAD) :
{
*(.stack)
_src_addr = .;
} > ram
 
}
/boot/Makefile
1,5 → 1,7
PROJECT_ROOT=../../../../..
 
BOARD=ml501
 
MAIN_SW_DIR=$(PROJECT_ROOT)/sw
 
SUPPORT_SOURCES=uart.c uart.h spr_defs.h support.h
8,9 → 10,15
# Some extra options, if we're going to compile the software for it to be pulled in by the synthesis tool
ifeq ($(SYNTHESIS), 1)
SW_SYNTHESIS_OPTS=-DSYNTHESIS
# Expecting the bootmem to be 0x800 big - if not, change this or it won't get pulled in by synthesis properly!
VMEM_SYNTHESIS_OPTS=-synfmt --pad-to-addr 0x800
# Parse the board defines file in the RTL path for the startup memory span
STARTUP_RAM_SIZE_HEX=$(shell grep -v // ../../rtl/$(BOARD)_defines.v | grep MEMORY_STARTUP_ADDR_SPAN | cut -d 'h' -f 2)
ifeq ($(STARTUP_RAM_SIZE_HEX),)
RAM_PAD_COMMAND=
else
RAM_PAD_COMMAND=--pad-to-addr 0x$(STARTUP_RAM_SIZE_HEX)
endif
VMEM_SYNTHESIS_OPTS=-synfmt $(RAM_PAD_COMMAND)
endif
 
 
CROSS_PREFIX=or32-elf-
/board.h
23,8 → 23,8
 
//#define SPI_BASE 0xa0000000
 
//#define ETH_BASE 0xD0000000
//#define IRQ_ETH_0 (4) /* interrupt source for Ethernet dvice 0 */
#define ETH_0_BASE 0x92000000
#define IRQ_ETH_0 (4) /* interrupt source for Ethernet dvice 0 */
 
#define ETH_DATA_BASE 0xa8000000 /* Address for ETH_DATA */
#define BOARD_DEF_IP 0x0a010185
/memtest/memtest.c
13,10 → 13,13
#define MEM_TEST_BASE 0x2000
#endif
 
#ifdef SYNTHESIS
#define MEM_TEST_LENGTH ((1024*1024*255)/4)
#else
#define MEM_TEST_LENGTH 64
 
#ifndef MEM_TEST_LENGTH
#ifdef SYNTHESIS
#define MEM_TEST_LENGTH (((1024*1024*255)/4) - (MEM_TEST_BASE/4))
#else
#define MEM_TEST_LENGTH 64
#endif
#endif
 
 
/memtest/Makefile
1,5 → 1,5
PROJECT_ROOT=../../../../..
 
BOARD=ml501
MAIN_SW_DIR=$(PROJECT_ROOT)/sw
 
SUPPORT_SOURCES=uart.c uart.h spr_defs.h support.h
11,7 → 11,19
VMEM_SYNTHESIS_OPTS=-synfmt
endif
 
# Setup some user definable paramters such as test start/length
 
# Check the board defines file for the size of the boot/low memory
# test will start after it...
STARTUP_RAM_SIZE_HEX=$(shell grep -v // ../../rtl/$(BOARD)_defines.v | grep MEMORY_STARTUP_ADDR_SPAN | cut -d 'h' -f 2)
ifneq ($(STARTUP_RAM_SIZE_HEX),)
SW_OPTS += -DMEM_TEST_BASE=0x$(STARTUP_RAM_SIZE_HEX)
endif
 
ifneq ($(MEM_TEST_LENGTH),)
SW_OPTS += -DMEM_TEST_LENGTH=$(MEM_TEST_LENGTH)
endif
 
CROSS_PREFIX=or32-elf-
CROSS_CC=$(CROSS_PREFIX)gcc
CROSS_OBJCOPY=$(CROSS_PREFIX)objcopy
21,7 → 33,7
all: clean
 
.PHONY: $(APP)
$(APP): prepare-sw prepare-links $(APP).vmem
$(APP): clean prepare-sw prepare-links $(APP).vmem
 
 
$(APP).vmem: $(APP).bin
31,7 → 43,7
$(CROSS_OBJCOPY) -O binary $? $@
 
$(APP).or32: $(APP)_reset.o $(APP).[cS] $(SUPPORT_C_SOURCES)
$(CROSS_CC) $? -nostdlib -mhard-mul -g -I../. -O2 $(SW_SYNTHESIS_OPTS) -T$(APP).ld -o $@
$(CROSS_CC) $? -nostdlib -mhard-mul -g -I../. -O2 $(SW_OPTS) $(SW_SYNTHESIS_OPTS) -T$(APP).ld -o $@
 
$(APP)_reset.o: $(APP)_reset.S
$(CROSS_CC) -c -o $@ $? -I../.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.