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

Subversion Repositories amber

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /amber/trunk
    from Rev 79 to Rev 80
    Reverse comparison

Rev 79 → Rev 80

/sw/boot-loader-serial/fpga-version.h
1,?rev1len? → ?rev2line?,?rev2len?
#define AMBER_FPGA_VERSION "20130506123001"
#define AMBER_FPGA_VERSION "20130506130110"
/sw/boot-loader-serial/README.txt
1,2 → 1,2
The boot loader must fit in the boot memory, which is 8KBytes.
The boot loader must fit in the boot memory, which is 16KBytes.
Keep an eye on the .mem file to make sure it doesn't get larger than that.
/sw/boot-loader-ethmac/telnet.h
46,4 → 46,6
void parse_telnet_payload (char *, socket_t*);
void telnet_options (socket_t*);
void telnet_tx (socket_t*, line_buf_t*);
void process_telnet (socket_t*);
int parse_command (socket_t*, char*);
 
/sw/boot-loader-ethmac/ethmac.c
51,30 → 51,19
#include "ethmac.h"
 
 
void close_link (void)
/* open a link */
void init_ethmac()
{
/* Disable EthMac interrupts in Ethmac core */
*(unsigned int *) ( ADR_ETHMAC_INT_MASK ) = 0x0;
/* initialize the packet rx buffer */
init_packet();
 
/* Disable Ethmac interrupt in interrupt controller */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
/* open ethernet port and wait for connection requests
keep trying forever */
while (!open_link());
}
 
/* Disable Rx & Tx - MODER Register
[15] = Add pads to short frames
[13] = CRCEN
[10] = Enable full duplex
[7] = loopback
[5] = 1 for promiscuous, 0 rx only frames that match mac address
[1] = txen
[0] = rxen */
*(unsigned int *) ( ADR_ETHMAC_MODER ) = 0xa420;
 
/* Put the PHY into reset */
phy_rst(0); /* reset is active low */
 
}
 
 
/* return 1 if link comes up */
int open_link (void)
{
92,7 → 81,8
d32 = self_g.mac[0]<<8|self_g.mac[1];
*(unsigned int *) ( ADR_ETHMAC_MAC_ADDR1 ) = d32;
 
if (!config_phy()) return 0;
if (!init_phy())
return 0;
 
/* Write the Receive Packet Buffer Descriptor */
/* Buffer Pointer */
141,6 → 131,31
}
 
 
 
void close_link (void)
{
/* Disable EthMac interrupts in Ethmac core */
*(unsigned int *) ( ADR_ETHMAC_INT_MASK ) = 0x0;
 
/* Disable Ethmac interrupt in interrupt controller */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
 
/* Disable Rx & Tx - MODER Register
[15] = Add pads to short frames
[13] = CRCEN
[10] = Enable full duplex
[7] = loopback
[5] = 1 for promiscuous, 0 rx only frames that match mac address
[1] = txen
[0] = rxen */
*(unsigned int *) ( ADR_ETHMAC_MODER ) = 0xa420;
 
/* Put the PHY into reset */
phy_rst(0); /* reset is active low */
 
}
 
 
void tx_packet(int len)
{
unsigned int status = 0;
170,7 → 185,7
 
 
/* returns 1 if link comes up */
int config_phy (void)
int init_phy (void)
{
int addr;
int bmcr;
179,7 → 194,7
int link_up = 1;
time_t* link_timer;
 
link_timer = init_timer();
link_timer = new_timer();
 
/* Bring PHY out of reset */
phy_rst(1); /* reset is active low */
303,7 → 318,6
rx_buf_status = *(volatile unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 );
 
if ((rx_buf_status & 0x8000) == 0) {
 
parse_rx_packet((char*)(ETHMAC_RX_BUFFER+buffer*0x1000), rx_packet_g);
 
/* set empty flag again */
/sw/boot-loader-ethmac/elfsplitter.h
43,11 → 43,11
 
/*
ELF File Structure
A single segment usually consist of several sections. E.g., a loadable
read-only segment could contain sections for executable code, read-only
data, and symbols for the dynamic linker. Relocatable files have section
header tables. Executable files have program header tables. Shared object
files have both. Sections are intended for further processing by a linker,
A single segment usually consist of several sections. E.g., a loadable
read-only segment could contain sections for executable code, read-only
data, and symbols for the dynamic linker. Relocatable files have section
header tables. Executable files have program header tables. Shared object
files have both. Sections are intended for further processing by a linker,
while the segments are intended to be mapped into memory.
*/
 
90,10 → 90,10
} Elf32_Shdr;
 
 
/* Buffer to hold interrupt vector memory values
Can't copy these into mem0 locations until ready to pass control
t new program
*/
/* Buffer to hold interrupt vector memory values
Can't copy these into mem0 locations until ready to pass control
t new program
*/
typedef struct {
char data;
int valid;
109,4 → 109,4
mem_buf_t* elf_mem0_g;
 
/* function prototypes */
int elfsplitter (char*, socket_t*);
int elfsplitter (char*);
/sw/boot-loader-ethmac/led.c
0,0 → 1,116
/*----------------------------------------------------------------
// //
// boot-loader-ethmac.c //
// //
// This file is part of the Amber project //
// http://www.opencores.org/project,amber //
// //
// Description //
// The main functions for the boot loader application. This //
// application is embedded in the FPGA's SRAM and is used //
// to load larger applications into the DDR3 memory on //
// the development board. //
// //
// Author(s): //
// - Conor Santifort, csantifort.amber@gmail.com //
// //
//////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2011 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 "amber_registers.h"
#include "timer.h"
#include "led.h"
 
 
/* global variables */
time_t* led_flash_timer_g;
 
 
void init_led()
{
/* Turn off all LEDs */
led_clear();
 
/* create some timers */
led_flash_timer_g = new_timer();
set_timer(led_flash_timer_g, 500);
}
 
 
void process_led()
{
/* Flash a heartbeat LED */
if (timer_expired(led_flash_timer_g)) {
led_flip(0);
set_timer(led_flash_timer_g, 500);
}
}
 
 
/* turn off all leds */
void led_clear()
{
*(unsigned int *) ADR_AMBER_TEST_LED = 0;
}
 
 
/* led is either 0,1,2 or 3 */
void led_flip(int led)
{
int current_value;
current_value = *(unsigned int *) ADR_AMBER_TEST_LED;
*(unsigned int *) ADR_AMBER_TEST_LED = current_value ^ (1<<led);
}
 
 
 
/* led is either 0,1,2 or 3 */
void led_on(int led)
{
int current_value;
current_value = *(unsigned int *) ADR_AMBER_TEST_LED;
*(unsigned int *) ADR_AMBER_TEST_LED = current_value | (1<<led);
}
 
 
 
/* led is either 0,1,2 or 3 */
void led_off(int led)
{
int current_value;
current_value = *(unsigned int *) ADR_AMBER_TEST_LED;
*(unsigned int *) ADR_AMBER_TEST_LED = current_value & ~(1<<led);
}
 
 
/* led is either 0,1,2 or 3 */
void led_123(int value)
{
int current_value;
current_value = *(unsigned int *) ADR_AMBER_TEST_LED;
*(unsigned int *) ADR_AMBER_TEST_LED = (current_value & 1) | value<<1;
}
/sw/boot-loader-ethmac/boot-loader-ethmac.c
41,307 → 41,70
// //
----------------------------------------------------------------*/
 
#include "amber_registers.h"
#include "address_map.h"
#include "line-buffer.h"
#include "timer.h"
#include "utilities.h"
#include "packet.h"
#include "ethmac.h"
#include "packet.h"
#include "tcp.h"
#include "udp.h"
#include "telnet.h"
#include "serial.h"
 
#include "elfsplitter.h"
#include "boot-loader-ethmac.h"
 
 
 
int main ( void ) {
char* line;
time_t* led_flash_timer;
time_t* reboot_timer;
socket_t* socket = socket0_g;
int reboot_stage = 0;
socket_t* socket;
 
 
/* Enable the serial debug port */
init_serial();
print_serial("Amber debug port\n\r");
 
 
/* Turn off all LEDs */
led_clear();
 
 
/* initialize the memory allocation system */
init_malloc();
 
/* Enable the hardware timer to generate interrrupts 100 timer per second,
current time will start incrementing from this point onwards */
init_timer();
 
/* Initialize current time and some timers */
init_current_time();
led_flash_timer = init_timer();
set_timer(led_flash_timer, 500);
reboot_timer = init_timer();
/* Create a timer to flash a led periodically */
init_led();
 
/* initialize the tftp stuff */
init_tftp();
 
/* receive packet buffer */
rx_packet_g = malloc(sizeof(packet_t));
 
/* create a tcp socket for listening */
first_socket_g = new_socket(NULL);
socket = first_socket_g;
 
/* initialize two tcp sockets */
socket0_g = init_socket(0);
socket1_g = init_socket(1);
/* initialize the PHY and MAC and listen for connections
This is the last init because packets will be received from this point
onwards. */
init_ethmac();
 
 
/* open ethernet port and wait for connection requests
keep trying forever */
while (!open_link());
 
 
/* infinite loop. Everything is timer, interrupt and queue driven from here on down */
/* Process loop. Everything is timer, interrupt and queue driven from here on down */
while (1) {
 
/* Flash a heartbeat LED */
if (timer_expired(led_flash_timer)) {
led_flip(0);
set_timer(led_flash_timer, 500);
}
/* flash an led */
process_led();
 
/* Check for received tftp files and reboot */
process_tftp();
 
/* Check for newly downloaded tftp file. Add to all tx buffers */
/* Has a file been uploaded via tftp ? */
if (udp_file_g != NULL) {
/* Notify telnet clients that file has been received */
if (udp_file_g->ready) {
udp_file_g->ready = 0;
 
print_serial("Received file %s, %d bytes",
udp_file_g->filename, udp_file_g->total_bytes);
if (udp_file_g->linux_boot)
print_serial(", linux image detected\r\n");
else
print_serial("\r\n");
 
if (process_file(socket0_g) == 0) {
/* Disconnect in 1 second */
set_timer(reboot_timer, 1000);
}
else
print_serial("Not an elf file\r\n");
}
}
 
 
/* reboot timer expired */
if (timer_expired(reboot_timer)) {
/* First stage of reboot sequence is to nicely disconnect */
if (reboot_stage == 0) {
set_timer(reboot_timer, 1000);
reboot_stage = 1;
socket0_g->tcp_disconnect = 1;
socket1_g->tcp_disconnect = 1;
}
else {
/* Second stage of reboot sequence is to turn off ethmac and then jump to restart vector */
close_link();
reboot();
}
}
 
 
/* Poll both sockets in turn for activity */
if (socket == socket0_g)
socket = socket1_g;
/* handle tcp connections and process buffers */
/* Poll all sockets in turn for activity */
if (socket->next == NULL)
socket = first_socket_g;
else
socket = socket0_g;
socket = socket->next;
 
 
/* Check if any tcp packets need to be re-transmitted */
tcp_retransmit(socket);
 
 
/* Handle exit command */
if (socket->tcp_disconnect && socket->tcp_connection_state == TCP_OPEN) {
tcp_disconnect(socket);
}
 
 
/* Reset connection */
if (socket->tcp_reset) {
socket->tcp_connection_state = TCP_CLOSED;
socket->telnet_connection_state = TELNET_CLOSED;
socket->telnet_options_sent = 0;
tcp_reply(socket, NULL, 0);
socket->tcp_reset = 0;
}
 
 
/* Send telnet options */
if (socket->tcp_connection_state == TCP_OPEN && !socket->telnet_options_sent){
telnet_options(socket);
socket->telnet_options_sent = 1;
}
 
/* telnet connection open
Communicate with client */
else if (socket->telnet_connection_state == TELNET_OPEN) {
/* Send telnet greeting */
if (!socket->telnet_sent_opening_message){
put_line (socket->telnet_txbuf, "Amber Processor Boot Loader\r\n> ");
socket->telnet_sent_opening_message = 1;
}
 
/* Parse telnet rx buffer */
if (get_line(socket->telnet_rxbuf, &line))
parse_command (socket, line);
 
/* Transmit text from telnet tx buffer */
telnet_tx(socket, socket->telnet_txbuf);
}
process_tcp(socket);
}
}
 
 
 
/* Parse a command line passed from main and execute the command */
/* returns the length of the reply string */
int parse_command (socket_t* socket, char* line)
{
unsigned int start_addr;
unsigned int address;
unsigned int range;
int len, error = 0;
 
/* All commands are just a single character.
Just ignore anything else */
switch (line[0]) {
/* Disconnect */
case 'e':
case 'x':
case 'q':
socket->tcp_disconnect = 1;
return 0;
 
case 'r': /* Read mem */
{
if (len = get_hex (&line[2], &start_addr)) {
if (len = get_hex (&line[3+len], &range)) {
for (address=start_addr; address<start_addr+range; address+=4) {
put_line (socket->telnet_txbuf, "0x%08x 0x%08x\r\n",
address, *(unsigned int *)address);
}
}
else {
put_line (socket->telnet_txbuf, "0x%08x 0x%08x\r\n",
start_addr, *(unsigned int *)start_addr);
}
}
else
error=1;
break;
}
 
 
case 'h': {/* Help */
put_line (socket->telnet_txbuf, "You need help alright\r\n");
break;
}
 
 
case 's': {/* Status */
put_line (socket->telnet_txbuf, "Socket ID %d\r\n", socket->id);
put_line (socket->telnet_txbuf, "Packets received %d\r\n", socket->packets_received);
put_line (socket->telnet_txbuf, "Packets transmitted %d\r\n", socket->packets_sent);
put_line (socket->telnet_txbuf, "Packets resent %d\r\n", socket->packets_resent);
put_line (socket->telnet_txbuf, "TCP checksum errors %d\r\n", tcp_checksum_errors_g);
 
put_line (socket->telnet_txbuf, "Counterparty IP %d.%d.%d.%d\r\n",
socket->rx_packet->src_ip[0],
socket->rx_packet->src_ip[1],
socket->rx_packet->src_ip[2],
socket->rx_packet->src_ip[3]);
 
put_line (socket->telnet_txbuf, "Counterparty Port %d\r\n",
socket->rx_packet->tcp_src_port);
 
put_line (socket->telnet_txbuf, "Malloc pointer 0x%08x\r\n",
*(unsigned int *)(ADR_MALLOC_POINTER));
put_line (socket->telnet_txbuf, "Malloc count %d\r\n",
*(unsigned int *)(ADR_MALLOC_COUNT));
put_line (socket->telnet_txbuf, "Uptime %d seconds\r\n", current_time_g->seconds);
break;
}
 
 
default: {
error=1; break;
}
}
 
 
if (error)
put_line (socket->telnet_txbuf, "You're not making any sense\r\n",
line[0], line[1], line[2]);
 
put_line (socket->telnet_txbuf, "> ");
return 0;
}
 
 
/* copy tftp file into a single contiguous buffer so
if can be processed by elf splitter */
int process_file(socket_t* socket)
{
block_t* block;
char* buf512;
char* tftp_file;
char* line;
int line_len;
int ret;
 
tftp_file = malloc(udp_file_g->total_bytes);
 
block = udp_file_g;
buf512= tftp_file;
 
while (block->next) {
memcpy(buf512, block->buf512, block->bytes);
buf512=&buf512[512];
block=block->next;
}
memcpy(buf512, block->buf512, block->bytes);
buf512=&buf512[512];
 
return elfsplitter(tftp_file, socket);
}
 
 
/* Disable interrupts
Load new values into the interrupt vector memory space
Jump to address 0
*/
void reboot()
{
int i;
 
/* Disable all interrupts */
/* Disable ethmac_int interrupt */
/* Disable timer 0 interrupt in interrupt controller */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x120;
 
for(i=0;i<MEM_BUF_ENTRIES;i++)
if (elf_mem0_g->entry[i].valid)
*(char *)(i) = elf_mem0_g->entry[i].data;
 
if (udp_file_g->linux_boot) {
print_serial("linux reboot\n\r");
_jump_to_program(LINUX_JUMP_ADR);
}
else {
print_serial("normal reboot\n\r");
_restart();
}
}
 
/sw/boot-loader-ethmac/ethmac.h
38,11 → 38,14
// //
----------------------------------------------------------------*/
 
/* Global variables */
extern packet_t* rx_packet_g;
 
/* Function prototypes */
void init_ethmac (void);
int open_link (void);
void close_link (void);
int config_phy (void);
int init_phy (void);
 
void mdio_ready ();
int mdio_read (int addr, int reg);
/sw/boot-loader-ethmac/packet.c
7,7 → 7,7
// //
// Description //
// The main functions for the boot loader application. This //
// application is embedded in the FPGA's SRAM and is used //
// application is embedded in the FPGA's SRAM and is used //
// to load larger applications into the DDR3 memory on //
// the development board. //
// //
56,66 → 56,17
{192, 168, 0, 17} /* IPv4 address */
};
 
 
packet_t* rx_packet_g;
socket_t* socket0_g;
socket_t* socket1_g;
 
 
 
socket_t* init_socket(int socket_id)
void init_packet()
{
socket_t* socket;
socket = (socket_t*) malloc(sizeof(socket_t));
socket->rx_packet =(packet_t*) malloc(sizeof(packet_t));
init_packet_buffers(socket);
socket->telnet_txbuf = init_line_buffer(0x80000);
socket->telnet_rxbuf = init_line_buffer(0x1000);
socket->id = socket_id;
socket->packets_sent = 0;
socket->packets_received = 0;
socket->packets_resent = 0;
socket->telnet_sent_opening_message = 0;
socket->telnet_echo_mode = 0;
socket->telnet_connection_state = TELNET_CLOSED;
socket->telnet_options_sent = 0;
socket->tcp_current_buf = 0;
socket->tcp_reset = 0;
socket->tcp_connection_state = TCP_CLOSED;
socket->tcp_disconnect = 0;
socket->tcp_seq = 0x100; /* should be random initial seq number for tcp */
socket->tcp_last_seq = socket->tcp_seq;
socket->tcp_last_ack = 0;
 
return socket;
/* receive packet buffer */
rx_packet_g = malloc(sizeof(packet_t));
}
 
 
void init_packet_buffers (socket_t* socket)
{
int i;
/* Create space for an array of pointers */
socket->tcp_buf = malloc (TCP_TX_BUFFERS * sizeof (void *));
/* Create space for a set of buffers, each pointed to by an element of the array */
for (i=0;i<TCP_TX_BUFFERS;i=i+1) {
socket->tcp_buf[i] = (packet_buffer_t*) malloc (sizeof (packet_buffer_t));
socket->tcp_buf[i]->payload_valid = 0;
socket->tcp_buf[i]->starting_seq = 0;
socket->tcp_buf[i]->ending_seq = 0;
socket->tcp_buf[i]->len_bytes = 0;
socket->tcp_buf[i]->ack_received = 0;
}
}
 
 
void ethernet_header(char *buf, mac_ip_t* target, unsigned short type)
{
/* ethernet header */
126,7 → 77,7
buf[ 3] = target->mac[3];
buf[ 4] = target->mac[4];
buf[ 5] = target->mac[5];
 
/* SA */
buf[ 6] = self_g.mac[0];
buf[ 7] = self_g.mac[1];
134,7 → 85,7
buf[ 9] = self_g.mac[3];
buf[10] = self_g.mac[4];
buf[11] = self_g.mac[5];
 
/* type */
buf[12] = type>>8;
buf[13] = type&0xff;
147,46 → 98,46
static unsigned short ip_id = 0;
 
/* Version, Header length */
buf[0] = 0x45;
buf[0] = 0x45;
 
/* dscp */
buf[1] = 0;
 
/* ip len */
buf[2] = ip_len>>8;
buf[2] = ip_len>>8;
buf[3] = ip_len&0xff;
 
/* ID */
buf[4] = (ip_id>>8)&0xff;
buf[5] = ip_id&0xff;
buf[5] = ip_id&0xff;
//ip_id++;
 
/* Fragment */
buf[6] = 0;
buf[7] = 0;
 
/* ttl */
buf[8] = 64;
 
/* Protocol */
buf[9] = ip_proto;
 
/* header checksum */
buf[10] = 0;
buf[11] = 0;
 
/* Source IP */
buf[12] = self_g.ip[0];
buf[13] = self_g.ip[1];
buf[14] = self_g.ip[2];
buf[15] = self_g.ip[3];
 
/* Destination IP */
buf[16] = target->ip[0];
buf[17] = target->ip[1];
buf[18] = target->ip[2];
buf[19] = target->ip[3];
 
/* header checksum */
header_checksum = header_checksum16(buf, 20, 0);
buf[10] = (header_checksum>>8)&0xff;
198,7 → 149,7
{
 
ethernet_header(buf, arp_sender, 0x0806);
 
/* Hardware Type */
buf[14] = 0x00;
buf[15] = 0x01;
209,11 → 160,11
buf[18] = 0x06;
/* PLEN */
buf[19] = 0x04;
 
/* Operation = Reply */
buf[20] = 0x00;
buf[21] = 0x02;
 
/* Sender MAC */
buf[22] = self_g.mac[0];
buf[23] = self_g.mac[1];
221,13 → 172,13
buf[25] = self_g.mac[3];
buf[26] = self_g.mac[4];
buf[27] = self_g.mac[5];
 
/* Sender IP */
buf[28] = self_g.ip[0];
buf[29] = self_g.ip[1];
buf[30] = self_g.ip[2];
buf[31] = self_g.ip[3];
 
/* Target MAC */
buf[32] = arp_sender->mac[0];
buf[33] = arp_sender->mac[1];
235,7 → 186,7
buf[35] = arp_sender->mac[3];
buf[36] = arp_sender->mac[4];
buf[37] = arp_sender->mac[5];
 
/* Target IP */
buf[38] = arp_sender->ip[0];
buf[39] = arp_sender->ip[1];
252,7 → 203,7
unsigned short header_checksum;
mac_ip_t target;
char * buf = (char*)ETHMAC_TX_BUFFER;
 
target.mac[0] = rx_packet->src_mac[0];
target.mac[1] = rx_packet->src_mac[1];
target.mac[2] = rx_packet->src_mac[2];
259,7 → 210,7
target.mac[3] = rx_packet->src_mac[3];
target.mac[4] = rx_packet->src_mac[4];
target.mac[5] = rx_packet->src_mac[5];
 
target.ip[0] = rx_packet->src_ip[0];
target.ip[1] = rx_packet->src_ip[1];
target.ip[2] = rx_packet->src_ip[2];
267,22 → 218,22
 
ethernet_header(buf, &target, 0x0800); /*bytes 0 to 13*/
ip_header(&buf[14], &target, rx_packet->ip_len, 1); /* bytes 14 to 33, ip_proto = 1, ICMP*/
 
/* ICMP */
/* Type = reply */
buf[34] = 0;
 
/* Code = 0 */
buf[35] = 0;
 
/* checksum */
buf[36] = 0;
buf[37] = 0;
 
/* ID */
buf[38] = ping_id>>8;
buf[39] = ping_id&0xff;
 
/* SEQ */
buf[40] = ping_seq>>8;
buf[41] = ping_seq&0xff;
301,7 → 252,7
void parse_rx_packet(char * buf, packet_t* rx_packet)
{
int i;
 
rx_packet->dst_mac[0] = buf[0];
rx_packet->dst_mac[1] = buf[1];
rx_packet->dst_mac[1] = buf[2];
314,10 → 265,10
rx_packet->src_mac[2] = buf[8];
rx_packet->src_mac[3] = buf[9];
rx_packet->src_mac[4] = buf[10];
rx_packet->src_mac[5] = buf[11];
rx_packet->src_mac[5] = buf[11];
rx_packet->eth_type = (buf[12]<<8) + buf[13];
 
 
/* ARP */
if (rx_packet->eth_type == 0x0806) {
parse_arp_packet(&buf[14]);
338,7 → 289,7
*/
int arp_op;
mac_ip_t arp_sender, arp_target;
 
arp_op = buf[6]<<8 | buf[7];
 
arp_sender.mac[0] = buf[8];
347,12 → 298,12
arp_sender.mac[3] = buf[11];
arp_sender.mac[4] = buf[12];
arp_sender.mac[5] = buf[13];
 
arp_sender.ip [0] = buf[14];
arp_sender.ip [1] = buf[15];
arp_sender.ip [2] = buf[16];
arp_sender.ip [3] = buf[17];
 
arp_target.mac[0] = buf[18];
arp_target.mac[1] = buf[19];
arp_target.mac[2] = buf[20];
359,19 → 310,19
arp_target.mac[3] = buf[21];
arp_target.mac[4] = buf[22];
arp_target.mac[5] = buf[23];
 
arp_target.ip [0] = buf[24];
arp_target.ip [1] = buf[25];
arp_target.ip [2] = buf[26];
arp_target.ip [3] = buf[27];
 
/* Send a reply ? */
if (arp_op==1 &&
arp_target.ip[0]==self_g.ip[0] &&
arp_target.ip[1]==self_g.ip[1] &&
arp_target.ip[2]==self_g.ip[2] &&
if (arp_op==1 &&
arp_target.ip[0]==self_g.ip[0] &&
arp_target.ip[1]==self_g.ip[1] &&
arp_target.ip[2]==self_g.ip[2] &&
arp_target.ip[3]==self_g.ip[3]) {
 
// ARP reply
arp_reply((char*)ETHMAC_TX_BUFFER, &arp_sender);
}
382,13 → 333,13
void parse_ip_packet(char * buf, packet_t* rx_packet)
{
unsigned int ip_version;
 
ip_version = buf[0]>>4;
if (ip_version != 4) {
//printf("%s: IP version %d not supported\n", __func__, ip_version);
return;
}
 
/* Get destination IP address */
rx_packet->dst_ip[0] = buf[16];
rx_packet->dst_ip[1] = buf[17];
396,13 → 347,13
rx_packet->dst_ip[3] = buf[19];
 
/* If its not my address then ignore the packet */
if (rx_packet->dst_ip[0] != self_g.ip[0] ||
rx_packet->dst_ip[1] != self_g.ip[1] ||
rx_packet->dst_ip[2] != self_g.ip[2] ||
if (rx_packet->dst_ip[0] != self_g.ip[0] ||
rx_packet->dst_ip[1] != self_g.ip[1] ||
rx_packet->dst_ip[2] != self_g.ip[2] ||
rx_packet->dst_ip[3] != self_g.ip[3] ) {
return;
}
 
rx_packet->ip_len = buf[ 2]<<8|buf[ 3];
rx_packet->ip_header_len = buf[0] & 0xf;
rx_packet->ip_proto = buf[9];
411,17 → 362,17
rx_packet->src_ip[2] = buf[14];
rx_packet->src_ip[3] = buf[15];
 
/* Ping packets */
 
/* Ping packets */
if (rx_packet->ip_proto == 1){
parse_ping_packet(&buf[(rx_packet->ip_header_len)*4], rx_packet);
}
 
/* TCP packets */
else if (rx_packet->ip_proto == 6){
parse_tcp_packet(&buf[(rx_packet->ip_header_len)*4], rx_packet);
}
 
/* UDP packets */
else if (rx_packet->ip_proto == 17){
parse_udp_packet(&buf[(rx_packet->ip_header_len)*4], rx_packet);
436,7 → 387,7
 
ping_id = buf[4]<<8|buf[5];
ping_seq = buf[6]<<8|buf[7];
 
ping_reply(rx_packet, ping_id, ping_seq, buf);
}
 
458,7 → 409,7
while (sum>>16) {
sum = (sum & 0xFFFF)+(sum >> 16);
}
 
// build 1's complement:
return( (unsigned short ) sum ^ 0xFFFF);
}
/sw/boot-loader-ethmac/led.h
0,0 → 1,50
/*----------------------------------------------------------------
// //
// boot-loader.h //
// //
// This file is part of the Amber project //
// http://www.opencores.org/project,amber //
// //
// Description //
// Defines for the boot-loader application. //
// //
// Author(s): //
// - Conor Santifort, csantifort.amber@gmail.com //
// //
//////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2010-2013 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 //
// //
----------------------------------------------------------------*/
 
/* Global variables */
extern time_t* led_flash_timer_g;
 
/* Function Prototypes */
void led_clear (void);
void led_flip (int);
void led_on (int);
void led_off (int);
void led_123 (int);
 
/sw/boot-loader-ethmac/utilities.c
7,7 → 7,7
// //
// Description //
// The main functions for the boot loader application. This //
// application is embedded in the FPGA's SRAM and is used //
// application is embedded in the FPGA's SRAM and is used //
// to load larger applications into the DDR3 memory on //
// the development board. //
// //
57,7 → 57,7
{
int pos = 0;
int equal=1;
 
while (*str1!=0 && *str2!=0 && pos<256 && equal) {
equal = *str1==*str2;
str1++;
74,7 → 74,7
int cpos = 0, done = 0;
*num = 0;
 
while (!done) {
while (!done) {
if ( buf[cpos] >= '0' && buf[cpos] <= '9' ) {
*num = *num<<4;
*num = *num + buf[cpos] - '0';
89,16 → 89,16
}
else
done = 1;
 
// Don't increment cops if the first character is not part of an ascii-hex string
// oo that a 0 is returned to indicate failure.
if (!done)
if (!done)
cpos++;
 
if (cpos >= 8)
done = 1;
}
 
/* Return length of acsii-hex string */
return cpos;
}
116,47 → 116,3
*(unsigned int *) ADR_AMBER_TEST_PHY_RST = value;
}
 
 
/* turn off all leds */
void led_clear()
{
*(unsigned int *) ADR_AMBER_TEST_LED = 0;
}
 
 
/* led is either 0,1,2 or 3 */
void led_flip(int led)
{
int current_value;
current_value = *(unsigned int *) ADR_AMBER_TEST_LED;
*(unsigned int *) ADR_AMBER_TEST_LED = current_value ^ (1<<led);
}
 
 
 
/* led is either 0,1,2 or 3 */
void led_on(int led)
{
int current_value;
current_value = *(unsigned int *) ADR_AMBER_TEST_LED;
*(unsigned int *) ADR_AMBER_TEST_LED = current_value | (1<<led);
}
 
 
 
/* led is either 0,1,2 or 3 */
void led_off(int led)
{
int current_value;
current_value = *(unsigned int *) ADR_AMBER_TEST_LED;
*(unsigned int *) ADR_AMBER_TEST_LED = current_value & ~(1<<led);
}
 
 
/* led is either 0,1,2 or 3 */
void led_123(int value)
{
int current_value;
current_value = *(unsigned int *) ADR_AMBER_TEST_LED;
*(unsigned int *) ADR_AMBER_TEST_LED = (current_value & 1) | value<<1;
}
/sw/boot-loader-ethmac/packet.h
134,7 → 134,7
unsigned char src_mac[6];
unsigned char dst_mac[6];
unsigned int eth_type;
 
/* IPv4 */
unsigned char src_ip[4];
unsigned char dst_ip[4];
141,8 → 141,8
unsigned int ip_len; // IP; in bytres
unsigned int ip_header_len; // IP; in 32-bit words
unsigned int ip_proto;
/* TCP */
 
/* TCP */
unsigned int tcp_src_port;
unsigned int tcp_dst_port;
unsigned int tcp_hdr_len;
153,7 → 153,7
unsigned int tcp_len;
unsigned int tcp_payload_len;
unsigned int tcp_src_time_stamp;
 
/* Telnet */
unsigned int telnet_payload_len;
} packet_t;
160,38 → 160,6
 
 
 
typedef struct {
 
packet_buffer_t** tcp_buf;
int tcp_current_buf;
 
/* Telnet rx and tx line buffers */
line_buf_t* telnet_rxbuf;
line_buf_t* telnet_txbuf;
 
int telnet_sent_opening_message;
int telnet_echo_mode;
int telnet_connection_state;
int telnet_options_sent;
int packets_sent;
int packets_received;
int packets_resent;
int tcp_connection_state;
int tcp_reset;
int tcp_disconnect;
int tcp_seq; /* should be random initial seq number for tcp */
int tcp_last_seq;
unsigned int tcp_last_ack;
int id;
packet_t* rx_packet; /* Header info from last packet received */
} socket_t;
 
 
 
/* Enumerated types */
enum mdi_ctrl {
mdi_write = 0x04000000,
209,13 → 177,10
 
/* Global Variables */
extern mac_ip_t self_g;
extern packet_t* rx_packet_g;
extern socket_t* socket0_g;
extern socket_t* socket1_g;
 
 
/* Functions */
void init_packet_buffers (socket_t*);
void init_packet ();
unsigned short header_checksum16 (unsigned char *buf, unsigned short len, unsigned int sum);
 
void arp_reply (char *buf, mac_ip_t*);
229,10 → 194,8
void parse_ip_packet (char*, packet_t*);
void parse_ping_packet (char*, packet_t*);
 
socket_t* init_socket (int);
 
 
 
 
 
 
/sw/boot-loader-ethmac/tftp.c
0,0 → 1,256
/*----------------------------------------------------------------
// //
// boot-loader-ethmac.c //
// //
// This file is part of the Amber project //
// http://www.opencores.org/project,amber //
// //
// Description //
// The main functions for the boot loader application. This //
// application is embedded in the FPGA's SRAM and is used //
// to load larger applications into the DDR3 memory on //
// the development board. //
// //
// Author(s): //
// - Conor Santifort, csantifort.amber@gmail.com //
// //
//////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2011 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 "amber_registers.h"
#include "address_map.h"
#include "line-buffer.h"
#include "timer.h"
#include "utilities.h"
#include "packet.h"
#include "udp.h"
#include "tcp.h"
#include "tftp.h"
#include "elfsplitter.h"
 
 
block_t* udp_file_g = NULL;
block_t* udp_current_block_g = NULL;
time_t* reboot_timer_g;
int reboot_stage_g;
 
 
block_t* init_buffer_512()
{
block_t* block = malloc(sizeof(block_t));
block->buf512 = malloc(512);
block->next = NULL;
block->bytes = 0;
block->last_block = 0;
block->total_bytes = 0;
block->total_blocks = 0;
block->ready = 0;
block->filename = NULL;
block->linux_boot = 0;
return block;
}
 
 
void parse_tftp_packet(char * buf, packet_t* rx_packet, int tftp_len, unsigned int udp_src_port, unsigned int udp_dst_port)
{
int mode_offset;
int binary_mode;
 
unsigned int opcode = buf[8]<<8|buf[9];
unsigned int block = buf[10]<<8|buf[11];
 
mode_offset = next_string(&buf[10]);
binary_mode = strcmp("octet", &buf[10+mode_offset]);
 
switch (opcode) {
 
case UDP_READ:
udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ERROR);
break;
 
case UDP_WRITE:
udp_file_g = init_buffer_512();
udp_file_g->filename = malloc(256);
strcpy(udp_file_g->filename, &buf[10]);
 
if (strncmp(&buf[10], "vmlinux", 7) == 0)
udp_file_g->linux_boot = 1;
 
udp_current_block_g = udp_file_g;
 
if (binary_mode)
udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ACK);
else
udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ERROR);
break;
 
 
case UDP_DATA:
udp_reply(rx_packet, udp_dst_port, udp_src_port, block, UDP_ACK);
 
if (block > udp_file_g->last_block) {
// Have not already received this block
udp_file_g->last_block = block;
 
/* receive and save a block */
udp_current_block_g->bytes = tftp_len;
udp_file_g->total_bytes += tftp_len;
udp_file_g->total_blocks++;
 
memcpy(udp_current_block_g->buf512, &buf[12], tftp_len);
 
/* Prepare the next block */
if (tftp_len == 512) {
udp_current_block_g->next = init_buffer_512();
udp_current_block_g = udp_current_block_g->next;
}
else { /* Last block */
udp_file_g->ready = 1;
}
}
break;
 
 
default: break;
}
}
 
 
 
void init_tftp()
{
reboot_timer_g = new_timer();
reboot_stage_g = 0;
}
 
 
void process_tftp ()
{
socket_t* socket;
 
/* Check for newly downloaded tftp file. Add to all tx buffers */
/* Has a file been uploaded via tftp ? */
if (udp_file_g != NULL) {
/* Notify telnet clients that file has been received */
if (udp_file_g->ready) {
udp_file_g->ready = 0;
 
print_serial("Received file %s, %d bytes",
udp_file_g->filename, udp_file_g->total_bytes);
if (udp_file_g->linux_boot)
print_serial(", linux image detected\r\n");
else
print_serial("\r\n");
 
if (process_file() == 0) {
/* Disconnect in 1 second */
set_timer(reboot_timer_g, 1000);
}
else
print_serial("Not an elf file\r\n");
}
}
 
/* reboot timer expired */
if (timer_expired(reboot_timer_g)) {
/* First stage of reboot sequence is to nicely disconnect */
if (reboot_stage_g == 0) {
set_timer(reboot_timer_g, 1000);
reboot_stage_g = 1;
socket = first_socket_g;
for(;;){
socket->tcp_disconnect = 1;
if (socket->next!=NULL)
socket=socket->next;
else
break;
}
}
else {
/* Second stage of reboot sequence is to turn off ethmac and then jump to restart vector */
close_link();
reboot();
}
}
}
 
 
 
/* copy tftp file into a single contiguous buffer so
if can be processed by elf splitter */
int process_file()
{
block_t* block;
char* buf512;
char* tftp_file;
char* line;
int line_len;
int ret;
 
tftp_file = malloc(udp_file_g->total_bytes);
 
block = udp_file_g;
buf512= tftp_file;
 
while (block->next) {
memcpy(buf512, block->buf512, block->bytes);
buf512=&buf512[512];
block=block->next;
}
memcpy(buf512, block->buf512, block->bytes);
buf512=&buf512[512];
 
return elfsplitter(tftp_file);
}
 
 
/* Disable interrupts
Load new values into the interrupt vector memory space
Jump to address 0
*/
void reboot()
{
int i;
 
/* Disable all interrupts */
/* Disable ethmac_int interrupt */
/* Disable timer 0 interrupt in interrupt controller */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x120;
 
for(i=0;i<MEM_BUF_ENTRIES;i++)
if (elf_mem0_g->entry[i].valid)
*(char *)(i) = elf_mem0_g->entry[i].data;
 
if (udp_file_g->linux_boot) {
print_serial("linux reboot\n\r");
_jump_to_program(LINUX_JUMP_ADR);
}
else {
print_serial("normal reboot\n\r");
_restart();
}
}
/sw/boot-loader-ethmac/timer.c
50,7 → 50,8
time_t* current_time_g;
 
 
time_t* init_timer()
/* Create a timer object */
time_t* new_timer()
{
time_t* timer;
timer= malloc(sizeof(time_t));
65,8 → 66,11
track of the current up time. Timers are
compared against this running value.
*/
void init_current_time()
void init_timer()
{
/* Initialize the current time object */
current_time_g = new_timer();
 
/* Configure timer 0 */
/* Counts down from this value and generates an interrupt every 1/100 seconds */
*(unsigned int *) ( ADR_AMBER_TM_TIMER0_LOAD ) = 1562; // 16-bit, x 256
74,14 → 78,28
 
/* Enable timer 0 interrupt */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x020;
}
 
current_time_g = malloc(sizeof(time_t));
current_time_g->milliseconds = 0;
current_time_g->seconds = 0;
 
/* Set the timer to current time plus a number of milliseconds */
void set_timer (time_t* timer, int milliseconds)
{
int seconds = _div(milliseconds, 1000);
int mseconds = milliseconds - seconds*1000; /* milliseconds % 1000 */
 
if (current_time_g->milliseconds >= (1000 - mseconds)) {
timer->seconds = current_time_g->seconds + 1;
timer->milliseconds = current_time_g->milliseconds + mseconds - 1000;
}
else {
timer->seconds = current_time_g->seconds;
timer->milliseconds = current_time_g->milliseconds + mseconds;
}
 
timer->seconds += seconds;
}
 
 
 
void timer_interrupt()
{
/* Clear timer 0 interrupt in timer */
120,22 → 138,4
}
 
 
/* Set the timer to current time plus 5 seconds */
void set_timer (time_t* timer, int milliseconds)
{
int seconds = _div(milliseconds, 1000);
int mseconds = milliseconds - seconds*1000; /* milliseconds % 1000 */
 
 
if (current_time_g->milliseconds >= (1000 - mseconds)) {
timer->seconds = current_time_g->seconds + 1;
timer->milliseconds = current_time_g->milliseconds + mseconds - 1000;
}
else {
timer->seconds = current_time_g->seconds;
timer->milliseconds = current_time_g->milliseconds + mseconds;
}
 
timer->seconds += seconds;
}
 
/sw/boot-loader-ethmac/utilities.h
39,6 → 39,7
----------------------------------------------------------------*/
#define NULL 0
 
/* function prototypes */
void udelay20 (void);
void * malloc (unsigned int);
int get_hex (char*, unsigned int*);
45,11 → 46,4
int next_string (char*);
int strcmp (char*, char*);
int serial_putchar_ (char *);
 
void led_clear (void);
void led_flip (int);
void led_on (int);
void led_off (int);
void led_123 (int);
 
void phy_rst (int);
/sw/boot-loader-ethmac/tftp.h
0,0 → 1,69
/*----------------------------------------------------------------
// //
// boot-loader.h //
// //
// This file is part of the Amber project //
// http://www.opencores.org/project,amber //
// //
// Description //
// Defines for the boot-loader application. //
// //
// Author(s): //
// - Conor Santifort, csantifort.amber@gmail.com //
// //
//////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2010 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 //
// //
----------------------------------------------------------------*/
#define LINUX_JUMP_ADR 0x00080000
 
 
typedef struct {
char * buf512;
void * next;
unsigned int bytes;
unsigned int last_block;
unsigned int total_bytes;
unsigned int total_blocks;
unsigned int ready;
unsigned int linux_boot;
char* filename;
} block_t;
 
 
/* Global variables */
extern time_t* reboot_timer_g;
extern int reboot_stage_g;
 
/* Function prototypes */
void process_tftp ();
void init_tftp ();
block_t* init_buffer_512 ();
int process_file ();
void reboot ();
void parse_tftp_packet(char*, packet_t*, int, unsigned int, unsigned int);
 
 
 
/sw/boot-loader-ethmac/timer.h
42,14 → 42,15
typedef struct {
volatile unsigned int seconds;
volatile unsigned int milliseconds;
void * expired;
} time_t;
 
 
void init_current_time ();
time_t* init_timer ();
time_t* new_timer ();
void init_timer ();
void timer_interrupt ();
void set_timer (time_t*, int);
int timer_expired (time_t*);
 
/* Global variables */
extern time_t* current_time_g;
extern time_t* current_time_g;
/sw/boot-loader-ethmac/tcp.c
7,7 → 7,7
// //
// Description //
// The main functions for the boot loader application. This //
// application is embedded in the FPGA's SRAM and is used //
// application is embedded in the FPGA's SRAM and is used //
// to load larger applications into the DDR3 memory on //
// the development board. //
// //
54,75 → 54,157
 
/* Global variables */
int tcp_checksum_errors_g = 0;
socket_t* first_socket_g;
socket_t* socket1_g;
 
/* input argument is a pointer to the previous socket,
if this is the first socket object, then it is NULL */
socket_t* new_socket(socket_t* prev)
{
socket_t* socket;
int i;
 
socket = (socket_t*) malloc(sizeof(socket_t));
socket->rx_packet = (packet_t*) malloc(sizeof(packet_t));
 
/* Create space for an array of pointers */
socket->tcp_buf = malloc (TCP_TX_BUFFERS * sizeof (void *));
 
/* Create space for a set of buffers, each pointed to by an element of the array */
for (i=0;i<TCP_TX_BUFFERS;i=i+1) {
socket->tcp_buf[i] = (packet_buffer_t*) malloc (sizeof (packet_buffer_t));
socket->tcp_buf[i]->payload_valid = 0;
socket->tcp_buf[i]->starting_seq = 0;
socket->tcp_buf[i]->ending_seq = 0;
socket->tcp_buf[i]->len_bytes = 0;
socket->tcp_buf[i]->ack_received = 0;
}
 
socket->telnet_txbuf = init_line_buffer(0x80000);
socket->telnet_rxbuf = init_line_buffer(0x1000);
 
socket->packets_sent = 0;
socket->packets_received = 0;
socket->packets_resent = 0;
 
socket->telnet_sent_opening_message = 0;
socket->telnet_echo_mode = 0;
socket->telnet_connection_state = TELNET_CLOSED;
socket->telnet_options_sent = 0;
 
socket->tcp_current_buf = 0;
socket->tcp_reset = 0;
socket->tcp_connection_state = TCP_CLOSED;
socket->tcp_disconnect = 0;
socket->tcp_seq = 0x100; /* should be random initial seq number for tcp */
socket->tcp_last_seq = socket->tcp_seq;
socket->tcp_last_ack = 0;
 
 
/* Chain the socket objects together */
if (prev == NULL){
socket->first = socket;
socket->id = 0;
}
else {
socket->first = prev->first;
socket->id = prev->id + 1;
prev->next = socket;
}
socket->next = NULL;
 
return socket;
}
 
 
/* All received tcp packets with dset ip == me arrive here */
void parse_tcp_packet(char * buf, packet_t* rx_packet)
{
int i;
int ptr;
socket_t* socket;
int found=0;
 
/* TCP Length */
rx_packet->tcp_len = rx_packet->ip_len - rx_packet->ip_header_len*4;
rx_packet->tcp_hdr_len = (buf[12]>>4)*4;
 
// Guard against incorrect tcp_hdr_len value
if (rx_packet->tcp_hdr_len < rx_packet->tcp_len)
rx_packet->tcp_payload_len = rx_packet->tcp_len - rx_packet->tcp_hdr_len;
else
rx_packet->tcp_payload_len = 0;
 
/* Verify the TCP checksum is correct */
if (tcp_checksum(buf, rx_packet, 0)) {
tcp_checksum_errors_g++;
goto error_out;
return;
}
 
 
rx_packet->tcp_src_port = buf[0]<<8|buf[1];
rx_packet->tcp_dst_port = buf[2]<<8|buf[3];
rx_packet->tcp_seq = buf[4]<<24|buf[5]<<16|buf[6]<<8|buf[7];
rx_packet->tcp_ack = buf[8]<<24|buf[9]<<16|buf[10]<<8|buf[11];
rx_packet->tcp_flags = buf[13];
rx_packet->tcp_window_size = buf[14]<<8|buf[15];
rx_packet->tcp_window_size = buf[14]<<8|buf[15];
 
 
/* only interested in telnet packet to dest port xx */
if (rx_packet->tcp_dst_port != 23) {
return;
}
 
if (rx_packet->tcp_hdr_len > 20) {
/* Get the source time stamp */
parse_tcp_options(buf, rx_packet);
parse_tcp_options(buf, rx_packet);
}
 
 
/* --------------------------------------------------
Assign the received packet to a socket
Assign the received packet to a socket
-------------------------------------------------- */
/* seach for an open socket that matches the tcp connection */
socket = first_socket_g;
for(;;){
if (socket->tcp_connection_state != TCP_CLOSED &&
socket->rx_packet->tcp_src_port == rx_packet->tcp_src_port) {
found=1;
break;
}
if (socket->next!=NULL)
socket=socket->next;
else
break;
}
 
/* socket 0 open and matches ? */
if (socket0_g->tcp_connection_state != TCP_CLOSED &&
socket0_g->rx_packet->tcp_src_port == rx_packet->tcp_src_port)
socket = socket0_g;
 
/* socket 1 open and matches ? */
else if (socket1_g->tcp_connection_state != TCP_CLOSED &&
socket1_g->rx_packet->tcp_src_port == rx_packet->tcp_src_port)
socket = socket1_g;
/* Search for an available closed soeckt to reuse */
if (!found){
socket = first_socket_g;
for(;;){
if (socket->tcp_connection_state == TCP_CLOSED) {
found=1;
break;
}
if (socket->next!=NULL)
socket=socket->next;
else
break;
}
}
 
/* no matches. Pick an unused socket */
else if (socket0_g->tcp_connection_state == TCP_CLOSED)
socket = socket0_g;
else if (socket1_g->tcp_connection_state == TCP_CLOSED)
socket = socket1_g;
else
goto error_out;
 
/* All available sockets being used. Add a new one to the end of the chain */
if (!found) {
socket = new_socket(socket);
}
 
 
/* Copy the rx_packet structure into the socket */
memcpy(socket->rx_packet, rx_packet, sizeof(packet_t));
 
tcp_response(buf, socket);
 
error_out:
return;
}
 
 
136,22 → 218,22
switch (buf[ptr]) {
case 0: ptr=rx_packet->tcp_hdr_len; break; // end of options
case 1: ptr++; break;
case 2: ptr = ptr + buf[ptr+1]; break; // max segment size
case 2: ptr = ptr + buf[ptr+1]; break; // max segment size
case 3: ptr = ptr + buf[ptr+1]; break; // Window Scale
case 4: ptr = ptr + buf[ptr+1]; break; // SACK Permitted
case 5: ptr = ptr + buf[ptr+1]; break; // SACK
case 8:
// Time Stamp Option
case 8:
// Time Stamp Option
rx_packet->tcp_src_time_stamp = buf[ptr+2]<<24|buf[ptr+3]<<16|buf[ptr+4]<<8|buf[ptr+5];
ptr = ptr + buf[ptr+1];
ptr = ptr + buf[ptr+1];
break;
 
case 28: // User Timeout Option
ptr = ptr + buf[ptr+1]; break;
ptr = ptr + buf[ptr+1]; break;
 
default:
ptr++; break;
}
ptr++; break;
}
}
}
 
159,56 → 241,56
void tcp_response(char * buf, socket_t* socket)
{
socket->packets_received++;
 
/* Mark the ack in the tcp tx packet buffer so the tx packet does not get resent */
if (socket->rx_packet->tcp_flags & 0x10) // ack flag set ?
if (socket->rx_packet->tcp_flags & 0x10) // ack flag set ?
tcp_ack(socket);
 
 
// Other side requesting to reset a connection ?
if (socket->rx_packet->tcp_flags & 0x04) { // RST
if (socket->rx_packet->tcp_flags & 0x04) { // RST
// Reset the connection
socket->tcp_disconnect = 1;
}
 
// open a connection
else if (socket->tcp_connection_state == TCP_CLOSED) {
if (socket->rx_packet->tcp_flags & 0x02) { // SYN
else if (socket->tcp_connection_state == TCP_CLOSED) {
 
if (socket->rx_packet->tcp_flags & 0x02) { // SYN
// Open connection
tcp_open(socket);
socket->tcp_connection_state = TCP_PENDING;
}
 
/* ACK any FIN received */
else if (socket->rx_packet->tcp_flags & 0x01) // FIN
tcp_reply(socket, NULL, 0);
else if (socket->rx_packet->tcp_flags & 0x01) // FIN
tcp_reply(socket, NULL, 0);
}
 
 
// Sent the first ack packet to establish a connection.
// Have just received the second packet from the server
else if (socket->tcp_connection_state == TCP_PENDING) {
// Have just received the second packet from the server
else if (socket->tcp_connection_state == TCP_PENDING) {
/* Add 1 to the sequence number as a special case to open
the connection */
socket->tcp_seq++;
socket->tcp_connection_state = TCP_OPEN;
socket->tcp_seq++;
socket->tcp_connection_state = TCP_OPEN;
}
 
 
// connection is already open
else {
 
/* contains tcp payload */
if (socket->rx_packet->tcp_payload_len != 0) {
/* Ack the packet only if the payload length is non-zero */
tcp_reply(socket, NULL, 0);
 
/* Process the tcp contents */
if (socket->rx_packet->tcp_dst_port == TELNET_PORT)
/* telnet */
parse_telnet_options(&buf[socket->rx_packet->tcp_hdr_len], socket);
}
}
}
}
 
229,16 → 311,16
 
 
/* Transmit a string of length line_len
Suspend interrupts so this process does not get interrupted */
Suspend interrupts so this process does not get interrupted */
void tcp_tx(socket_t* socket, char* buf, int len)
{
/* Disable ethmac_int interrupt */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
tcp_reply(socket, buf, len);
/* Enable ethmac_int interrupt */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x100;
/* Disable ethmac_int interrupt */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
 
tcp_reply(socket, buf, len);
 
/* Enable ethmac_int interrupt */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x100;
}
 
 
253,10 → 335,10
int ip_length;
char * buf;
 
 
buf = socket->tcp_buf[socket->tcp_current_buf]->buf;
 
 
target.mac[0] = socket->rx_packet->src_mac[0];
target.mac[1] = socket->rx_packet->src_mac[1];
target.mac[2] = socket->rx_packet->src_mac[2];
271,18 → 353,18
 
/* Include 20 bytes of tcp options */
ip_length = 20+20+20; /* 20 bytes ip header, 20 bytes tcp header, 20 bytes tcp options */
 
socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 1;
socket->tcp_buf[socket->tcp_current_buf]->ack_received = 0;
socket->tcp_buf[socket->tcp_current_buf]->starting_seq = tcp_header(&buf[34], socket, 0, TCP_NEW);
socket->tcp_buf[socket->tcp_current_buf]->starting_seq = tcp_header(&buf[34], socket, 0, TCP_NEW);
socket->tcp_buf[socket->tcp_current_buf]->ending_seq = socket->tcp_buf[socket->tcp_current_buf]->starting_seq + 1;
set_timer(&socket->tcp_buf[socket->tcp_current_buf]->resend_time, 500);
 
ip_header(&buf[14], &target, ip_length, 6); /* 20 byes of tcp options, bytes 14 to 33, ip_proto = 6, TCP*/
ethernet_header(buf, &target, 0x0800); /* bytes 0 to 13*/
 
socket->tcp_buf[socket->tcp_current_buf]->len_bytes = 14+ip_length;
 
strncpy((char*)ETHMAC_TX_BUFFER, buf, socket->tcp_buf[socket->tcp_current_buf]->len_bytes);
 
tx_packet(socket->tcp_buf[socket->tcp_current_buf]->len_bytes); // MAC header, IP header, TCP header, TCP options
289,7 → 371,7
socket->packets_sent++;
 
 
/* Pick the next tx buffer to use */
/* Pick the next tx buffer to use */
if (socket->tcp_current_buf == TCP_TX_BUFFERS-1)
socket->tcp_current_buf=0;
else
306,9 → 388,9
int ip_length;
char * buf;
 
 
buf = socket->tcp_buf[socket->tcp_current_buf]->buf;
 
target.mac[0] = socket->rx_packet->src_mac[0];
target.mac[1] = socket->rx_packet->src_mac[1];
target.mac[2] = socket->rx_packet->src_mac[2];
321,7 → 403,7
target.ip[3] = socket->rx_packet->src_ip[3];
 
ip_length = 20+20 + telnet_payload_length;
 
/* Copy the payload into the transmit buffer */
if (telnet_payload_length != 0) {
for (i=14+ip_length-telnet_payload_length, j=0; i<14+ip_length;i++,j++) {
328,14 → 410,14
buf[i] = telnet_payload[j];
}
}
 
if (telnet_payload_length)
socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 1;
else
socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 0;
 
socket->tcp_buf[socket->tcp_current_buf]->ack_received = 0;
socket->tcp_buf[socket->tcp_current_buf]->starting_seq = tcp_header(&buf[34], socket, telnet_payload_length, TCP_NORMAL);
socket->tcp_buf[socket->tcp_current_buf]->starting_seq = tcp_header(&buf[34], socket, telnet_payload_length, TCP_NORMAL);
socket->tcp_buf[socket->tcp_current_buf]->ending_seq = socket->tcp_buf[socket->tcp_current_buf]->starting_seq + telnet_payload_length;
set_timer(&socket->tcp_buf[socket->tcp_current_buf]->resend_time, 500);
 
343,7 → 425,7
ethernet_header(buf, &target, 0x0800); /*bytes 0 to 13*/
 
socket->tcp_buf[socket->tcp_current_buf]->len_bytes = 14+ip_length;
 
strncpy((char*)ETHMAC_TX_BUFFER, buf, socket->tcp_buf[socket->tcp_current_buf]->len_bytes);
 
tx_packet(socket->tcp_buf[socket->tcp_current_buf]->len_bytes); // MAC header, IP header, TCP header, TCP options
350,7 → 432,7
socket->packets_sent++;
 
 
/* Pick the next tx buffer to use */
/* Pick the next tx buffer to use */
if (socket->tcp_current_buf == TCP_TX_BUFFERS-1)
socket->tcp_current_buf=0;
else
366,12 → 448,12
int i, ack_valid;
unsigned int ack = socket->rx_packet->tcp_ack;
unsigned int last_ack = socket->tcp_last_ack;
 
for (i=0;i<TCP_TX_BUFFERS;i=i+1) {
if (socket->tcp_buf[i]->payload_valid) {
 
if (ack > last_ack) {
ack_valid = (socket->tcp_buf[i]->ending_seq > last_ack) &&
ack_valid = (socket->tcp_buf[i]->ending_seq > last_ack) &&
(socket->tcp_buf[i]->ending_seq <= ack);
}
else { /* ack is a little after 0, last_ack is a little before 0 */
381,7 → 463,7
else
ack_valid = 1;
}
 
if (ack_valid) {
socket->tcp_buf[i]->ack_received = 1;
if (socket->tcp_buf[i]->ending_seq == ack) break;
388,34 → 470,34
}
}
}
 
socket->tcp_last_ack = ack;
}
 
 
/* Check if any tcp packets need to be re-transmitted */
void tcp_retransmit(socket_t* socket)
void tcp_retransmit(socket_t* socket)
{
int i;
 
/* Find the packet that matches seq */
for (i=0;i<TCP_TX_BUFFERS;i=i+1) {
if (socket->tcp_buf[i]->payload_valid && !socket->tcp_buf[i]->ack_received) {
if (timer_expired(&socket->tcp_buf[i]->resend_time)) {
 
/* Update the timer to trigger again in another little while */
set_timer(&socket->tcp_buf[i]->resend_time, 500);
 
socket->packets_resent++;
 
/* Disable ethmac_int interrupt */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
 
strncpy((char*)ETHMAC_TX_BUFFER, socket->tcp_buf[i]->buf, socket->tcp_buf[i]->len_bytes);
tx_packet(socket->tcp_buf[i]->len_bytes); // MAC header, IP header, TCP header, TCP options
socket->packets_sent++;
 
 
/* Enable ethmac_int interrupt */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x100;
break;
434,14 → 516,14
char flags = 0;
unsigned short len_tcp;
unsigned int starting_seq;
 
/* Source Port */
buf[0] = socket->rx_packet->tcp_dst_port >>8;
buf[1] = socket->rx_packet->tcp_dst_port &0xff;
buf[0] = socket->rx_packet->tcp_dst_port >>8;
buf[1] = socket->rx_packet->tcp_dst_port &0xff;
 
/* Destination Port */
buf[2] = socket->rx_packet->tcp_src_port >>8;
buf[3] = socket->rx_packet->tcp_src_port &0xff;
buf[2] = socket->rx_packet->tcp_src_port >>8;
buf[3] = socket->rx_packet->tcp_src_port &0xff;
 
/* Sequence Number */
/* Increment the sequence number for the next packet */
448,23 → 530,23
starting_seq = socket->tcp_seq;
socket->tcp_last_seq = socket->tcp_seq;
socket->tcp_seq += payload_length;
 
 
buf[4] = starting_seq>>24;
buf[5] = (starting_seq>>16)&0xff;
buf[6] = (starting_seq>>8)&0xff;
buf[7] = starting_seq&0xff;
 
 
/* Ack Number */
if (options == TCP_NEW)
ack_num = socket->rx_packet->tcp_seq + 1;
else if (socket->rx_packet->tcp_flags & 0x01) // FIN
else if (socket->rx_packet->tcp_flags & 0x01) // FIN
// +1 to the final ack
ack_num = socket->rx_packet->tcp_seq + 1;
else
ack_num = socket->rx_packet->tcp_seq + socket->rx_packet->tcp_payload_len;
 
buf[8] = ack_num>>24;
buf[9] = (ack_num>>16)&0xff;
buf[10] = (ack_num>>8)&0xff;
477,42 → 559,42
else
buf[12] = 0x50; /* upper 4 bits, min is 5 */
 
 
/* Flags */
flags = 0x10; /* ACK */
flags = 0x10; /* ACK */
if (options == TCP_NEW) /* Valid in first reply in new connection only */
flags |= 0x02; /* SYNchronise */
if (socket->tcp_disconnect)
if (socket->tcp_disconnect)
flags |= 0x01; /* FINish */
if (socket->tcp_reset)
if (socket->tcp_reset)
flags |= 0x04; /* Reset */
 
buf[13] = flags;
 
/* Window Size */
buf[14] = socket->rx_packet->tcp_window_size >> 8;
buf[15] = socket->rx_packet->tcp_window_size & 0xff;
 
/* Checksum */
buf[16] = 0;
buf[17] = 0;
 
/* Urgent Pointer */
buf[18] = 0;
buf[19] = 0;
 
 
if (options == TCP_NEW) {
/* OPTION: max seg size */
buf[20] = 0x02;
buf[21] = 0x04;
buf[21] = 0x04;
buf[22] = 0x05;
buf[23] = 0xb4;
 
/* OPTION Sack OK */
buf[24] = 0x04;
buf[25] = 0x02;
 
/* OPTION Time Stamp */
buf[26] = 0x08;
buf[27] = 0x0a;
524,7 → 606,7
buf[33] = (socket->rx_packet->tcp_src_time_stamp>>16)&0xff;
buf[34] = (socket->rx_packet->tcp_src_time_stamp>>8)&0xff;
buf[35] = socket->rx_packet->tcp_src_time_stamp&0xff;
 
/* OPTION: NOP */
buf[36] = 0x01;
 
534,19 → 616,19
buf[39] = 0x06;
}
 
 
/* Length */
if (options == TCP_NEW)
len_tcp = 40+payload_length;
else
len_tcp = 20+payload_length;
 
 
/* header checksum */
header_checksum = tcp_checksum(buf, socket->rx_packet, len_tcp);
header_checksum = tcp_checksum(buf, socket->rx_packet, len_tcp);
buf[16] = (header_checksum>>8)&0xff;
buf[17] = header_checksum&0xff;
 
return starting_seq;
}
 
555,23 → 637,23
{
unsigned short prot_tcp=6;
unsigned short word16;
unsigned long sum;
unsigned long sum;
int i;
 
//initialize sum to zero
sum=0;
if (!len_tcp) len_tcp = rx_packet->tcp_len;
 
 
// add the TCP pseudo header which contains:
// the IP source and destinationn addresses,
for (i=0;i<4;i=i+2){
word16 =((rx_packet->src_ip[i]<<8)&0xFF00)+(rx_packet->src_ip[i+1]&0xFF);
sum=sum+word16;
sum=sum+word16;
}
for (i=0;i<4;i=i+2){
word16 =((rx_packet->dst_ip[i]<<8)&0xFF00)+(rx_packet->dst_ip[i+1]&0xFF);
sum=sum+word16;
sum=sum+word16;
}
// the protocol number and the length of the TCP packet
sum = sum + prot_tcp + len_tcp;
580,3 → 662,31
return header_checksum16(buf, len_tcp, sum);
}
 
 
/* handle tcp connections and process buffers
Poll all sockets in turn for activity */
void process_tcp(socket_t* socket)
{
/* Check if any tcp packets need to be re-transmitted */
tcp_retransmit(socket);
 
/* Handle exit command */
if (socket->tcp_disconnect && socket->tcp_connection_state == TCP_OPEN) {
tcp_disconnect(socket);
}
 
/* Reset connection */
else if (socket->tcp_reset) {
socket->tcp_connection_state = TCP_CLOSED;
socket->telnet_connection_state = TELNET_CLOSED;
socket->telnet_options_sent = 0;
tcp_reply(socket, NULL, 0);
socket->tcp_reset = 0;
}
 
/* handle telnet messages */
else if (socket->tcp_connection_state == TCP_OPEN){
process_telnet(socket);
}
}
 
/sw/boot-loader-ethmac/udp.c
51,8 → 51,6
 
 
int udp_checksum_errors_g = 0;
block_t* udp_file_g = NULL;
block_t* udp_current_block_g = NULL;
 
 
void parse_udp_packet(char * buf, packet_t* rx_packet)
88,66 → 86,9
 
 
/* TFTP */
if (udp_dst_port == 69 && !checksum) {
unsigned int opcode = buf[8]<<8|buf[9];
unsigned int block = buf[10]<<8|buf[11];
int tftp_len = udp_len - 12;
if (udp_dst_port == 69 && !checksum)
parse_tftp_packet(buf, rx_packet, udp_len-12, udp_src_port, udp_dst_port);
 
mode_offset = next_string(&buf[10]);
binary_mode = strcmp("octet", &buf[10+mode_offset]);
 
switch (opcode) {
 
case UDP_READ:
udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ERROR);
break;
 
case UDP_WRITE:
udp_file_g = init_buffer_512();
udp_file_g->filename = malloc(256);
strcpy(udp_file_g->filename, &buf[10]);
 
if (strncmp(&buf[10], "vmlinux", 7) == 0)
udp_file_g->linux_boot = 1;
 
udp_current_block_g = udp_file_g;
 
if (binary_mode)
udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ACK);
else
udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ERROR);
break;
 
 
case UDP_DATA:
udp_reply(rx_packet, udp_dst_port, udp_src_port, block, UDP_ACK);
 
if (block > udp_file_g->last_block) {
// Have not already received this block
udp_file_g->last_block = block;
 
/* receive and save a block */
udp_current_block_g->bytes = tftp_len;
udp_file_g->total_bytes += tftp_len;
udp_file_g->total_blocks++;
 
memcpy(udp_current_block_g->buf512, &buf[12], tftp_len);
 
/* Prepare the next block */
if (tftp_len == 512) {
udp_current_block_g->next = init_buffer_512();
udp_current_block_g = udp_current_block_g->next;
}
else { /* Last block */
udp_file_g->ready = 1;
}
}
break;
 
 
default: break;
}
}
}
 
 
236,19 → 177,3
tx_packet(34+udp_len); // packet length in bytes
}
 
 
block_t* init_buffer_512()
{
block_t* block = malloc(sizeof(block_t));
block->buf512 = malloc(512);
block->next = NULL;
block->bytes = 0;
block->last_block = 0;
block->total_bytes = 0;
block->total_blocks = 0;
block->ready = 0;
block->filename = NULL;
block->linux_boot = 0;
return block;
}
 
/sw/boot-loader-ethmac/tcp.h
53,6 → 53,49
};
 
 
typedef struct {
 
packet_buffer_t** tcp_buf;
int tcp_current_buf;
 
/* Telnet rx and tx line buffers */
line_buf_t* telnet_rxbuf;
line_buf_t* telnet_txbuf;
 
int telnet_sent_opening_message;
int telnet_echo_mode;
int telnet_connection_state;
int telnet_options_sent;
 
int packets_sent;
int packets_received;
int packets_resent;
 
int tcp_connection_state;
int tcp_reset;
int tcp_disconnect;
int tcp_seq; /* should be random initial seq number for tcp */
int tcp_last_seq;
unsigned int tcp_last_ack;
 
int id;
 
packet_t* rx_packet; /* Header info from last packet received */
 
/* pointers to the next socket in the chain and the first socket in the chain */
void* next;
void* first;
} socket_t;
 
 
/* Global Variables */
extern socket_t* first_socket_g;
extern int tcp_checksum_errors_g;
 
 
/* Function prototypes */
socket_t* new_socket (socket_t* prev);
 
unsigned short tcp_checksum (unsigned char *, packet_t*, unsigned short);
unsigned int tcp_header (char *, socket_t*, int, int);
void tcp_reply (socket_t*, char*, int);
64,7 → 107,6
void tcp_tx (socket_t*, char*, int);
void parse_tcp_options (char*, packet_t*);
void parse_tcp_packet (char*, packet_t*);
void process_tcp (socket_t*);
 
extern int tcp_checksum_errors_g;
 
 
/sw/boot-loader-ethmac/telnet.c
41,7 → 41,7
// //
----------------------------------------------------------------*/
 
 
#include "address_map.h"
#include "timer.h"
#include "line-buffer.h"
#include "packet.h"
179,3 → 179,114
}
}
 
 
void process_telnet(socket_t* socket)
{
char* line;
 
if (!socket->telnet_options_sent){
telnet_options(socket);
socket->telnet_options_sent = 1;
}
 
else {
/* Send telnet greeting */
if (!socket->telnet_sent_opening_message){
put_line (socket->telnet_txbuf, "Amber Processor Boot Loader\r\n> ");
socket->telnet_sent_opening_message = 1;
}
 
/* Parse telnet rx buffer */
if (get_line(socket->telnet_rxbuf, &line))
parse_command (socket, line);
 
/* Transmit text from telnet tx buffer */
telnet_tx(socket, socket->telnet_txbuf);
}
}
 
 
 
/* Parse a command line passed from main and execute the command */
/* returns the length of the reply string */
int parse_command (socket_t* socket, char* line)
{
unsigned int start_addr;
unsigned int address;
unsigned int range;
int len, error = 0;
 
/* All commands are just a single character.
Just ignore anything else */
switch (line[0]) {
/* Disconnect */
case 'e':
case 'x':
case 'q':
socket->tcp_disconnect = 1;
return 0;
 
case 'r': /* Read mem */
{
if (len = get_hex (&line[2], &start_addr)) {
if (len = get_hex (&line[3+len], &range)) {
for (address=start_addr; address<start_addr+range; address+=4) {
put_line (socket->telnet_txbuf, "0x%08x 0x%08x\r\n",
address, *(unsigned int *)address);
}
}
else {
put_line (socket->telnet_txbuf, "0x%08x 0x%08x\r\n",
start_addr, *(unsigned int *)start_addr);
}
}
else
error=1;
break;
}
 
 
case 'h': {/* Help */
put_line (socket->telnet_txbuf, "You need help alright\r\n");
break;
}
 
 
case 's': {/* Status */
put_line (socket->telnet_txbuf, "Socket ID %d\r\n", socket->id);
put_line (socket->telnet_txbuf, "Packets received %d\r\n", socket->packets_received);
put_line (socket->telnet_txbuf, "Packets transmitted %d\r\n", socket->packets_sent);
put_line (socket->telnet_txbuf, "Packets resent %d\r\n", socket->packets_resent);
put_line (socket->telnet_txbuf, "TCP checksum errors %d\r\n", tcp_checksum_errors_g);
 
put_line (socket->telnet_txbuf, "Counterparty IP %d.%d.%d.%d\r\n",
socket->rx_packet->src_ip[0],
socket->rx_packet->src_ip[1],
socket->rx_packet->src_ip[2],
socket->rx_packet->src_ip[3]);
 
put_line (socket->telnet_txbuf, "Counterparty Port %d\r\n",
socket->rx_packet->tcp_src_port);
 
put_line (socket->telnet_txbuf, "Malloc pointer 0x%08x\r\n",
*(unsigned int *)(ADR_MALLOC_POINTER));
put_line (socket->telnet_txbuf, "Malloc count %d\r\n",
*(unsigned int *)(ADR_MALLOC_COUNT));
put_line (socket->telnet_txbuf, "Uptime %d seconds\r\n", current_time_g->seconds);
break;
}
 
 
default: {
error=1; break;
}
}
 
 
if (error)
put_line (socket->telnet_txbuf, "You're not making any sense\r\n",
line[0], line[1], line[2]);
 
put_line (socket->telnet_txbuf, "> ");
return 0;
}
/sw/boot-loader-ethmac/Makefile
40,10 → 40,10
# ----------------------------------------------------------------
# Assembly source files
 
SRC = boot-loader-ethmac.c line-buffer.c timer.c print.c elfsplitter.c utilities.c \
serial.c ethmac.c packet.c tcp.c udp.c telnet.c start.S ../mini-libc/memcpy.c
DEP = address_map.h boot-loader-ethmac.h line-buffer.h timer.h utilities.h \
serial.h ethmac.h tcp.h udp.h telnet.h packet.h elfsplitter.h
SRC = boot-loader-ethmac.c line-buffer.c timer.c print.c elfsplitter.c utilities.c led.c \
serial.c ethmac.c packet.c tcp.c udp.c tftp.c telnet.c start.S ../mini-libc/memcpy.c
DEP = address_map.h line-buffer.h timer.h utilities.h led.h \
serial.h ethmac.h tcp.h udp.h telnet.h tftp.h packet.h elfsplitter.h
TGT = boot-loader-ethmac.elf
LDS = sections.lds
 
/sw/boot-loader-ethmac/elfsplitter.c
45,12 → 45,13
#include "line-buffer.h"
#include "timer.h"
#include "packet.h"
#include "tcp.h"
#include "telnet.h"
#include "elfsplitter.h"
 
 
 
int elfsplitter (char* inbuf, socket_t* socket)
int elfsplitter (char* inbuf)
{
unsigned int i, j, k;
ElfHeader* elfHeader;
/sw/boot-loader-ethmac/udp.h
39,26 → 39,11
----------------------------------------------------------------*/
 
 
typedef struct {
char * buf512;
void * next;
unsigned int bytes;
unsigned int last_block;
unsigned int total_bytes;
unsigned int total_blocks;
unsigned int ready;
unsigned int linux_boot;
char* filename;
} block_t;
/* Global variables */
extern int udp_checksum_errors_g;
 
 
 
/* Function prototypes */
void parse_udp_packet (char*, packet_t*);
void udp_reply (packet_t*, int, int, int, int);
block_t* init_buffer_512 ();
 
 
/* Global variables */
extern int udp_checksum_errors_g;
extern block_t* udp_file_g;
extern block_t* udp_current_block_g;
/hw/fpga/flash/README.txt
39,6 → 39,9
M0=on, M1=off
Then press the PROG button just below it to load that bitfile from the SPI flash into the FPGA.
 
To use the Parallel flash
M0=off, M1=off
 
 
Online tutorial for instructions with pictures -
http://www.digilentinc.com/Data/Documents/Tutorials/MCS%20File%20Creation%20with%20Xilinx%20ISE%20Tutorial.pdf

powered by: WebSVN 2.1.0

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