merged fixes from 0.8.6.1 (errornous skip of FPGA load)

This commit is contained in:
Markus Fröschle
2014-12-26 09:36:45 +00:00
parent c549e9b1e6
commit 4d409f4242
6 changed files with 1177 additions and 1165 deletions

View File

@@ -10,254 +10,256 @@
/* make bas_rom access flags rx if compiling to RAM */ /* make bas_rom access flags rx if compiling to RAM */
#ifdef COMPILE_RAM #ifdef COMPILE_RAM
#define ROMFLAGS WX #define ROMFLAGS WX
#else #else
#define ROMFLAGS RX #define ROMFLAGS RX
#endif /* COMPILE_RAM */ #endif /* COMPILE_RAM */
MEMORY MEMORY
{ {
bas_rom (ROMFLAGS) : ORIGIN = TARGET_ADDRESS, LENGTH = 0x00100000 bas_rom (ROMFLAGS) : ORIGIN = TARGET_ADDRESS, LENGTH = 0x00100000
/* /*
* target to copy BaS data segment to. 1M should be enough for now * target to copy BaS data segment to. 1M should be enough for now
*/ */
bas_ram (WX) : ORIGIN = SDRAM_START + SDRAM_SIZE - 0x00200000, LENGTH = 0x00100000 bas_ram (WX) : ORIGIN = SDRAM_START + SDRAM_SIZE - 0x00200000, LENGTH = 0x00100000
/* /*
* driver_ram is an uncached, reserved memory area for drivers (e.g. USB) that need this type of memory * driver_ram is an uncached, reserved memory area for drivers (e.g. USB) that need this type of memory
*/ */
driver_ram (WX) : ORIGIN = SDRAM_START + SDRAM_SIZE - 0x00100000, LENGTH = 0x00100000 driver_ram (WX) : ORIGIN = SDRAM_START + SDRAM_SIZE - 0x00100000, LENGTH = 0x00100000
} }
SECTIONS SECTIONS
{ {
/* BaS in ROM */ /* BaS in ROM */
.text : .text :
{ {
OBJDIR/startcf.o(.text) /* this one is the entry point so it must be the first */ OBJDIR/startcf.o(.text) /* this one is the entry point so it must be the first */
OBJDIR/sysinit.o(.text) OBJDIR/sysinit.o(.text)
OBJDIR/fault_vectors.o(.text) OBJDIR/fault_vectors.o(.text)
#ifdef MACHINE_FIREBEE #ifdef MACHINE_FIREBEE
OBJDIR/init_fpga.o(.text) OBJDIR/init_fpga.o(.text)
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
OBJDIR/wait.o(.text) OBJDIR/wait.o(.text)
OBJDIR/exceptions.o(.text) OBJDIR/exceptions.o(.text)
OBJDIR/driver_vec.o(.text) OBJDIR/driver_vec.o(.text)
OBJDIR/interrupts.o(.text) OBJDIR/interrupts.o(.text)
OBJDIR/mmu.o(.text) OBJDIR/mmu.o(.text)
OBJDIR/BaS.o(.text) OBJDIR/BaS.o(.text)
OBJDIR/pci.o(.text) OBJDIR/pci.o(.text)
OBJDIR/pci_wrappers.o(.text) OBJDIR/pci_wrappers.o(.text)
OBJDIR/usb.o(.text) OBJDIR/usb.o(.text)
OBJDIR/driver_mem.o(.text) OBJDIR/driver_mem.o(.text)
OBJDIR/usb_hub.o(.text) OBJDIR/usb_hub.o(.text)
OBJDIR/usb_mouse.o(.text) OBJDIR/usb_mouse.o(.text)
OBJDIR/usb_kbd.o(.text) OBJDIR/usb_kbd.o(.text)
OBJDIR/ohci-hcd.o(.text) OBJDIR/ohci-hcd.o(.text)
OBJDIR/ehci-hcd.o(.text) OBJDIR/ehci-hcd.o(.text)
OBJDIR/wait.o(.text) OBJDIR/wait.o(.text)
OBJDIR/nbuf.o(.text) OBJDIR/nbuf.o(.text)
OBJDIR/net_timer.o(.text) OBJDIR/net_timer.o(.text)
OBJDIR/queue.o(.text) OBJDIR/queue.o(.text)
OBJDIR/nif.o(.text) OBJDIR/nif.o(.text)
OBJDIR/fecbd.o(.text) OBJDIR/fecbd.o(.text)
OBJDIR/fec.o(.text) OBJDIR/fec.o(.text)
OBJDIR/am79c874.o(.text) OBJDIR/am79c874.o(.text)
OBJDIR/bcm5222.o(.text) OBJDIR/bcm5222.o(.text)
OBJDIR/ip.o(.text) OBJDIR/ip.o(.text)
OBJDIR/udp.o(text) OBJDIR/udp.o(text)
OBJDIR/bootp.o(text) OBJDIR/bootp.o(text)
OBJDIR/tftp.o(text) OBJDIR/tftp.o(text)
OBJDIR/arp.o(text) OBJDIR/arp.o(text)
OBJDIR/unicode.o(.text) OBJDIR/unicode.o(.text)
OBJDIR/mmc.o(.text) OBJDIR/mmc.o(.text)
OBJDIR/ff.o(.text) OBJDIR/ff.o(.text)
OBJDIR/sd_card.o(.text) OBJDIR/sd_card.o(.text)
OBJDIR/s19reader.o(.text) OBJDIR/s19reader.o(.text)
OBJDIR/bas_printf.o(.text) OBJDIR/bas_printf.o(.text)
OBJDIR/bas_string.o(.text) OBJDIR/bas_string.o(.text)
OBJDIR/printf_helper.o(.text) OBJDIR/printf_helper.o(.text)
OBJDIR/cache.o(.text) OBJDIR/cache.o(.text)
OBJDIR/dma.o(.text) OBJDIR/dma.o(.text)
OBJDIR/MCD_dmaApi.o(.text) OBJDIR/MCD_dmaApi.o(.text)
OBJDIR/MCD_tasks.o(.text) OBJDIR/MCD_tasks.o(.text)
OBJDIR/MCD_tasksInit.o(.text) OBJDIR/MCD_tasksInit.o(.text)
OBJDIR/video.o(.text) OBJDIR/video.o(.text)
OBJDIR/videl.o(.text) OBJDIR/videl.o(.text)
OBJDIR/fbmem.o(.text) OBJDIR/fbmem.o(.text)
OBJDIR/fbmon.o(.text) OBJDIR/fbmon.o(.text)
OBJDIR/fbmodedb.o(.text) OBJDIR/fbmodedb.o(.text)
OBJDIR/offscreen.o(.text) OBJDIR/offscreen.o(.text)
OBJDIR/x86decode.o(.text) OBJDIR/x86decode.o(.text)
OBJDIR/x86ops.o(.text) OBJDIR/x86ops.o(.text)
OBJDIR/x86ops2.o(.text) OBJDIR/x86ops2.o(.text)
OBJDIR/x86fpu.o(.text) OBJDIR/x86fpu.o(.text)
OBJDIR/x86sys.o(.text) OBJDIR/x86sys.o(.text)
OBJDIR/x86biosemu.o(.text) OBJDIR/x86biosemu.o(.text)
OBJDIR/x86debug.o(.text) OBJDIR/x86debug.o(.text)
OBJDIR/x86prim_ops.o(.text) OBJDIR/x86prim_ops.o(.text)
OBJDIR/x86pcibios.o(.text) OBJDIR/x86pcibios.o(.text)
OBJDIR/radeon_base.o(.text) OBJDIR/radeon_base.o(.text)
OBJDIR/radeon_accel.o(.text) OBJDIR/radeon_accel.o(.text)
OBJDIR/radeon_cursor.o(.text) OBJDIR/radeon_cursor.o(.text)
OBJDIR/radeon_monitor.o(.text) OBJDIR/radeon_monitor.o(.text)
OBJDIR/xhdi_sd.o(.text) OBJDIR/xhdi_sd.o(.text)
OBJDIR/xhdi_interface.o(.text) OBJDIR/xhdi_interface.o(.text)
OBJDIR/xhdi_vec.o(.text) OBJDIR/xhdi_vec.o(.text)
#ifdef COMPILE_RAM #ifdef COMPILE_RAM
/* /*
* if we compile to RAM anyway, there is no need to copy anything * if we compile to RAM anyway, there is no need to copy anything
*/ */
. = ALIGN(4); . = ALIGN(4);
__BAS_DATA_START = .; __BAS_DATA_START = .;
*(.data) *(.data)
__BAS_DATA_END = .; __BAS_DATA_END = .;
__BAS_BSS_START = .; __BAS_BSS_START = .;
*(.bss) *(.bss)
__BAS_BSS_END = .; __BAS_BSS_END = .;
#endif /* COMPILE_RAM */ #endif /* COMPILE_RAM */
#if (FORMAT_ELF == 1) #if (FORMAT_ELF == 1)
*(.rodata) *(.rodata)
*(.rodata.*) *(.rodata.*)
#endif #endif
} > bas_rom } > bas_rom
#if (TARGET_ADDRESS == BOOTFLASH_BASE_ADDRESS) #if (TARGET_ADDRESS == BOOTFLASH_BASE_ADDRESS)
/* /*
* put BaS .data and .bss segments to flash, but relocate it to RAM after initialize_hardware() ran * put BaS .data and .bss segments to flash, but relocate it to RAM after initialize_hardware() ran
*/ */
.bas : .bas :
AT (ALIGN(ADDR(.text) + SIZEOF(.text), 4)) AT (ALIGN(ADDR(.text) + SIZEOF(.text), 4))
{ {
. = ALIGN(4); /* same alignment than AT() statement! */ . = ALIGN(4); /* same alignment than AT() statement! */
__BAS_DATA_START = .; __BAS_DATA_START = .;
*(.data) *(.data)
__BAS_DATA_END = .; __BAS_DATA_END = .;
__BAS_BSS_START = .; __BAS_BSS_START = .;
*(.bss) *(.bss)
__BAS_BSS_END = .; __BAS_BSS_END = .;
. = ALIGN(16); . = ALIGN(16);
} > bas_ram } > bas_ram
#endif #endif
.driver_memory : .driver_memory :
{ {
. = ALIGN(4); . = ALIGN(4);
_driver_mem_buffer = .; _driver_mem_buffer = .;
//. = . + DRIVER_MEM_BUFFER_SIZE; //. = . + DRIVER_MEM_BUFFER_SIZE;
} > driver_ram } > driver_ram
/* /*
* Global memory map * Global memory map
*/ */
/* SDRAM Initialization */ /* SDRAM Initialization */
___SDRAM = SDRAM_START; ___SDRAM = SDRAM_START;
___SDRAM_SIZE = SDRAM_SIZE; ___SDRAM_SIZE = SDRAM_SIZE;
_SDRAM_VECTOR_TABLE = ___SDRAM; _SDRAM_VECTOR_TABLE = ___SDRAM;
/* ST-RAM */ /* ST-RAM */
__STRAM = ___SDRAM; __STRAM = ___SDRAM;
__STRAM_END = __TOS; __STRAM_END = __TOS;
/* TOS */ /* TOS */
__TOS = 0x00e00000; __TOS = 0x00e00000;
/* FastRAM */ /* FastRAM */
__FASTRAM = 0x10000000; __FASTRAM = 0x10000000;
__TARGET_ADDRESS = TARGET_ADDRESS; __TARGET_ADDRESS = TARGET_ADDRESS;
#if TARGET_ADDRESS == BOOTFLASH_BASE_ADDRESS #if TARGET_ADDRESS == BOOTFLASH_BASE_ADDRESS
__FASTRAM_END = __BAS_IN_RAM; __FASTRAM_END = __BAS_IN_RAM;
#else #else
__FASTRAM_END = TARGET_ADDRESS; __FASTRAM_END = TARGET_ADDRESS;
#endif #endif
__FASTRAM_SIZE = __FASTRAM_END - __FASTRAM; __FASTRAM_SIZE = __FASTRAM_END - __FASTRAM;
/* Init CS0 (BootFLASH @ E000_0000 - E07F_FFFF 8Mbytes) */ /* Init CS0 (BootFLASH @ E000_0000 - E07F_FFFF 8Mbytes) */
___BOOT_FLASH = BOOTFLASH_BASE_ADDRESS; ___BOOT_FLASH = BOOTFLASH_BASE_ADDRESS;
___BOOT_FLASH_SIZE = BOOTFLASH_SIZE; ___BOOT_FLASH_SIZE = BOOTFLASH_SIZE;
#if TARGET_ADDRESS == BOOTFLASH_BASE_ADDRESS #if TARGET_ADDRESS == BOOTFLASH_BASE_ADDRESS
/* BaS */ /* BaS */
__BAS_LMA = LOADADDR(.bas); __BAS_LMA = LOADADDR(.bas);
__BAS_IN_RAM = ADDR(.bas); __BAS_IN_RAM = ADDR(.bas);
__BAS_SIZE = SIZEOF(.bas); __BAS_SIZE = SIZEOF(.bas);
#else #else
/* BaS is already in RAM - no need to copy anything */ /* BaS is already in RAM - no need to copy anything */
__BAS_IN_RAM = __FASTRAM_END; __BAS_IN_RAM = __FASTRAM_END;
__BAS_SIZE = 0; __BAS_SIZE = 0;
__BAS_LMA = __BAS_IN_RAM; __BAS_LMA = __BAS_IN_RAM;
#endif #endif
/* Other flash components */ /* Other flash components */
__FIRETOS = 0xe0400000; __FIRETOS = 0xe0400000;
__EMUTOS = EMUTOS_BASE_ADDRESS; __EMUTOS = EMUTOS_BASE_ADDRESS;
__EMUTOS_SIZE = 0x00100000; __EMUTOS_SIZE = 0x00100000;
/* where FPGA data lives in flash */ /* where FPGA data lives in flash */
__FPGA_CONFIG = 0xe0700000; __FPGA_CONFIG = 0xe0700000;
__FPGA_CONFIG_SIZE = 0x100000; __FPGA_CONFIG_SIZE = 0x100000;
/* VIDEO RAM BASIS */ /* VIDEO RAM BASIS */
__VRAM = 0x60000000; __VRAM = 0x60000000;
/* Memory mapped registers */ /* Memory mapped registers */
__MBAR = 0xFF000000; __MBAR = 0xFF000000;
/* 32KB on-chip System SRAM */ /* 32KB on-chip System SRAM */
__SYS_SRAM = __MBAR + 0x10000; __SYS_SRAM = __MBAR + 0x10000;
__SYS_SRAM_SIZE = 0x00008000; __SYS_SRAM_SIZE = 0x00008000;
/* MMU memory mapped registers */ /* MMU memory mapped registers */
__MMUBAR = 0xFF040000; __MMUBAR = 0xFF040000;
/* /*
* 4KB on-chip Core SRAM0: -> exception table * 4KB on-chip Core SRAM0: -> exception table
*/ */
__RAMBAR0 = 0xFF100000; __RAMBAR0 = 0xFF100000;
__RAMBAR0_SIZE = 0x00001000; __RAMBAR0_SIZE = 0x00001000;
/* 4KB on-chip Core SRAM1 */ /* 4KB on-chip Core SRAM1 */
__RAMBAR1 = 0xFF101000; __RAMBAR1 = 0xFF101000;
__RAMBAR1_SIZE = 0x00001000; __RAMBAR1_SIZE = 0x00001000;
__SUP_SP = __RAMBAR1 + __RAMBAR1_SIZE - 4; __SUP_SP = __RAMBAR1 + __RAMBAR1_SIZE - 4;
/* /*
* this flag (if 1) indicates that FPGA configuration has been loaded through JTAG * this flag (if 1) indicates that FPGA configuration has been loaded through JTAG
* and shouldn't be overwritten on boot * and shouldn't be overwritten on boot
*/ */
__FPGA_JTAG_LOADED = __RAMBAR1; __FPGA_JTAG_LOADED = __RAMBAR1;
__FPGA_JTAG_VALID = __RAMBAR1 + 4; __FPGA_JTAG_VALID = __RAMBAR1 + 4;
/* system variables */ /* system variables */
/* RAMBAR0 0 to 0x7FF -> exception vectors */ /* system variables */
_rt_mod = __RAMBAR0 + 0x800;
_rt_ssp = __RAMBAR0 + 0x804; /* RAMBAR0 0 to 0x7FF -> exception vectors */
_rt_usp = __RAMBAR0 + 0x808; _rt_mod = __RAMBAR0 + 0x800;
_rt_vbr = __RAMBAR0 + 0x80C; /* (8)01 */ _rt_ssp = __RAMBAR0 + 0x804;
_rt_cacr = __RAMBAR0 + 0x810; /* 002 */ _rt_usp = __RAMBAR0 + 0x808;
_rt_asid = __RAMBAR0 + 0x814; /* 003 */ _rt_vbr = __RAMBAR0 + 0x80C; /* (8)01 */
_rt_acr0 = __RAMBAR0 + 0x818; /* 004 */ _rt_cacr = __RAMBAR0 + 0x810; /* 002 */
_rt_acr1 = __RAMBAR0 + 0x81c; /* 005 */ _rt_asid = __RAMBAR0 + 0x814; /* 003 */
_rt_acr2 = __RAMBAR0 + 0x820; /* 006 */ _rt_acr0 = __RAMBAR0 + 0x818; /* 004 */
_rt_acr3 = __RAMBAR0 + 0x824; /* 007 */ _rt_acr1 = __RAMBAR0 + 0x81c; /* 005 */
_rt_mmubar = __RAMBAR0 + 0x828; /* 008 */ _rt_acr2 = __RAMBAR0 + 0x820; /* 006 */
_rt_sr = __RAMBAR0 + 0x82c; _rt_acr3 = __RAMBAR0 + 0x824; /* 007 */
_d0_save = __RAMBAR0 + 0x830; _rt_mmubar = __RAMBAR0 + 0x828; /* 008 */
_a7_save = __RAMBAR0 + 0x834; _rt_sr = __RAMBAR0 + 0x82c;
_video_tlb = __RAMBAR0 + 0x838; _d0_save = __RAMBAR0 + 0x830;
_video_sbt = __RAMBAR0 + 0x83C; _a7_save = __RAMBAR0 + 0x834;
_rt_mbar = __RAMBAR0 + 0x844; /* (c)0f */ _video_tlb = __RAMBAR0 + 0x838;
_video_sbt = __RAMBAR0 + 0x83C;
_rt_mbar = __RAMBAR0 + 0x844; /* (c)0f */
} }

View File

@@ -11,7 +11,7 @@
#include "bas_printf.h" #include "bas_printf.h"
#include <stddef.h> #include <stddef.h>
#define DBG_FECBD //#define DBG_FECBD
#ifdef DBG_FECBD #ifdef DBG_FECBD
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0)
#else #else
@@ -62,94 +62,94 @@ static int iRxbd;
*/ */
void fecbd_init(uint8_t ch) void fecbd_init(uint8_t ch)
{ {
NBUF *nbuf; NBUF *nbuf;
int i; int i;
dbg("\r\n"); dbg("\r\n");
/* /*
* Align Buffer Descriptors to 4-byte boundary * Align Buffer Descriptors to 4-byte boundary
*/ */
RxBD = (FECBD *)(((int) unaligned_bds + 3) & 0xFFFFFFFC); RxBD = (FECBD *)(((int) unaligned_bds + 3) & 0xFFFFFFFC);
TxBD = (FECBD *)((int) RxBD + (sizeof(FECBD) * 2 * NRXBD)); TxBD = (FECBD *)((int) RxBD + (sizeof(FECBD) * 2 * NRXBD));
dbg("initialise RX buffer descriptor ring\r\n"); dbg("initialise RX buffer descriptor ring\r\n");
/* /*
* Initialize the Rx Buffer Descriptor ring * Initialize the Rx Buffer Descriptor ring
*/ */
for (i = 0; i < NRXBD; ++i) for (i = 0; i < NRXBD; ++i)
{ {
/* Grab a network buffer from the free list */ /* Grab a network buffer from the free list */
nbuf = nbuf_alloc(); nbuf = nbuf_alloc();
if (nbuf == NULL) if (nbuf == NULL)
{ {
dbg("could not allocate network buffer\r\n"); dbg("could not allocate network buffer\r\n");
return; return;
} }
/* Initialize the BD */ /* Initialize the BD */
RxBD(ch,i).status = RX_BD_E | RX_BD_INTERRUPT; RxBD(ch,i).status = RX_BD_E | RX_BD_INTERRUPT;
RxBD(ch,i).length = RX_BUF_SZ; RxBD(ch,i).length = RX_BUF_SZ;
RxBD(ch,i).data = nbuf->data; RxBD(ch,i).data = nbuf->data;
/* Add the network buffer to the Rx queue */ /* Add the network buffer to the Rx queue */
nbuf_add(NBUF_RX_RING, nbuf); nbuf_add(NBUF_RX_RING, nbuf);
} }
/* /*
* Set the WRAP bit on the last one * Set the WRAP bit on the last one
*/ */
RxBD(ch, i - 1).status |= RX_BD_W; RxBD(ch, i - 1).status |= RX_BD_W;
dbg("initialise TX buffer descriptor ring\r\n"); dbg("initialise TX buffer descriptor ring\r\n");
/* /*
* Initialize the Tx Buffer Descriptor ring * Initialize the Tx Buffer Descriptor ring
*/ */
for (i = 0; i < NTXBD; ++i) for (i = 0; i < NTXBD; ++i)
{ {
TxBD(ch, i).status = TX_BD_INTERRUPT; TxBD(ch, i).status = TX_BD_INTERRUPT;
TxBD(ch, i).length = 0; TxBD(ch, i).length = 0;
TxBD(ch, i).data = NULL; TxBD(ch, i).data = NULL;
} }
/* /*
* Set the WRAP bit on the last one * Set the WRAP bit on the last one
*/ */
TxBD(ch, i - 1).status |= TX_BD_W; TxBD(ch, i - 1).status |= TX_BD_W;
/* /*
* Initialize the buffer descriptor indexes * Initialize the buffer descriptor indexes
*/ */
iTxbd_new = iTxbd_old = iRxbd = 0; iTxbd_new = iTxbd_old = iRxbd = 0;
} }
void fecbd_dump(uint8_t ch) void fecbd_dump(uint8_t ch)
{ {
#ifdef DBG_FECBD #ifdef DBG_FECBD
int i; int i;
xprintf("\n------------ FEC%d BDs -----------\n",ch); xprintf("\n------------ FEC%d BDs -----------\n",ch);
xprintf("RxBD Ring\n"); xprintf("RxBD Ring\n");
for (i = 0; i < NRXBD; i++) for (i = 0; i < NRXBD; i++)
{ {
xprintf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n", xprintf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n",
i, &RxBD(ch, i), i, &RxBD(ch, i),
RxBD(ch, i).status, RxBD(ch, i).status,
RxBD(ch, i).length, RxBD(ch, i).length,
RxBD(ch, i).data); RxBD(ch, i).data);
} }
xprintf("TxBD Ring\n"); xprintf("TxBD Ring\n");
for (i = 0; i < NTXBD; i++) for (i = 0; i < NTXBD; i++)
{ {
xprintf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n", xprintf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n",
i, &TxBD(ch, i), i, &TxBD(ch, i),
TxBD(ch, i).status, TxBD(ch, i).status,
TxBD(ch, i).length, TxBD(ch, i).length,
TxBD(ch, i).data); TxBD(ch, i).data);
} }
xprintf("--------------------------------\n\n"); xprintf("--------------------------------\n\n");
#endif /* DBG_FECBD */ #endif /* DBG_FECBD */
} }
@@ -165,28 +165,28 @@ void fecbd_dump(uint8_t ch)
*/ */
uint32_t fecbd_get_start(uint8_t ch, uint8_t direction) uint32_t fecbd_get_start(uint8_t ch, uint8_t direction)
{ {
switch (direction) switch (direction)
{ {
case Rx: case Rx:
return (uint32_t)((int)RxBD + (ch * sizeof(FECBD) * NRXBD)); return (uint32_t)((int)RxBD + (ch * sizeof(FECBD) * NRXBD));
case Tx: case Tx:
default: default:
return (uint32_t)((int)TxBD + (ch * sizeof(FECBD) * NTXBD)); return (uint32_t)((int)TxBD + (ch * sizeof(FECBD) * NTXBD));
} }
} }
FECBD *fecbd_rx_alloc(uint8_t ch) FECBD *fecbd_rx_alloc(uint8_t ch)
{ {
int i = iRxbd; int i = iRxbd;
/* Check to see if the ring of BDs is full */ /* Check to see if the ring of BDs is full */
if (RxBD(ch, i).status & RX_BD_E) if (RxBD(ch, i).status & RX_BD_E)
return NULL; return NULL;
/* Increment the circular index */ /* Increment the circular index */
iRxbd = (uint8_t)((iRxbd + 1) % NRXBD); iRxbd = (uint8_t)((iRxbd + 1) % NRXBD);
return &RxBD(ch, i); return &RxBD(ch, i);
} }
/* /*
@@ -201,16 +201,16 @@ FECBD *fecbd_rx_alloc(uint8_t ch)
*/ */
FECBD *fecbd_tx_alloc(uint8_t ch) FECBD *fecbd_tx_alloc(uint8_t ch)
{ {
int i = iTxbd_new; int i = iTxbd_new;
/* Check to see if the ring of BDs is full */ /* Check to see if the ring of BDs is full */
if (TxBD(ch, i).status & TX_BD_R) if (TxBD(ch, i).status & TX_BD_R)
return NULL; return NULL;
/* Increment the circular index */ /* Increment the circular index */
iTxbd_new = (uint8_t)((iTxbd_new + 1) % NTXBD); iTxbd_new = (uint8_t)((iTxbd_new + 1) % NTXBD);
return &TxBD(ch, i); return &TxBD(ch, i);
} }
/* /*
@@ -226,14 +226,14 @@ FECBD *fecbd_tx_alloc(uint8_t ch)
*/ */
FECBD *fecbd_tx_free(uint8_t ch) FECBD *fecbd_tx_free(uint8_t ch)
{ {
int i = iTxbd_old; int i = iTxbd_old;
/* Check to see if the ring of BDs is empty */ /* Check to see if the ring of BDs is empty */
if ((TxBD(ch, i).data == NULL) || (TxBD(ch, i).status & TX_BD_R)) if ((TxBD(ch, i).data == NULL) || (TxBD(ch, i).status & TX_BD_R))
return NULL; return NULL;
/* Increment the circular index */ /* Increment the circular index */
iTxbd_old = (uint8_t)((iTxbd_old + 1) % NTXBD); iTxbd_old = (uint8_t)((iTxbd_old + 1) % NTXBD);
return &TxBD(ch, i); return &TxBD(ch, i);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* File: ip.c * File: ip.c
* Purpose: Internet Protcol device driver * Purpose: Internet Protcol device driver
* *
* Notes: * Notes:
@@ -12,7 +12,7 @@
#include "bas_string.h" #include "bas_string.h"
#define IP_DEBUG //#define IP_DEBUG
#if defined(IP_DEBUG) #if defined(IP_DEBUG)
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
@@ -21,300 +21,297 @@
void ip_init(IP_INFO *info, IP_ADDR_P myip, IP_ADDR_P gateway, IP_ADDR_P netmask) void ip_init(IP_INFO *info, IP_ADDR_P myip, IP_ADDR_P gateway, IP_ADDR_P netmask)
{ {
int index; int index;
for (index = 0; index < sizeof(IP_ADDR); index++) for (index = 0; index < sizeof(IP_ADDR); index++)
{ {
info->myip[index] = myip[index]; info->myip[index] = myip[index];
info->gateway[index] = gateway[index]; info->gateway[index] = gateway[index];
info->netmask[index] = netmask[index]; info->netmask[index] = netmask[index];
info->broadcast[index] = 0xFF; info->broadcast[index] = 0xFF;
} }
info->rx = 0; info->rx = 0;
info->rx_unsup = 0; info->rx_unsup = 0;
info->tx = 0; info->tx = 0;
info->err = 0; info->err = 0;
} }
uint8_t *ip_get_myip(IP_INFO *info) uint8_t *ip_get_myip(IP_INFO *info)
{ {
if (info != 0) if (info != 0)
{ {
return (uint8_t *) &info->myip[0]; return (uint8_t *) &info->myip[0];
} }
dbg("info is NULL!\n\t"); dbg("info is NULL!\n\t");
return 0; return 0;
} }
int ip_addr_compare(IP_ADDR_P addr1, IP_ADDR_P addr2) int ip_addr_compare(IP_ADDR_P addr1, IP_ADDR_P addr2)
{ {
int i; int i;
for (i = 0; i < sizeof(IP_ADDR); i++) for (i = 0; i < sizeof(IP_ADDR); i++)
{ {
if (addr1[i] != addr2[i]) if (addr1[i] != addr2[i])
return 0; return 0;
} }
return 1; return 1;
} }
uint8_t *ip_resolve_route(NIF *nif, IP_ADDR_P destip) uint8_t *ip_resolve_route(NIF *nif, IP_ADDR_P destip)
{ {
/* /*
* This function determines whether or not an outgoing IP * This function determines whether or not an outgoing IP
* packet needs to be transmitted on the local net or sent * packet needs to be transmitted on the local net or sent
* to the router for transmission. * to the router for transmission.
*/ */
IP_INFO *info; IP_INFO *info;
IP_ADDR mask, result; IP_ADDR mask, result;
IP_ADDR bc = { 255, 255, 255, 255 }; IP_ADDR bc = { 255, 255, 255, 255 };
int i; int i;
info = nif_get_protocol_info(nif, ETH_FRM_IP); info = nif_get_protocol_info(nif, ETH_FRM_IP);
if (memcmp(destip, bc, 4) == 0) if (memcmp(destip, bc, 4) == 0)
{ {
dbg("destip is broadcast address, no gateway needed\r\n"); dbg("destip is broadcast address, no gateway needed\r\n");
return destip; return destip;
} }
/* create mask for local IP */ /* create mask for local IP */
for (i = 0; i < sizeof(IP_ADDR); i++) for (i = 0; i < sizeof(IP_ADDR); i++)
{ {
mask[i] = info->myip[i] & info->netmask[i]; mask[i] = info->myip[i] & info->netmask[i];
} }
/* apply mask to the destination IP */ /* apply mask to the destination IP */
for (i = 0; i < sizeof(IP_ADDR); i++) for (i = 0; i < sizeof(IP_ADDR); i++)
{ {
result[i] = mask[i] & destip[i]; result[i] = mask[i] & destip[i];
} }
/* See if destination IP is local or not */ /* See if destination IP is local or not */
if (ip_addr_compare(mask, result)) if (ip_addr_compare(mask, result))
{ {
/* The destination IP is on the local net */ /* The destination IP is on the local net */
return arp_resolve(nif, ETH_FRM_IP, destip); return arp_resolve(nif, ETH_FRM_IP, destip);
} }
else else
{ {
/* The destination IP is not on the local net */ /* The destination IP is not on the local net */
return arp_resolve(nif, ETH_FRM_IP, info->gateway); return arp_resolve(nif, ETH_FRM_IP, info->gateway);
} }
} }
int ip_send(NIF *nif, uint8_t *dest, uint8_t *src, uint8_t protocol, NBUF *pNbuf) int ip_send(NIF *nif, uint8_t *dest, uint8_t *src, uint8_t protocol, NBUF *pNbuf)
{ {
/* /*
* This function assembles an IP datagram and passes it * This function assembles an IP datagram and passes it
* onto the hardware to be sent over the network. * onto the hardware to be sent over the network.
*/ */
uint8_t *route; uint8_t *route;
ip_frame_hdr *ipframe; ip_frame_hdr *ipframe;
/* /*
* Construct the IP header * Construct the IP header
*/ */
ipframe = (ip_frame_hdr*) &pNbuf->data[IP_HDR_OFFSET]; ipframe = (ip_frame_hdr*) &pNbuf->data[IP_HDR_OFFSET];
/* IP version 4, Internet Header Length of 5 32-bit words */ /* IP version 4, Internet Header Length of 5 32-bit words */
ipframe->version_ihl = 0x45; ipframe->version_ihl = 0x45;
/* Type of Service == 0, normal and routine */ /* Type of Service == 0, normal and routine */
ipframe->service_type = 0x00; ipframe->service_type = 0x00;
/* Total length of data */ /* Total length of data */
ipframe->total_length = (uint16_t) (pNbuf->length + IP_HDR_SIZE); ipframe->total_length = (uint16_t) (pNbuf->length + IP_HDR_SIZE);
/* User defined identification */ /* User defined identification */
ipframe->identification = 0x0000; ipframe->identification = 0x0000;
/* Fragment Flags and Offset -- Don't fragment, last frag */ /* Fragment Flags and Offset -- Don't fragment, last frag */
ipframe->flags_frag_offset = 0x0000; ipframe->flags_frag_offset = 0x0000;
/* Time To Live */ /* Time To Live */
ipframe->ttl = 0xFF; ipframe->ttl = 0xFF;
/* Protocol */ /* Protocol */
ipframe->protocol = protocol; ipframe->protocol = protocol;
/* Checksum, computed later, zeroed for computation */ /* Checksum, computed later, zeroed for computation */
ipframe->checksum = 0x0000; ipframe->checksum = 0x0000;
/* source IP address */ /* source IP address */
ipframe->source_addr[0] = src[0]; ipframe->source_addr[0] = src[0];
ipframe->source_addr[1] = src[1]; ipframe->source_addr[1] = src[1];
ipframe->source_addr[2] = src[2]; ipframe->source_addr[2] = src[2];
ipframe->source_addr[3] = src[3]; ipframe->source_addr[3] = src[3];
/* dest IP address */ /* dest IP address */
ipframe->dest_addr[0] = dest[0]; ipframe->dest_addr[0] = dest[0];
ipframe->dest_addr[1] = dest[1]; ipframe->dest_addr[1] = dest[1];
ipframe->dest_addr[2] = dest[2]; ipframe->dest_addr[2] = dest[2];
ipframe->dest_addr[3] = dest[3]; ipframe->dest_addr[3] = dest[3];
/* Compute checksum */ /* Compute checksum */
ipframe->checksum = ip_chksum((uint16_t *) ipframe, IP_HDR_SIZE); ipframe->checksum = ip_chksum((uint16_t *) ipframe, IP_HDR_SIZE);
/* Increment the packet length by the size of the IP header */ /* Increment the packet length by the size of the IP header */
pNbuf->length += IP_HDR_SIZE; pNbuf->length += IP_HDR_SIZE;
/* /*
* Determine the hardware address of the recipient * Determine the hardware address of the recipient
*/ */
IP_ADDR bc = { 255, 255, 255, 255}; IP_ADDR bc = { 255, 255, 255, 255};
if (memcmp(bc, dest, 4) != 0) if (memcmp(bc, dest, 4) != 0)
{ {
route = ip_resolve_route(nif, dest); route = ip_resolve_route(nif, dest);
if (route == NULL) if (route == NULL)
{ {
dbg("Unable to locate %d.%d.%d.%d\r\n", dbg("Unable to locate %d.%d.%d.%d\r\n",
dest[0], dest[1], dest[2], dest[3]); dest[0], dest[1], dest[2], dest[3]);
return 0; return 0;
} }
} }
else else
{ {
route = bc; route = bc;
dbg("route = broadcast\r\n"); dbg("route = broadcast\r\n");
dbg("nif = %p\r\n", nif); dbg("nif = %p\r\n", nif);
dbg("nif->send = %p\r\n", nif->send); dbg("nif->send = %p\r\n", nif->send);
} }
return nif->send(nif, route, &nif->hwa[0], ETH_FRM_IP, pNbuf); return nif->send(nif, route, &nif->hwa[0], ETH_FRM_IP, pNbuf);
} }
#if defined(DEBUG_PRINT) #if defined(DEBUG_PRINT)
void dump_ip_frame(ip_frame_hdr *ipframe) void dump_ip_frame(ip_frame_hdr *ipframe)
{ {
xprintf("Version: %02X\n", ((ipframe->version_ihl & 0x00f0) >> 4)); xprintf("Version: %02X\n", ((ipframe->version_ihl & 0x00f0) >> 4));
xprintf("IHL: %02X\n", ipframe->version_ihl & 0x000f); xprintf("IHL: %02X\n", ipframe->version_ihl & 0x000f);
xprintf("Service: %02X\n", ipframe->service_type); xprintf("Service: %02X\n", ipframe->service_type);
xprintf("Length: %04X\n", ipframe->total_length); xprintf("Length: %04X\n", ipframe->total_length);
xprintf("Ident: %04X\n", ipframe->identification); xprintf("Ident: %04X\n", ipframe->identification);
xprintf("Flags: %02X\n", ((ipframe->flags_frag_offset & 0xC000) >> 14)); xprintf("Flags: %02X\n", ((ipframe->flags_frag_offset & 0xC000) >> 14));
xprintf("Frag: %04X\n", ipframe->flags_frag_offset & 0x3FFF); xprintf("Frag: %04X\n", ipframe->flags_frag_offset & 0x3FFF);
xprintf("TTL: %02X\n", ipframe->ttl); xprintf("TTL: %02X\n", ipframe->ttl);
xprintf("Protocol: %02X\n", ipframe->protocol); xprintf("Protocol: %02X\n", ipframe->protocol);
xprintf("Chksum: %04X\n", ipframe->checksum); xprintf("Chksum: %04X\n", ipframe->checksum);
xprintf("Source : %d.%d.%d.%d\n", xprintf("Source : %d.%d.%d.%d\n",
ipframe->source_addr[0], ipframe->source_addr[0],
ipframe->source_addr[1], ipframe->source_addr[1],
ipframe->source_addr[2], ipframe->source_addr[2],
ipframe->source_addr[3]); ipframe->source_addr[3]);
xprintf("Dest : %d.%d.%d.%d\n", xprintf("Dest : %d.%d.%d.%d\n",
ipframe->dest_addr[0], ipframe->dest_addr[0],
ipframe->dest_addr[1], ipframe->dest_addr[1],
ipframe->dest_addr[2], ipframe->dest_addr[2],
ipframe->dest_addr[3]); ipframe->dest_addr[3]);
xprintf("Options: %08X\n", ipframe->options); xprintf("Options: %08X\n", ipframe->options);
} }
#endif #endif
uint16_t ip_chksum(uint16_t *data, int num) uint16_t ip_chksum(uint16_t *data, int num)
{ {
int chksum, ichksum; int chksum, ichksum;
uint16_t temp; uint16_t temp;
chksum = 0; chksum = 0;
num = num >> 1; /* from bytes to words */ num = num >> 1; /* from bytes to words */
for (; num; num--, data++) for (; num; num--, data++)
{ {
temp = *data; temp = *data;
ichksum = chksum + temp; ichksum = chksum + temp;
ichksum = ichksum & 0x0000FFFF; ichksum = ichksum & 0x0000FFFF;
if ((ichksum < temp) || (ichksum < chksum)) if ((ichksum < temp) || (ichksum < chksum))
{ {
ichksum += 1; ichksum += 1;
ichksum = ichksum & 0x0000FFFF; ichksum = ichksum & 0x0000FFFF;
} }
chksum = ichksum; chksum = ichksum;
} }
return (uint16_t) ~chksum; return (uint16_t) ~chksum;
} }
static int validate_ip_hdr(NIF *nif, ip_frame_hdr *ipframe) static int validate_ip_hdr(NIF *nif, ip_frame_hdr *ipframe)
{ {
int index, chksum; int index, chksum;
IP_INFO *info; IP_INFO *info;
/* /*
* Check the IP Version * Check the IP Version
*/ */
if (IP_VERSION(ipframe) != 4) if (IP_VERSION(ipframe) != 4)
return 0; return 0;
/* /*
* Check Internet Header Length * Check Internet Header Length
*/ */
if (IP_IHL(ipframe) < 5) if (IP_IHL(ipframe) < 5)
return 0; return 0;
/* /*
* Check the destination IP address * Check the destination IP address
*/ */
info = nif_get_protocol_info(nif,ETH_FRM_IP); info = nif_get_protocol_info(nif,ETH_FRM_IP);
for (index = 0; index < sizeof(IP_ADDR); index++) for (index = 0; index < sizeof(IP_ADDR); index++)
if (info->myip[index] != ipframe->dest_addr[index]) if (info->myip[index] != ipframe->dest_addr[index])
return 0; return 0;
/* /*
* Check the checksum * Check the checksum
*/ */
chksum = (int)((uint16_t) IP_CHKSUM(ipframe)); chksum = (int)((uint16_t) IP_CHKSUM(ipframe));
IP_CHKSUM(ipframe) = 0; IP_CHKSUM(ipframe) = 0;
if (ip_chksum((uint16_t *) ipframe, IP_IHL(ipframe) * 4) != chksum) if (ip_chksum((uint16_t *) ipframe, IP_IHL(ipframe) * 4) != chksum)
return 0; return 0;
IP_CHKSUM(ipframe) = (uint16_t) chksum; IP_CHKSUM(ipframe) = (uint16_t) chksum;
return 1; return 1;
} }
void ip_handler(NIF *nif, NBUF *pNbuf) void ip_handler(NIF *nif, NBUF *pNbuf)
{ {
/* /*
* IP packet handler * IP packet handler
*/ */
ip_frame_hdr *ipframe; ip_frame_hdr *ipframe;
dbg("packet received\r\n"); dbg("packet received\r\n");
ipframe = (ip_frame_hdr *) &pNbuf->data[pNbuf->offset]; ipframe = (ip_frame_hdr *) &pNbuf->data[pNbuf->offset];
/* /*
* Verify valid IP header and destination IP * Verify valid IP header and destination IP
*/ */
if (!validate_ip_hdr(nif, ipframe)) if (!validate_ip_hdr(nif, ipframe))
{ {
dbg("not a valid IP packet!\r\n"); dbg("not a valid IP packet!\r\n");
nbuf_free(pNbuf); nbuf_free(pNbuf);
return; return;
} }
pNbuf->offset += (IP_IHL(ipframe) * 4); /*
pNbuf->length = (uint16_t)(IP_LENGTH(ipframe) - (IP_IHL(ipframe) * 4)); * Call the appriopriate handler
*/
/* switch (IP_PROTOCOL(ipframe))
* Call the appriopriate handler {
*/ case IP_PROTO_ICMP:
switch (IP_PROTOCOL(ipframe)) // FIXME: icmp_handler(nif, pNbuf);
{ break;
case IP_PROTO_ICMP: case IP_PROTO_UDP:
// FIXME: icmp_handler(nif, pNbuf); udp_handler(nif,pNbuf);
break; break;
case IP_PROTO_UDP: default:
udp_handler(nif,pNbuf); dbg("no protocol handler registered for protocol %d\r\n",
break; __FUNCTION__, IP_PROTOCOL(ipframe));
default: nbuf_free(pNbuf);
dbg("no protocol handler registered for protocol %d\r\n", break;
__FUNCTION__, IP_PROTOCOL(ipframe)); }
nbuf_free(pNbuf); return;
break;
}
return;
} }

View File

@@ -21,8 +21,8 @@
typedef struct typedef struct
{ {
uint16_t port; uint16_t port;
void (*handler)(NIF *, NBUF *); void (*handler)(NIF *, NBUF *);
} UDP_BOUND_PORT; } UDP_BOUND_PORT;
#define UDP_MAX_PORTS (5) /* plenty for this implementation */ #define UDP_MAX_PORTS (5) /* plenty for this implementation */
@@ -34,151 +34,151 @@ static uint16_t udp_port;
void udp_init(void) void udp_init(void)
{ {
int index; int index;
for (index = 0; index < UDP_MAX_PORTS; ++index) for (index = 0; index < UDP_MAX_PORTS; ++index)
{ {
udp_port_table[index].port = 0; udp_port_table[index].port = 0;
udp_port_table[index].handler = 0; udp_port_table[index].handler = 0;
} }
udp_port = DEFAULT_UDP_PORT; /* next free port */ udp_port = DEFAULT_UDP_PORT; /* next free port */
} }
void udp_prime_port(uint16_t init_port) void udp_prime_port(uint16_t init_port)
{ {
udp_port = init_port; udp_port = init_port;
} }
void udp_bind_port(uint16_t port, void (*handler)(NIF *, NBUF *)) void udp_bind_port(uint16_t port, void (*handler)(NIF *, NBUF *))
{ {
int index; int index;
for (index = 0; index < UDP_MAX_PORTS; ++index) for (index = 0; index < UDP_MAX_PORTS; ++index)
{ {
if (udp_port_table[index].port == 0) if (udp_port_table[index].port == 0)
{ {
udp_port_table[index].port = port; udp_port_table[index].port = port;
udp_port_table[index].handler = handler; udp_port_table[index].handler = handler;
return; return;
} }
} }
} }
void udp_free_port(uint16_t port) void udp_free_port(uint16_t port)
{ {
int index; int index;
for (index = 0; index < UDP_MAX_PORTS; ++index) for (index = 0; index < UDP_MAX_PORTS; ++index)
{ {
if (udp_port_table[index].port == port) if (udp_port_table[index].port == port)
{ {
udp_port_table[index].port = 0; udp_port_table[index].port = 0;
return; return;
} }
} }
} }
static void *udp_port_handler(uint16_t port) static void *udp_port_handler(uint16_t port)
{ {
int index; int index;
for (index = 0; index < UDP_MAX_PORTS; ++index) for (index = 0; index < UDP_MAX_PORTS; ++index)
{ {
if (udp_port_table[index].port == port) if (udp_port_table[index].port == port)
{ {
return (void *) udp_port_table[index].handler; return (void *) udp_port_table[index].handler;
} }
} }
return NULL; return NULL;
} }
uint16_t udp_obtain_free_port(void) uint16_t udp_obtain_free_port(void)
{ {
uint16_t port; uint16_t port;
port = udp_port; port = udp_port;
if (--udp_port <= 255) if (--udp_port <= 255)
udp_port = DEFAULT_UDP_PORT; udp_port = DEFAULT_UDP_PORT;
return port; return port;
} }
int udp_send(NIF *nif, uint8_t *dest, int sport, int dport, NBUF *pNbuf) int udp_send(NIF *nif, uint8_t *dest, int sport, int dport, NBUF *pNbuf)
{ {
uint8_t *myip; uint8_t *myip;
if (nif == NULL) if (nif == NULL)
{ {
dbg("nif is NULL\r\n"); dbg("nif is NULL\r\n");
return 0; return 0;
} }
/* /*
* This function takes data, creates a UDP frame from it and * This function takes data, creates a UDP frame from it and
* passes it onto the IP layer * passes it onto the IP layer
*/ */
udp_frame_hdr *udpframe; udp_frame_hdr *udpframe;
udpframe = (udp_frame_hdr *) &pNbuf->data[UDP_HDR_OFFSET]; udpframe = (udp_frame_hdr *) &pNbuf->data[UDP_HDR_OFFSET];
/* Set UDP source port */ /* Set UDP source port */
udpframe->src_port = (uint16_t) sport; udpframe->src_port = (uint16_t) sport;
/* Set UDP destination port */ /* Set UDP destination port */
udpframe->dest_port = (uint16_t) dport; udpframe->dest_port = (uint16_t) dport;
/* Set length */ /* Set length */
udpframe->length = (uint16_t) (pNbuf->length + UDP_HDR_SIZE); udpframe->length = (uint16_t) (pNbuf->length + UDP_HDR_SIZE);
/* No checksum calcualation needed */ /* No checksum calcualation needed */
udpframe->chksum = (uint16_t) 0; udpframe->chksum = (uint16_t) 0;
/* Add the length of the UDP packet to the total length of the packet */ /* Add the length of the UDP packet to the total length of the packet */
pNbuf->length += 8; pNbuf->length += 8;
myip = ip_get_myip(nif_get_protocol_info(nif, ETH_FRM_IP)); myip = ip_get_myip(nif_get_protocol_info(nif, ETH_FRM_IP));
dbg("sent UDP request to %d.%d.%d.%d from %d.%d.%d.%d\r\n", dbg("sent UDP request to %d.%d.%d.%d from %d.%d.%d.%d\r\n",
dest[0], dest[1], dest[2], dest[3], dest[0], dest[1], dest[2], dest[3],
myip[0], myip[1], myip[2], myip[3]); myip[0], myip[1], myip[2], myip[3]);
return (ip_send(nif, dest, myip, IP_PROTO_UDP, pNbuf)); return (ip_send(nif, dest, myip, IP_PROTO_UDP, pNbuf));
} }
void udp_handler(NIF *nif, NBUF *pNbuf) void udp_handler(NIF *nif, NBUF *pNbuf)
{ {
/* /*
* This function handles incoming UDP packets * This function handles incoming UDP packets
*/ */
udp_frame_hdr *udpframe; udp_frame_hdr *udpframe;
void (*handler)(NIF *, NBUF *); void (*handler)(NIF *, NBUF *);
udpframe = (udp_frame_hdr *) &pNbuf->data[pNbuf->offset]; udpframe = (udp_frame_hdr *) &pNbuf->data[pNbuf->offset];
dbg("packet received\r\n",); dbg("packet received\r\n",);
/* /*
* Adjust the length and valid data offset of the packet we are * Adjust the length and valid data offset of the packet we are
* passing on * passing on
*/ */
pNbuf->length -= UDP_HDR_SIZE; pNbuf->length -= UDP_HDR_SIZE;
pNbuf->offset += UDP_HDR_SIZE; pNbuf->offset += UDP_HDR_SIZE;
/* /*
* Traverse the list of bound ports to see if there is a higher * Traverse the list of bound ports to see if there is a higher
* level protocol to pass the packet on to * level protocol to pass the packet on to
*/ */
if ((handler = (void(*)(NIF*, NBUF*)) udp_port_handler(UDP_DEST(udpframe))) != NULL) if ((handler = (void(*)(NIF*, NBUF*)) udp_port_handler(UDP_DEST(udpframe))) != NULL)
handler(nif, pNbuf); handler(nif, pNbuf);
else else
{ {
dbg("received UDP packet for non-supported port\n"); dbg("received UDP packet for non-supported port\n");
nbuf_free(pNbuf); nbuf_free(pNbuf);
} }
return; return;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -34,54 +34,57 @@
#define dbg(format, arg...) do { ; } while (0) #define dbg(format, arg...) do { ; } while (0)
#endif #endif
#define FPGA_STATUS (1 << 0) #define FPGA_STATUS (1 << 0)
#define FPGA_CLOCK (1 << 1) #define FPGA_CLOCK (1 << 1)
#define FPGA_CONFIG (1 << 2) #define FPGA_CONFIG (1 << 2)
#define FPGA_DATA0 (1 << 3) #define FPGA_DATA0 (1 << 3)
#define FPGA_CONF_DONE (1 << 5) #define FPGA_CONF_DONE (1 << 5)
extern uint8_t _FPGA_CONFIG[]; extern uint8_t _FPGA_CONFIG[];
#define FPGA_FLASH_DATA &_FPGA_CONFIG[0] #define FPGA_FLASH_DATA &_FPGA_CONFIG[0]
extern uint8_t _FPGA_CONFIG_SIZE[]; extern uint8_t _FPGA_CONFIG_SIZE[];
#define FPGA_FLASH_DATA_SIZE ((uint32_t) &_FPGA_CONFIG_SIZE[0]) #define FPGA_FLASH_DATA_SIZE ((uint32_t) &_FPGA_CONFIG_SIZE[0])
/* /*
* flag located in processor SRAM1 that indicates that the FPGA configuration has * flag located in processor SRAM1 that indicates that the FPGA configuration has
* been loaded through JTAG. init_fpga() will honour this and not overwrite config. * been loaded through the onboard JTAG interface.
* init_fpga() will honour this and not overwrite config.
*/ */
extern bool _FPGA_JTAG_LOADED; extern bool _FPGA_JTAG_LOADED;
extern long _FPGA_JTAG_VALID; extern long _FPGA_JTAG_VALID;
#define VALID_JTAG 0xaffeaffe #define VALID_JTAG 0xaffeaffe
extern int32_t _FPGA_JTAG_VALID;
#define VALID_JTAG 0xaffeaffe
void config_gpio_for_fpga_config(void) void config_gpio_for_fpga_config(void)
{ {
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
/* /*
* Configure GPIO FEC1L port directions (needed to load FPGA configuration) * Configure GPIO FEC1L port directions (needed to load FPGA configuration)
*/ */
MCF_GPIO_PDDR_FEC1L = 0 | /* bit 7 = input */ MCF_GPIO_PDDR_FEC1L = 0 | /* bit 7 = input */
0 | /* bit 6 = input */ 0 | /* bit 6 = input */
0 | /* bit 5 = input */ 0 | /* bit 5 = input */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4 | /* bit 4 = LED => output */ MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4 | /* bit 4 = LED => output */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L3 | /* bit 3 = PRG_DQ0 => output */ MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L3 | /* bit 3 = PRG_DQ0 => output */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L2 | /* bit 2 = FPGA_CONFIG => output */ MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L2 | /* bit 2 = FPGA_CONFIG => output */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L1 | /* bit 1 = PRG_CLK (FPGA) => output */ MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L1 | /* bit 1 = PRG_CLK (FPGA) => output */
0; /* bit 0 => input */ 0; /* bit 0 => input */
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
} }
void config_gpio_for_jtag_config(void) void config_gpio_for_jtag_config(void)
{ {
/* /*
* configure FEC1L port directions to enable external JTAG configuration download to FPGA * configure FEC1L port directions to enable external JTAG configuration download to FPGA
*/ */
MCF_GPIO_PDDR_FEC1L = 0 | MCF_GPIO_PDDR_FEC1L = 0 |
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */ MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
/* all other bits = input */ /* all other bits = input */
/* /*
* unfortunately, the GPIO module cannot trigger interrupts. That means CONF_DONE needs to be polled to detect * unfortunately, the GPIO module cannot trigger interrupts. That means CONF_DONE needs to be polled to detect
* external FPGA (re)configuration and reset the system in that case. Could be done from the OS as well... * external FPGA (re)configuration and reset the system in that case. Could be done from the OS as well...
*/ */
} }
/* /*
@@ -89,96 +92,100 @@ void config_gpio_for_jtag_config(void)
*/ */
bool init_fpga(void) bool init_fpga(void)
{ {
uint8_t *fpga_data; uint8_t *fpga_data;
volatile int32_t time, start, end; volatile int32_t time, start, end;
int i; int i;
dbg("FPGA load config\r\n(_FPGA_JTAG_LOADED = %x, _FPGA_JTAG_VALID = %x)...\r\n", _FPGA_JTAG_LOADED, _FPGA_JTAG_VALID); dbg("FPGA load config\r\n(_FPGA_JTAG_LOADED = %x, _FPGA_JTAG_VALID = %x)...\r\n", _FPGA_JTAG_LOADED, _FPGA_JTAG_VALID);
if (_FPGA_JTAG_LOADED == true && _FPGA_JTAG_VALID == VALID_JTAG) if (_FPGA_JTAG_LOADED == true && _FPGA_JTAG_VALID == VALID_JTAG)
{ {
dbg("detected _FPGA_JTAG_LOADED flag. Not overwriting FPGA config.\r\n"); dbg("detected _FPGA_JTAG_LOADED flag. Not overwriting FPGA config.\r\n");
/* reset the flag so that next boot will load config again from flash */ /* reset the flag so that next boot will load config again from flash */
_FPGA_JTAG_LOADED = 0; _FPGA_JTAG_LOADED = 0;
return true; _FPGA_JTAG_VALID = 0;
}
start = MCF_SLT0_SCNT;
config_gpio_for_fpga_config(); return true;
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */ }
start = MCF_SLT0_SCNT;
/* pulling FPGA_CONFIG to low resets the FPGA */ config_gpio_for_fpga_config();
MCF_GPIO_PODR_FEC1L &= ~FPGA_CONFIG; /* FPGA config => low */ MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */
wait(10); /* give it some time to do its reset stuff */
while ((MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS) && (MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)); /* pulling FPGA_CONFIG to low resets the FPGA */
MCF_GPIO_PODR_FEC1L &= ~FPGA_CONFIG; /* FPGA config => low */
wait(10); /* give it some time to do its reset stuff */
MCF_GPIO_PODR_FEC1L |= FPGA_CONFIG; /* pull FPGA_CONFIG high to start config cycle */ while ((MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS) && (MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE));
while (!(MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS)); /* wait until status becomes high */
/* MCF_GPIO_PODR_FEC1L |= FPGA_CONFIG; /* pull FPGA_CONFIG high to start config cycle */
* excerpt from an Altera configuration manual: while (!(MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS))
* ; /* wait until status becomes high */
* The low-to-high transition of nCONFIG on the FPGA begins the configuration cycle. The
* configuration cycle consists of 3 stages<65>reset, configuration, and initialization.
* While nCONFIG is low, the device is in reset. When the device comes out of reset,
* nCONFIG must be at a logic high level in order for the device to release the open-drain
* nSTATUS pin. After nSTATUS is released, it is pulled high by a pull-up resistor and the FPGA
* is ready to receive configuration data. Before and during configuration, all user I/O pins
* are tri-stated. Stratix series, Arria series, and Cyclone series have weak pull-up resistors
* on the I/O pins which are on, before and during configuration.
*
* To begin configuration, nCONFIG and nSTATUS must be at a logic high level. You can delay
* configuration by holding the nCONFIG low. The device receives configuration data on its
* DATA0 pins. Configuration data is latched into the FPGA on the rising edge of DCLK. After
* the FPGA has received all configuration data successfully, it releases the CONF_DONE pin,
* which is pulled high by a pull-up resistor. A low to high transition on CONF_DONE indicates
* configuration is complete and initialization of the device can begin.
*/
const uint8_t *fpga_flash_data_end = FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE; /*
* excerpt from an Altera configuration manual:
*
* The low-to-high transition of nCONFIG on the FPGA begins the configuration cycle. The
* configuration cycle consists of 3 stages<65>reset, configuration, and initialization.
* While nCONFIG is low, the device is in reset. When the device comes out of reset,
* nCONFIG must be at a logic high level in order for the device to release the open-drain
* nSTATUS pin. After nSTATUS is released, it is pulled high by a pull-up resistor and the FPGA
* is ready to receive configuration data. Before and during configuration, all user I/O pins
* are tri-stated. Stratix series, Arria series, and Cyclone series have weak pull-up resistors
* on the I/O pins which are on, before and during configuration.
*
* To begin configuration, nCONFIG and nSTATUS must be at a logic high level. You can delay
* configuration by holding the nCONFIG low. The device receives configuration data on its
* DATA0 pins. Configuration data is latched into the FPGA on the rising edge of DCLK. After
* the FPGA has received all configuration data successfully, it releases the CONF_DONE pin,
* which is pulled high by a pull-up resistor. A low to high transition on CONF_DONE indicates
* configuration is complete and initialization of the device can begin.
*/
fpga_data = (uint8_t *) FPGA_FLASH_DATA; const uint8_t *fpga_flash_data_end = FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
do
{
uint8_t value = *fpga_data++;
for (i = 0; i < 8; i++, value >>= 1)
{
if (value & 1) fpga_data = (uint8_t *) FPGA_FLASH_DATA;
{ do
/* bit set -> toggle DATA0 to high */ {
MCF_GPIO_PODR_FEC1L |= FPGA_DATA0; uint8_t value = *fpga_data++;
} for (i = 0; i < 8; i++, value >>= 1)
else {
{
/* bit is cleared -> toggle DATA0 to low */
MCF_GPIO_PODR_FEC1L &= ~FPGA_DATA0;
}
/* toggle DCLK -> FPGA reads the bit */
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
}
} while ((!(MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)) && (fpga_data < fpga_flash_data_end));
if (fpga_data < fpga_flash_data_end) if (value & 1)
{ {
/* bit set -> toggle DATA0 to high */
MCF_GPIO_PODR_FEC1L |= FPGA_DATA0;
}
else
{
/* bit is cleared -> toggle DATA0 to low */
MCF_GPIO_PODR_FEC1L &= ~FPGA_DATA0;
}
/* toggle DCLK -> FPGA reads the bit */
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
}
} while ((!(MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)) && (fpga_data < fpga_flash_data_end));
if (fpga_data < fpga_flash_data_end)
{
#ifdef _NOT_USED_ #ifdef _NOT_USED_
while (fpga_data++ < fpga_flash_data_end) while (fpga_data++ < fpga_flash_data_end)
{ {
/* toggle a little more since it's fun ;) */ /* toggle a little more since it's fun ;) */
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK; MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
} }
#endif /* _NOT_USED_ */ #endif /* _NOT_USED_ */
end = MCF_SLT0_SCNT; end = MCF_SLT0_SCNT;
time = (start - end) / (SYSCLK / 1000) / 1000; time = (start - end) / (SYSCLK / 1000) / 1000;
xprintf("finished (took %f seconds).\r\n", time / 1000.0); xprintf("finished (took %f seconds).\r\n", time / 1000.0);
config_gpio_for_jtag_config(); config_gpio_for_jtag_config();
return true; return true;
} }
xprintf("FAILED!\r\n"); xprintf("FAILED!\r\n");
config_gpio_for_jtag_config(); config_gpio_for_jtag_config();
return false;
return false;
} }