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
- from Rev 67 to Rev 69
- ↔ Reverse comparison
Rev 67 → Rev 69
/bench/ml501_testbench.v
210,8 → 210,11
|
|
// UART |
.uart0_stx_pad_o (uart0_stx_o), |
.uart0_srx_pad_i (uart0_srx_i), |
.uart0_RX(uart0_srx_i), |
.uart0_TX(uart0_stx_o), |
// Duplicates of the UART signals, this time to the USB debug cable |
.uart0_RX_expheader(uart0_srx_i), |
.uart0_TX_expheader(uart0_stx_o), |
|
// JTAG |
.dbg_tdo_pad_o (dbg_tdo_o), |
485,9 → 488,15
`ifdef VCD |
|
`ifdef ML501_MEMORY_DDR2 |
// #81263000; // DDR2 calibration completed |
//#87_572_000; // DDR2 calibration completed |
`endif |
|
`ifdef USE_ETHERNET |
#206_847_000 // TX Frame start in simple eth TX test |
`endif |
|
//#157_173_500 // Or1200 IC enabled, program begins |
|
|
$display("VCD in %s\n", {`TEST_RESULTS_DIR,`TEST_NAME_STRING,".vcd"}); |
$dumpfile({`TEST_RESULTS_DIR,`TEST_NAME_STRING,".vcd"}); |
|
513,7 → 522,12
`define UART_BAUDRATE 115200 |
`include "uart_decoder.v" |
`endif |
|
|
wire ic_en = dut.i_or1k.i_or1200_top.or1200_ic_top.ic_en; |
always @(posedge ic_en) |
$display("Or1200 IC enabled at %t", $time); |
|
endmodule // orpsoc_testbench |
|
// Local Variables: |
/rtl/eth_defines.v
335,3 → 335,6
|
// WISHBONE interface is Revision B3 compliant (uncomment when needed) |
`define ETH_WISHBONE_B3 |
|
// TXBuffer Polling enable |
`define POLL_TXBDS |
/rtl/ml501_mc.v
146,7 → 146,7
/* On-chip startup RAM */ |
ml501_startup ml501_startup0 |
( |
.wb_adr_i(wbs_strtup_adr_i[11:2]), |
.wb_adr_i(wbs_strtup_adr_i), |
.wb_stb_i(wbs_strtup_stb_i), |
.wb_cyc_i(wbs_strtup_cyc_i), |
.wb_we_i(wbs_strtup_we_i), |
158,6 → 158,7
.wb_rst(wb_rst) |
); |
defparam ml501_startup0.mem_span = startup_size; |
defparam ml501_startup0.adr_width = `ML501_MEMORY_STARTUP_ADDR_WIDTH; |
`else // !`ifdef ML501_MEMORY_STARTUP |
assign wbs_strtup_dat_o = 0; |
assign wb_strtup_ack_o = 0; |
/rtl/ml501_ddr2_wb_if.v
8,6 → 8,8
//// To Do: //// |
//// Increase usage of cache BRAM to maximum (currently only //// |
//// 256 bytes out of about 8192) //// |
//// Make this a Wishbone B3 registered feedback burst friendly //// |
//// server. //// |
//// //// |
//// Author(s): //// |
//// - Julius Baxter, julius.baxter@orsoc.se //// |
211,11 → 213,6
always @(posedge wb_clk) |
wb_req_new_r <= wb_req_new; |
|
// Register request address, actually, don't bother, it's useless. |
always @(posedge wb_clk) |
if (wb_req_new) |
wb_req_cache_word_addr <= wb_adr_i[4:2]; |
|
// Register whether it's a hit or not |
// As more lines are added, add them to this check. |
always @(posedge wb_clk) |
265,7 → 262,8
// 1. Enable on first access, if it's not a write |
// 2. Enable if we've just refreshed the cache |
// 3. Enable on ACK'ing for a write |
assign wb_cache_en = (wb_req_new & !wb_we_i) | do_readfrom_finished | |
assign wb_cache_en = (wb_req_new & !wb_we_i) | do_readfrom_finished | |
(wb_req_addr_hit & wb_stb_i & !wb_we_i & !wb_ack_o) | |
(wb_ack_o & wb_we_i); |
|
// Writeback detect logic |
/rtl/ml501_startup.v
38,24 → 38,31
//// //// |
////////////////////////////////////////////////////////////////////// |
|
/* Memory containing memory addresses 0-0x200 */ |
/* Memory containing memory addresses 0x0 up to mem_span */ |
module ml501_startup |
( |
input [11:2] wb_adr_i, |
input wb_stb_i, |
input wb_cyc_i, |
input wb_we_i, |
input [3:0] wb_sel_i, |
input [31:0] wb_dat_i, |
output [31:0] wb_dat_o, |
output wb_ack_o, |
input wb_clk, |
input wb_rst |
); |
( wb_adr_i, wb_stb_i, wb_cyc_i, wb_we_i, wb_sel_i, wb_dat_i, |
wb_dat_o, wb_ack_o, |
wb_clk, wb_rst |
); |
|
/* Make this memory span up to this value */ |
parameter mem_span = 12'h800; |
parameter mem_span_word_address_width = 9;// log2((mem_span/bytes_per_word) |
parameter adr_width = 11; // log2(mem_span) |
parameter mem_span_word_address_width = (adr_width-2); |
|
input [adr_width-1:0] wb_adr_i; |
input wb_stb_i; |
input wb_cyc_i; |
input wb_we_i; |
input [3:0] wb_sel_i; |
input [31:0] wb_dat_i; |
output [31:0] wb_dat_o; |
output wb_ack_o; |
input wb_clk; |
input wb_rst; |
|
|
|
// synthesis attribute ram_style of mem is block |
reg [31:0] mem [0:(mem_span/4)-1] /* synthesis ram_style = no_rw_check */; |
reg [mem_span_word_address_width-1:0] adr; |
/rtl/ml501_defines.v
20,7 → 20,7
// |
// Main memory options (select only of the following): |
// |
// On-Chip Xilinx RAMBs (~64KByte, resource used depending) |
// On-Chip Xilinx RAMBs (~64KByte, resource use depending) |
// ZBT SSRAM (1MByte, 200Mhz) |
// DDR2 SDRAM (256MByte, 266Mhz) |
// It is recommended the startup memory is used with only the ZBT SSRAM or DDR2 |
32,8 → 32,16
// Use on-chip memory as a boot-ROM |
`define ML501_MEMORY_STARTUP |
`ifdef ML501_MEMORY_STARTUP |
// Define the size of the onchip memory |
`define ML501_MEMORY_STARTUP_ADDR_SPAN 12'h800 |
// Define the size of the onchip low/startup memory |
// 4KByte |
//`define ML501_MEMORY_STARTUP_ADDR_SPAN 16'h1000 |
//`define ML501_MEMORY_STARTUP_ADDR_WIDTH 12 |
// 8KByte |
//`define ML501_MEMORY_STARTUP_ADDR_SPAN 16'h2000 |
//`define ML501_MEMORY_STARTUP_ADDR_WIDTH 13 |
// 32KByte |
`define ML501_MEMORY_STARTUP_ADDR_SPAN 16'h8000 |
`define ML501_MEMORY_STARTUP_ADDR_WIDTH 15 |
`endif |
|
// Main memory configuration |
/rtl/ml501.v
113,8 → 113,11
output dbg_tdo_pad_o, |
|
// Uart |
input uart0_srx_pad_i, |
output uart0_stx_pad_o, |
input uart0_RX, |
output uart0_TX, |
// Duplicates of the UART signals, this time to the USB debug cable |
input uart0_RX_expheader, |
output uart0_TX_expheader, |
|
// GPIO |
inout [25:0] gpio |
744,6 → 747,13
|
assign wbs_mc_m_err_o = 1'b0; |
|
// Wires for duplication |
wire uart_rx, uart_tx; |
assign uart_rx = uart0_RX & uart0_RX_expheader; |
|
assign uart0_TX = uart_tx; |
assign uart0_TX_expheader = uart_tx; |
|
uart_top |
#( 32, 5) |
i_uart_0_top |
759,8 → 769,8
.wb_clk_i (wb_clk), |
.wb_rst_i (wb_rst), |
.int_o (uart0_irq), |
.srx_pad_i (uart0_srx_pad_i), |
.stx_pad_o (uart0_stx_pad_o), |
.srx_pad_i (uart_rx), |
.stx_pad_o (uart_tx), |
.cts_pad_i (1'b0), |
.rts_pad_o ( ), |
.dtr_pad_o ( ), |
769,6 → 779,8
.ri_pad_i (1'b0) |
); |
|
|
|
`ifdef USE_ETHERNET |
|
wire phy_smi_data_i, phy_smi_data_o, phy_smi_data_dir; |
/par/ml501_xst.ucf
83,17 → 83,15
# OpenCores JTAG Debug signals and User UART on EXP Header pins |
#------------------------------------------------------------------------------ |
|
#NET uart0_srx_pad_i LOC = K20; # HDR1_12 |
NET uart0_srx_pad_i LOC = F25; # HDR2_2 |
NET uart0_srx_pad_i TIG; |
NET uart0_srx_pad_i PULLUP; |
NET uart0_srx_pad_i IOSTANDARD = LVCMOS25; |
NET uart0_RX_expheader LOC = F25; # HDR2_2 |
NET uart0_RX_expheader TIG; |
NET uart0_RX_expheader PULLUP; |
NET uart0_RX_expheader IOSTANDARD = LVCMOS25; |
|
#NET uart0_stx_pad_o LOC = M22; # HDR1_10 |
NET uart0_stx_pad_o LOC = F24; # HDR2_4 |
NET uart0_stx_pad_o TIG; |
NET uart0_stx_pad_o PULLUP; |
NET uart0_stx_pad_o IOSTANDARD = LVCMOS25; |
NET uart0_TX_expheader LOC = F24; # HDR2_4 |
NET uart0_TX_expheader TIG; |
NET uart0_TX_expheader PULLUP; |
NET uart0_TX_expheader IOSTANDARD = LVCMOS25; |
|
NET dbg_tdo_pad_o LOC = E26; # HDR2_6 |
NET dbg_tdi_pad_i LOC = E25; # HDR2_8 |
677,7 → 675,9
# 300MHz = 850ps, 267MHz = 900ps. At 200MHz = 950ps. |
# In general PAR should be able to route this |
# within 900ps over all speed grades. |
NET "*/u_phy_io/en_dqs*" MAXDELAY = 900 ps; |
#NET "*/u_phy_io/en_dqs*" MAXDELAY = 900 ps; |
# JB: Every single one failed with < 2ns slack!! Try upping this... |
NET "*/u_phy_io/en_dqs*" MAXDELAY = 3000 ps; |
NET "*/u_phy_io/gen_dqs*.u_iob_dqs/en_dqs_sync" MAXDELAY = 850 ps; |
|
############################################################################### |
711,7 → 711,9
# time = 0.4*Tcyc + 0.40ns = 1.6ns @333MHz |
INST "*/gen_dqs[*].u_iob_dqs/u_iddr_dq_ce" TNM = "TNM_DQ_CE_IDDR"; |
INST "*/gen_dq[*].u_iob_dq/gen_stg2_*.u_iddr_dq" TNM = "TNM_DQS_FLOPS"; |
TIMESPEC "TS_DQ_CE" = FROM "TNM_DQ_CE_IDDR" TO "TNM_DQS_FLOPS" 2.4 ns; |
#TIMESPEC "TS_DQ_CE" = FROM "TNM_DQ_CE_IDDR" TO "TNM_DQS_FLOPS" 2.4 ns; |
# JB: Was very closely failing on some paths, so up it by 100ps, but note it as an issue! |
TIMESPEC "TS_DQ_CE" = FROM "TNM_DQ_CE_IDDR" TO "TNM_DQS_FLOPS" 2.5 ns; |
|
|
## #------------------------------------------------------------------------------ |
718,13 → 720,20
## # IO Pad Location Constraints / Properties for UART |
## #------------------------------------------------------------------------------ |
|
## NET uart_RX LOC = AC7; |
## NET uart_RX IOSTANDARD = LVCMOS33; |
## NET uart_RX TIG; |
## NET uart_TX LOC = AD14; |
## NET uart_TX IOSTANDARD = LVCMOS33; |
## NET uart_TX TIG; |
#NET uart_RX LOC = AC7; |
#NET uart_RX IOSTANDARD = LVCMOS33; |
#NET uart_RX TIG; |
#NET uart_TX LOC = AD14; |
#NET uart_TX IOSTANDARD = LVCMOS33; |
#NET uart_TX TIG; |
|
NET uart0_RX LOC = AC7; |
NET uart0_RX IOSTANDARD = LVCMOS33; |
NET uart0_RX TIG; |
NET uart0_TX LOC = AD14; |
NET uart0_TX IOSTANDARD = LVCMOS33; |
NET uart0_TX TIG; |
|
## #------------------------------------------------------------------------------ |
## # IO Pad Location Constraints / Properties for SRAM |
## #------------------------------------------------------------------------------ |
895,8 → 904,10
|
## # Timing Constraints (these are recommended in documentation and |
## # are unaltered except for the TIG) |
NET "phy_rx_clk" TNM_NET = "RXCLK_GRP"; |
NET "phy_tx_clk" TNM_NET = "TXCLK_GRP"; |
#NET "phy_rx_clk" TNM_NET = "RXCLK_GRP"; |
NET "phy_rx_clk_BUFGP" TNM_NET = "RXCLK_GRP"; |
#NET "phy_tx_clk" TNM_NET = "TXCLK_GRP"; |
NET "phy_tx_clk_BUFGP" TNM_NET = "TXCLK_GRP"; |
TIMESPEC "TSTXOUT" = FROM "TXCLK_GRP" TO "PADS" 10 ns; |
TIMESPEC "TSRXIN" = FROM "PADS" TO "RXCLK_GRP" 6 ns; |
|
/sim/bin/Makefile
92,7 → 92,7
|
# A new set of tests for software which will run only on this board |
|
BOARD_TESTS=boot |
BOARD_TESTS=boot memtest eth gpio |
|
rtl-board-tests: $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE) prepare-sw prepare-rtl prepare-dirs |
@echo |
/sw/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 |
|
} |
/sw/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 |
|
/sw/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 |
/sw/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 */ |
|
/sw/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 |
|
/sw/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 |
|
/sw/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 |
|
} |
/sw/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- |
/sw/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 |
/sw/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 |
|
|
/sw/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../. |
/syn/Makefile
14,7 → 14,7
MODULES=or1200r2 or1k_startup or1k_top tap debug_if wb_conbus uart16550 ram_wb ethernet |
|
# A list of parts of names of files to be excluded from the automatic file list generation |
EXCLUDE=or1200_dpram or1200_fpu |
EXCLUDE=or1200_dpram or1200_fpu eth_defines |
|
# When cleaning - files not to delete |
FILES_TO_KEEP=$(BOARD).xcf $(BOARD)_xst.tpl ml501_ddr2_wb_if_cache.ngc timescale.v Makefile |