merged fixes from 0.8.6.1 (errornous skip of FPGA load)
This commit is contained in:
382
bas.lk.in
382
bas.lk.in
@@ -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 */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
194
net/fecbd.c
194
net/fecbd.c
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
451
net/ip.c
451
net/ip.c
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
182
net/udp.c
182
net/udp.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
910
sys/exceptions.S
910
sys/exceptions.S
File diff suppressed because it is too large
Load Diff
223
sys/init_fpga.c
223
sys/init_fpga.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user