Compare commits
4 Commits
Bas_gcc_mm
...
R_0_8_6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40162047d8 | ||
|
|
f871794760 | ||
|
|
88c1bd2373 | ||
|
|
5163fd5813 |
372
bas.lk.in
372
bas.lk.in
@@ -19,242 +19,244 @@ MEMORY
|
||||
{
|
||||
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
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* BaS in ROM */
|
||||
.text :
|
||||
{
|
||||
OBJDIR/startcf.o(.text) /* this one is the entry point so it must be the first */
|
||||
/* BaS in ROM */
|
||||
.text :
|
||||
{
|
||||
OBJDIR/startcf.o(.text) /* this one is the entry point so it must be the first */
|
||||
|
||||
OBJDIR/sysinit.o(.text)
|
||||
OBJDIR/fault_vectors.o(.text)
|
||||
OBJDIR/sysinit.o(.text)
|
||||
OBJDIR/fault_vectors.o(.text)
|
||||
#ifdef MACHINE_FIREBEE
|
||||
OBJDIR/init_fpga.o(.text)
|
||||
OBJDIR/init_fpga.o(.text)
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
OBJDIR/wait.o(.text)
|
||||
OBJDIR/exceptions.o(.text)
|
||||
OBJDIR/driver_vec.o(.text)
|
||||
OBJDIR/interrupts.o(.text)
|
||||
OBJDIR/mmu.o(.text)
|
||||
OBJDIR/wait.o(.text)
|
||||
OBJDIR/exceptions.o(.text)
|
||||
OBJDIR/driver_vec.o(.text)
|
||||
OBJDIR/interrupts.o(.text)
|
||||
OBJDIR/mmu.o(.text)
|
||||
|
||||
OBJDIR/BaS.o(.text)
|
||||
OBJDIR/pci.o(.text)
|
||||
OBJDIR/pci_wrappers.o(.text)
|
||||
OBJDIR/usb.o(.text)
|
||||
OBJDIR/driver_mem.o(.text)
|
||||
OBJDIR/usb_mouse.o(.text)
|
||||
OBJDIR/ohci-hcd.o(.text)
|
||||
OBJDIR/ehci-hcd.o(.text)
|
||||
OBJDIR/wait.o(.text)
|
||||
OBJDIR/BaS.o(.text)
|
||||
OBJDIR/pci.o(.text)
|
||||
OBJDIR/pci_wrappers.o(.text)
|
||||
OBJDIR/usb.o(.text)
|
||||
OBJDIR/driver_mem.o(.text)
|
||||
OBJDIR/usb_mouse.o(.text)
|
||||
OBJDIR/ohci-hcd.o(.text)
|
||||
OBJDIR/ehci-hcd.o(.text)
|
||||
OBJDIR/wait.o(.text)
|
||||
|
||||
OBJDIR/nbuf.o(.text)
|
||||
OBJDIR/net_timer.o(.text)
|
||||
OBJDIR/queue.o(.text)
|
||||
OBJDIR/nif.o(.text)
|
||||
OBJDIR/fecbd.o(.text)
|
||||
OBJDIR/fec.o(.text)
|
||||
OBJDIR/am79c874.o(.text)
|
||||
OBJDIR/bcm5222.o(.text)
|
||||
OBJDIR/ip.o(.text)
|
||||
OBJDIR/udp.o(text)
|
||||
OBJDIR/bootp.o(text)
|
||||
OBJDIR/tftp.o(text)
|
||||
OBJDIR/arp.o(text)
|
||||
OBJDIR/nbuf.o(.text)
|
||||
OBJDIR/net_timer.o(.text)
|
||||
OBJDIR/queue.o(.text)
|
||||
OBJDIR/nif.o(.text)
|
||||
OBJDIR/fecbd.o(.text)
|
||||
OBJDIR/fec.o(.text)
|
||||
OBJDIR/am79c874.o(.text)
|
||||
OBJDIR/bcm5222.o(.text)
|
||||
OBJDIR/ip.o(.text)
|
||||
OBJDIR/udp.o(text)
|
||||
OBJDIR/bootp.o(text)
|
||||
OBJDIR/tftp.o(text)
|
||||
OBJDIR/arp.o(text)
|
||||
|
||||
OBJDIR/unicode.o(.text)
|
||||
OBJDIR/mmc.o(.text)
|
||||
OBJDIR/ff.o(.text)
|
||||
OBJDIR/sd_card.o(.text)
|
||||
OBJDIR/s19reader.o(.text)
|
||||
OBJDIR/bas_printf.o(.text)
|
||||
OBJDIR/bas_string.o(.text)
|
||||
OBJDIR/printf_helper.o(.text)
|
||||
OBJDIR/cache.o(.text)
|
||||
OBJDIR/dma.o(.text)
|
||||
OBJDIR/MCD_dmaApi.o(.text)
|
||||
OBJDIR/MCD_tasks.o(.text)
|
||||
OBJDIR/MCD_tasksInit.o(.text)
|
||||
OBJDIR/unicode.o(.text)
|
||||
OBJDIR/mmc.o(.text)
|
||||
OBJDIR/ff.o(.text)
|
||||
OBJDIR/sd_card.o(.text)
|
||||
OBJDIR/s19reader.o(.text)
|
||||
OBJDIR/bas_printf.o(.text)
|
||||
OBJDIR/bas_string.o(.text)
|
||||
OBJDIR/printf_helper.o(.text)
|
||||
OBJDIR/cache.o(.text)
|
||||
OBJDIR/dma.o(.text)
|
||||
OBJDIR/MCD_dmaApi.o(.text)
|
||||
OBJDIR/MCD_tasks.o(.text)
|
||||
OBJDIR/MCD_tasksInit.o(.text)
|
||||
|
||||
OBJDIR/video.o(.text)
|
||||
OBJDIR/videl.o(.text)
|
||||
OBJDIR/fbmem.o(.text)
|
||||
OBJDIR/fbmon.o(.text)
|
||||
OBJDIR/fbmodedb.o(.text)
|
||||
OBJDIR/offscreen.o(.text)
|
||||
OBJDIR/video.o(.text)
|
||||
OBJDIR/videl.o(.text)
|
||||
OBJDIR/fbmem.o(.text)
|
||||
OBJDIR/fbmon.o(.text)
|
||||
OBJDIR/fbmodedb.o(.text)
|
||||
OBJDIR/offscreen.o(.text)
|
||||
|
||||
OBJDIR/x86decode.o(.text)
|
||||
OBJDIR/x86ops.o(.text)
|
||||
OBJDIR/x86ops2.o(.text)
|
||||
OBJDIR/x86fpu.o(.text)
|
||||
OBJDIR/x86sys.o(.text)
|
||||
OBJDIR/x86biosemu.o(.text)
|
||||
OBJDIR/x86debug.o(.text)
|
||||
OBJDIR/x86prim_ops.o(.text)
|
||||
OBJDIR/x86pcibios.o(.text)
|
||||
OBJDIR/x86decode.o(.text)
|
||||
OBJDIR/x86ops.o(.text)
|
||||
OBJDIR/x86ops2.o(.text)
|
||||
OBJDIR/x86fpu.o(.text)
|
||||
OBJDIR/x86sys.o(.text)
|
||||
OBJDIR/x86biosemu.o(.text)
|
||||
OBJDIR/x86debug.o(.text)
|
||||
OBJDIR/x86prim_ops.o(.text)
|
||||
OBJDIR/x86pcibios.o(.text)
|
||||
|
||||
OBJDIR/radeon_base.o(.text)
|
||||
OBJDIR/radeon_accel.o(.text)
|
||||
OBJDIR/radeon_cursor.o(.text)
|
||||
OBJDIR/radeon_monitor.o(.text)
|
||||
OBJDIR/radeon_base.o(.text)
|
||||
OBJDIR/radeon_accel.o(.text)
|
||||
OBJDIR/radeon_cursor.o(.text)
|
||||
OBJDIR/radeon_monitor.o(.text)
|
||||
|
||||
OBJDIR/xhdi_sd.o(.text)
|
||||
OBJDIR/xhdi_interface.o(.text)
|
||||
OBJDIR/xhdi_vec.o(.text)
|
||||
OBJDIR/xhdi_sd.o(.text)
|
||||
OBJDIR/xhdi_interface.o(.text)
|
||||
OBJDIR/xhdi_vec.o(.text)
|
||||
|
||||
#ifdef COMPILE_RAM
|
||||
/*
|
||||
* if we compile to RAM anyway, there is no need to copy anything
|
||||
*/
|
||||
. = ALIGN(4);
|
||||
__BAS_DATA_START = .;
|
||||
*(.data)
|
||||
__BAS_DATA_END = .;
|
||||
__BAS_BSS_START = .;
|
||||
*(.bss)
|
||||
__BAS_BSS_END = .;
|
||||
/*
|
||||
* if we compile to RAM anyway, there is no need to copy anything
|
||||
*/
|
||||
. = ALIGN(4);
|
||||
__BAS_DATA_START = .;
|
||||
*(.data)
|
||||
__BAS_DATA_END = .;
|
||||
__BAS_BSS_START = .;
|
||||
*(.bss)
|
||||
__BAS_BSS_END = .;
|
||||
#endif /* COMPILE_RAM */
|
||||
|
||||
#if (FORMAT_ELF == 1)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
#endif
|
||||
} > bas_rom
|
||||
} > bas_rom
|
||||
|
||||
#if (TARGET_ADDRESS == BOOTFLASH_BASE_ADDRESS)
|
||||
/*
|
||||
* put BaS .data and .bss segments to flash, but relocate it to RAM after initialize_hardware() ran
|
||||
*/
|
||||
.bas :
|
||||
AT (ALIGN(ADDR(.text) + SIZEOF(.text), 4))
|
||||
{
|
||||
. = ALIGN(4); /* same alignment than AT() statement! */
|
||||
__BAS_DATA_START = .;
|
||||
*(.data)
|
||||
__BAS_DATA_END = .;
|
||||
__BAS_BSS_START = .;
|
||||
*(.bss)
|
||||
__BAS_BSS_END = .;
|
||||
/*
|
||||
* put BaS .data and .bss segments to flash, but relocate it to RAM after initialize_hardware() ran
|
||||
*/
|
||||
.bas :
|
||||
AT (ALIGN(ADDR(.text) + SIZEOF(.text), 4))
|
||||
{
|
||||
. = ALIGN(4); /* same alignment than AT() statement! */
|
||||
__BAS_DATA_START = .;
|
||||
*(.data)
|
||||
__BAS_DATA_END = .;
|
||||
__BAS_BSS_START = .;
|
||||
*(.bss)
|
||||
__BAS_BSS_END = .;
|
||||
|
||||
. = ALIGN(16);
|
||||
} > bas_ram
|
||||
. = ALIGN(16);
|
||||
} > bas_ram
|
||||
#endif
|
||||
|
||||
.driver_memory :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_driver_mem_buffer = .;
|
||||
//. = . + DRIVER_MEM_BUFFER_SIZE;
|
||||
} > driver_ram
|
||||
.driver_memory :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_driver_mem_buffer = .;
|
||||
//. = . + DRIVER_MEM_BUFFER_SIZE;
|
||||
} > driver_ram
|
||||
|
||||
/*
|
||||
* Global memory map
|
||||
*/
|
||||
/*
|
||||
* Global memory map
|
||||
*/
|
||||
|
||||
/* SDRAM Initialization */
|
||||
___SDRAM = SDRAM_START;
|
||||
___SDRAM_SIZE = SDRAM_SIZE;
|
||||
_SDRAM_VECTOR_TABLE = ___SDRAM;
|
||||
/* SDRAM Initialization */
|
||||
___SDRAM = SDRAM_START;
|
||||
___SDRAM_SIZE = SDRAM_SIZE;
|
||||
_SDRAM_VECTOR_TABLE = ___SDRAM;
|
||||
|
||||
/* ST-RAM */
|
||||
__STRAM = ___SDRAM;
|
||||
__STRAM_END = __TOS;
|
||||
/* ST-RAM */
|
||||
__STRAM = ___SDRAM;
|
||||
__STRAM_END = __TOS;
|
||||
|
||||
/* TOS */
|
||||
__TOS = 0x00e00000;
|
||||
/* TOS */
|
||||
__TOS = 0x00e00000;
|
||||
|
||||
/* FastRAM */
|
||||
__FASTRAM = 0x10000000;
|
||||
__TARGET_ADDRESS = TARGET_ADDRESS;
|
||||
/* FastRAM */
|
||||
__FASTRAM = 0x10000000;
|
||||
__TARGET_ADDRESS = TARGET_ADDRESS;
|
||||
|
||||
#if TARGET_ADDRESS == BOOTFLASH_BASE_ADDRESS
|
||||
__FASTRAM_END = __BAS_IN_RAM;
|
||||
__FASTRAM_END = __BAS_IN_RAM;
|
||||
#else
|
||||
__FASTRAM_END = TARGET_ADDRESS;
|
||||
__FASTRAM_END = TARGET_ADDRESS;
|
||||
#endif
|
||||
__FASTRAM_SIZE = __FASTRAM_END - __FASTRAM;
|
||||
__FASTRAM_SIZE = __FASTRAM_END - __FASTRAM;
|
||||
|
||||
/* Init CS0 (BootFLASH @ E000_0000 - E07F_FFFF 8Mbytes) */
|
||||
___BOOT_FLASH = BOOTFLASH_BASE_ADDRESS;
|
||||
___BOOT_FLASH_SIZE = BOOTFLASH_SIZE;
|
||||
/* Init CS0 (BootFLASH @ E000_0000 - E07F_FFFF 8Mbytes) */
|
||||
___BOOT_FLASH = BOOTFLASH_BASE_ADDRESS;
|
||||
___BOOT_FLASH_SIZE = BOOTFLASH_SIZE;
|
||||
|
||||
#if TARGET_ADDRESS == BOOTFLASH_BASE_ADDRESS
|
||||
/* BaS */
|
||||
__BAS_LMA = LOADADDR(.bas);
|
||||
__BAS_IN_RAM = ADDR(.bas);
|
||||
__BAS_SIZE = SIZEOF(.bas);
|
||||
/* BaS */
|
||||
__BAS_LMA = LOADADDR(.bas);
|
||||
__BAS_IN_RAM = ADDR(.bas);
|
||||
__BAS_SIZE = SIZEOF(.bas);
|
||||
#else
|
||||
/* BaS is already in RAM - no need to copy anything */
|
||||
__BAS_IN_RAM = __FASTRAM_END;
|
||||
__BAS_SIZE = 0;
|
||||
__BAS_LMA = __BAS_IN_RAM;
|
||||
/* BaS is already in RAM - no need to copy anything */
|
||||
__BAS_IN_RAM = __FASTRAM_END;
|
||||
__BAS_SIZE = 0;
|
||||
__BAS_LMA = __BAS_IN_RAM;
|
||||
#endif
|
||||
|
||||
/* Other flash components */
|
||||
__FIRETOS = 0xe0400000;
|
||||
__EMUTOS = EMUTOS_BASE_ADDRESS;
|
||||
__EMUTOS_SIZE = 0x00100000;
|
||||
/* Other flash components */
|
||||
__FIRETOS = 0xe0400000;
|
||||
__EMUTOS = EMUTOS_BASE_ADDRESS;
|
||||
__EMUTOS_SIZE = 0x00100000;
|
||||
|
||||
/* where FPGA data lives in flash */
|
||||
__FPGA_CONFIG = 0xe0700000;
|
||||
__FPGA_CONFIG_SIZE = 0x100000;
|
||||
/* where FPGA data lives in flash */
|
||||
__FPGA_CONFIG = 0xe0700000;
|
||||
__FPGA_CONFIG_SIZE = 0x100000;
|
||||
|
||||
/* VIDEO RAM BASIS */
|
||||
__VRAM = 0x60000000;
|
||||
/* VIDEO RAM BASIS */
|
||||
__VRAM = 0x60000000;
|
||||
|
||||
/* Memory mapped registers */
|
||||
__MBAR = 0xFF000000;
|
||||
/* Memory mapped registers */
|
||||
__MBAR = 0xFF000000;
|
||||
|
||||
/* 32KB on-chip System SRAM */
|
||||
__SYS_SRAM = __MBAR + 0x10000;
|
||||
__SYS_SRAM_SIZE = 0x00008000;
|
||||
/* 32KB on-chip System SRAM */
|
||||
__SYS_SRAM = __MBAR + 0x10000;
|
||||
__SYS_SRAM_SIZE = 0x00008000;
|
||||
|
||||
/* MMU memory mapped registers */
|
||||
__MMUBAR = 0xFF040000;
|
||||
/* MMU memory mapped registers */
|
||||
__MMUBAR = 0xFF040000;
|
||||
|
||||
/*
|
||||
* 4KB on-chip Core SRAM0: -> exception table
|
||||
*/
|
||||
__RAMBAR0 = 0xFF100000;
|
||||
__RAMBAR0_SIZE = 0x00001000;
|
||||
/*
|
||||
* 4KB on-chip Core SRAM0: -> exception table
|
||||
*/
|
||||
__RAMBAR0 = 0xFF100000;
|
||||
__RAMBAR0_SIZE = 0x00001000;
|
||||
|
||||
/* 4KB on-chip Core SRAM1 */
|
||||
__RAMBAR1 = 0xFF101000;
|
||||
__RAMBAR1_SIZE = 0x00001000;
|
||||
__SUP_SP = __RAMBAR1 + __RAMBAR1_SIZE - 4;
|
||||
/* 4KB on-chip Core SRAM1 */
|
||||
__RAMBAR1 = 0xFF101000;
|
||||
__RAMBAR1_SIZE = 0x00001000;
|
||||
__SUP_SP = __RAMBAR1 + __RAMBAR1_SIZE - 4;
|
||||
|
||||
/*
|
||||
* this flag (if 1) indicates that FPGA configuration has been loaded through JTAG
|
||||
* and shouldn't be overwritten on boot
|
||||
*/
|
||||
__FPGA_JTAG_LOADED = __RAMBAR1;
|
||||
/* system variables */
|
||||
/*
|
||||
* this flag (if 1) indicates that FPGA configuration has been loaded through JTAG
|
||||
* and shouldn't be overwritten on boot
|
||||
*/
|
||||
__FPGA_JTAG_LOADED = __RAMBAR1;
|
||||
__FPGA_JTAG_VALID = __FPGA_JTAG_LOADED + 4;
|
||||
|
||||
/* RAMBAR0 0 to 0x7FF -> exception vectors */
|
||||
_rt_mod = __RAMBAR0 + 0x800;
|
||||
_rt_ssp = __RAMBAR0 + 0x804;
|
||||
_rt_usp = __RAMBAR0 + 0x808;
|
||||
_rt_vbr = __RAMBAR0 + 0x80C; /* (8)01 */
|
||||
_rt_cacr = __RAMBAR0 + 0x810; /* 002 */
|
||||
_rt_asid = __RAMBAR0 + 0x814; /* 003 */
|
||||
_rt_acr0 = __RAMBAR0 + 0x818; /* 004 */
|
||||
_rt_acr1 = __RAMBAR0 + 0x81c; /* 005 */
|
||||
_rt_acr2 = __RAMBAR0 + 0x820; /* 006 */
|
||||
_rt_acr3 = __RAMBAR0 + 0x824; /* 007 */
|
||||
_rt_mmubar = __RAMBAR0 + 0x828; /* 008 */
|
||||
_rt_sr = __RAMBAR0 + 0x82c;
|
||||
_d0_save = __RAMBAR0 + 0x830;
|
||||
_a7_save = __RAMBAR0 + 0x834;
|
||||
_video_tlb = __RAMBAR0 + 0x838;
|
||||
_video_sbt = __RAMBAR0 + 0x83C;
|
||||
_rt_mbar = __RAMBAR0 + 0x844; /* (c)0f */
|
||||
/* system variables */
|
||||
|
||||
/* RAMBAR0 0 to 0x7FF -> exception vectors */
|
||||
_rt_mod = __RAMBAR0 + 0x800;
|
||||
_rt_ssp = __RAMBAR0 + 0x804;
|
||||
_rt_usp = __RAMBAR0 + 0x808;
|
||||
_rt_vbr = __RAMBAR0 + 0x80C; /* (8)01 */
|
||||
_rt_cacr = __RAMBAR0 + 0x810; /* 002 */
|
||||
_rt_asid = __RAMBAR0 + 0x814; /* 003 */
|
||||
_rt_acr0 = __RAMBAR0 + 0x818; /* 004 */
|
||||
_rt_acr1 = __RAMBAR0 + 0x81c; /* 005 */
|
||||
_rt_acr2 = __RAMBAR0 + 0x820; /* 006 */
|
||||
_rt_acr3 = __RAMBAR0 + 0x824; /* 007 */
|
||||
_rt_mmubar = __RAMBAR0 + 0x828; /* 008 */
|
||||
_rt_sr = __RAMBAR0 + 0x82c;
|
||||
_d0_save = __RAMBAR0 + 0x830;
|
||||
_a7_save = __RAMBAR0 + 0x834;
|
||||
_video_tlb = __RAMBAR0 + 0x838;
|
||||
_video_sbt = __RAMBAR0 + 0x83C;
|
||||
_rt_mbar = __RAMBAR0 + 0x844; /* (c)0f */
|
||||
|
||||
}
|
||||
|
||||
281
if/driver_vec.c
281
if/driver_vec.c
@@ -23,21 +23,21 @@
|
||||
* Author: Markus Fröschle
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <bas_types.h>
|
||||
#include "version.h"
|
||||
#include "xhdi_sd.h"
|
||||
#include "dma.h"
|
||||
#include "driver_vec.h"
|
||||
#include "driver_mem.h"
|
||||
#include "pci.h"
|
||||
#include "mmu.h"
|
||||
|
||||
/*
|
||||
* driver interface struct for the SD card BaS driver
|
||||
*/
|
||||
static struct xhdi_driver_interface xhdi_call_interface =
|
||||
static struct xhdi_driver_interface xhdi_call_interface =
|
||||
{
|
||||
xhdi_call
|
||||
xhdi_call
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -47,79 +47,81 @@ static struct xhdi_driver_interface xhdi_call_interface =
|
||||
*/
|
||||
static struct dma_driver_interface dma_interface =
|
||||
{
|
||||
.version = 0x0101,
|
||||
.magic = 0x444d4143, /* 'DMAC' */
|
||||
.dma_set_initiator = dma_set_initiator,
|
||||
.dma_get_initiator = dma_get_initiator,
|
||||
.dma_free_initiator = dma_free_initiator,
|
||||
.dma_set_channel = dma_set_channel,
|
||||
.dma_get_channel = dma_get_channel,
|
||||
.dma_free_channel = dma_free_channel,
|
||||
.dma_clear_channel = dma_clear_channel,
|
||||
.MCD_startDma = MCD_startDma,
|
||||
.MCD_dmaStatus = MCD_dmaStatus,
|
||||
.MCD_XferProgrQuery = MCD_XferProgrQuery,
|
||||
.MCD_killDma = MCD_killDma,
|
||||
.MCD_continDma = MCD_continDma,
|
||||
.MCD_pauseDma = MCD_pauseDma,
|
||||
.MCD_resumeDma = MCD_resumeDma,
|
||||
.MCD_csumQuery = MCD_csumQuery,
|
||||
.dma_malloc = driver_mem_alloc,
|
||||
.dma_free = driver_mem_free
|
||||
.version = 0x0101,
|
||||
.magic = 0x444d4143, /* 'DMAC' */
|
||||
.dma_set_initiator = dma_set_initiator,
|
||||
.dma_get_initiator = dma_get_initiator,
|
||||
.dma_free_initiator = dma_free_initiator,
|
||||
.dma_set_channel = dma_set_channel,
|
||||
.dma_get_channel = dma_get_channel,
|
||||
.dma_free_channel = dma_free_channel,
|
||||
.dma_clear_channel = dma_clear_channel,
|
||||
.MCD_startDma = (int (*)(long, int8_t *, unsigned int, int8_t *, unsigned int,
|
||||
unsigned int, unsigned int, unsigned int, int,
|
||||
unsigned int, unsigned int)) MCD_startDma,
|
||||
.MCD_dmaStatus = (int32_t (*)(int32_t)) MCD_dmaStatus,
|
||||
.MCD_XferProgrQuery = (int32_t (*)(int32_t, MCD_XferProg *)) MCD_XferProgrQuery,
|
||||
.MCD_killDma = (int32_t (*)(int32_t)) MCD_killDma,
|
||||
.MCD_continDma = (int32_t (*)(int32_t)) MCD_continDma,
|
||||
.MCD_pauseDma = (int32_t (*)(int32_t)) MCD_pauseDma,
|
||||
.MCD_resumeDma = (int32_t (*)(int32_t)) MCD_resumeDma,
|
||||
.MCD_csumQuery = (int32_t (*)(int32_t, uint32_t *)) MCD_csumQuery,
|
||||
.dma_malloc = driver_mem_alloc,
|
||||
.dma_free = driver_mem_free
|
||||
};
|
||||
|
||||
extern const struct fb_info *info_fb;
|
||||
extern struct fb_info *info_fb;
|
||||
|
||||
/*
|
||||
* driver interface struct for the PCI_BIOS BaS driver
|
||||
*/
|
||||
static struct pci_bios_interface pci_interface =
|
||||
static struct pci_bios_interface pci_interface =
|
||||
{
|
||||
.subjar = 0,
|
||||
.version = 0x00010000,
|
||||
.find_pci_device = wrapper_find_pci_device,
|
||||
.find_pci_classcode = wrapper_find_pci_classcode,
|
||||
.read_config_byte = wrapper_read_config_byte,
|
||||
.read_config_word = wrapper_read_config_word,
|
||||
.read_config_longword = wrapper_read_config_longword,
|
||||
.fast_read_config_byte = wrapper_fast_read_config_byte,
|
||||
.fast_read_config_word = wrapper_fast_read_config_word,
|
||||
.fast_read_config_longword = wrapper_fast_read_config_longword,
|
||||
.write_config_byte = wrapper_write_config_byte,
|
||||
.write_config_word = wrapper_write_config_word,
|
||||
.write_config_longword = wrapper_write_config_longword,
|
||||
.hook_interrupt = wrapper_hook_interrupt,
|
||||
.unhook_interrupt = wrapper_unhook_interrupt,
|
||||
.special_cycle = wrapper_special_cycle,
|
||||
.get_routing = wrapper_get_routing,
|
||||
.set_interrupt = wrapper_set_interrupt,
|
||||
.get_resource = wrapper_get_resource,
|
||||
.get_card_used = wrapper_get_card_used,
|
||||
.set_card_used = wrapper_set_card_used,
|
||||
.read_mem_byte = wrapper_read_mem_byte,
|
||||
.read_mem_word = wrapper_read_mem_word,
|
||||
.read_mem_longword = wrapper_read_mem_longword,
|
||||
.fast_read_mem_byte = wrapper_fast_read_mem_byte,
|
||||
.fast_read_mem_word = wrapper_fast_read_mem_word,
|
||||
.fast_read_mem_longword = wrapper_fast_read_mem_longword,
|
||||
.write_mem_byte = wrapper_write_mem_byte,
|
||||
.write_mem_word = wrapper_write_mem_word,
|
||||
.write_mem_longword = wrapper_write_mem_longword,
|
||||
.read_io_byte = wrapper_read_io_byte,
|
||||
.read_io_word = wrapper_read_io_word,
|
||||
.read_io_longword = wrapper_read_io_longword,
|
||||
.fast_read_io_byte = wrapper_fast_read_io_byte,
|
||||
.fast_read_io_word = wrapper_fast_read_io_word,
|
||||
.fast_read_io_longword = wrapper_fast_read_io_longword,
|
||||
.write_io_byte = wrapper_write_io_byte,
|
||||
.write_io_word = wrapper_write_io_word,
|
||||
.write_io_longword = wrapper_write_io_longword,
|
||||
.get_machine_id = wrapper_get_machine_id,
|
||||
.get_pagesize = wrapper_get_pagesize,
|
||||
.virt_to_bus = wrapper_virt_to_bus,
|
||||
.bus_to_virt = wrapper_bus_to_virt,
|
||||
.virt_to_phys = wrapper_virt_to_phys,
|
||||
.phys_to_virt = wrapper_phys_to_virt,
|
||||
.subjar = 0,
|
||||
.version = 0x00010000,
|
||||
.find_pci_device = wrapper_find_pci_device,
|
||||
.find_pci_classcode = wrapper_find_pci_classcode,
|
||||
.read_config_byte = wrapper_read_config_byte,
|
||||
.read_config_word = wrapper_read_config_word,
|
||||
.read_config_longword = wrapper_read_config_longword,
|
||||
.fast_read_config_byte = wrapper_fast_read_config_byte,
|
||||
.fast_read_config_word = wrapper_fast_read_config_word,
|
||||
.fast_read_config_longword = wrapper_fast_read_config_longword,
|
||||
.write_config_byte = wrapper_write_config_byte,
|
||||
.write_config_word = wrapper_write_config_word,
|
||||
.write_config_longword = wrapper_write_config_longword,
|
||||
.hook_interrupt = wrapper_hook_interrupt,
|
||||
.unhook_interrupt = wrapper_unhook_interrupt,
|
||||
.special_cycle = wrapper_special_cycle,
|
||||
.get_routing = wrapper_get_routing,
|
||||
.set_interrupt = wrapper_set_interrupt,
|
||||
.get_resource = wrapper_get_resource,
|
||||
.get_card_used = wrapper_get_card_used,
|
||||
.set_card_used = wrapper_set_card_used,
|
||||
.read_mem_byte = wrapper_read_mem_byte,
|
||||
.read_mem_word = wrapper_read_mem_word,
|
||||
.read_mem_longword = wrapper_read_mem_longword,
|
||||
.fast_read_mem_byte = wrapper_fast_read_mem_byte,
|
||||
.fast_read_mem_word = wrapper_fast_read_mem_word,
|
||||
.fast_read_mem_longword = wrapper_fast_read_mem_longword,
|
||||
.write_mem_byte = wrapper_write_mem_byte,
|
||||
.write_mem_word = wrapper_write_mem_word,
|
||||
.write_mem_longword = wrapper_write_mem_longword,
|
||||
.read_io_byte = wrapper_read_io_byte,
|
||||
.read_io_word = wrapper_read_io_word,
|
||||
.read_io_longword = wrapper_read_io_longword,
|
||||
.fast_read_io_byte = wrapper_fast_read_io_byte,
|
||||
.fast_read_io_word = wrapper_fast_read_io_word,
|
||||
.fast_read_io_longword = wrapper_fast_read_io_longword,
|
||||
.write_io_byte = wrapper_write_io_byte,
|
||||
.write_io_word = wrapper_write_io_word,
|
||||
.write_io_longword = wrapper_write_io_longword,
|
||||
.get_machine_id = wrapper_get_machine_id,
|
||||
.get_pagesize = wrapper_get_pagesize,
|
||||
.virt_to_bus = wrapper_virt_to_bus,
|
||||
.bus_to_virt = wrapper_bus_to_virt,
|
||||
.virt_to_phys = wrapper_virt_to_phys,
|
||||
.phys_to_virt = wrapper_phys_to_virt,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -127,69 +129,112 @@ static struct pci_bios_interface pci_interface =
|
||||
*/
|
||||
static struct framebuffer_driver_interface framebuffer_interface =
|
||||
{
|
||||
.framebuffer_info = &info_fb
|
||||
.framebuffer_info = &info_fb
|
||||
};
|
||||
|
||||
|
||||
static struct generic_interface interfaces[] =
|
||||
{
|
||||
{
|
||||
/* BaS SD-card driver interface */
|
||||
{
|
||||
/* BaS SD-card driver interface */
|
||||
|
||||
.type = XHDI_DRIVER,
|
||||
.name = "SDCARD",
|
||||
.description = "BaS SD Card driver",
|
||||
.version = 0,
|
||||
.revision = 1,
|
||||
.interface.xhdi = &xhdi_call_interface
|
||||
},
|
||||
{
|
||||
.type = MCD_DRIVER,
|
||||
.name = "MCDDMA",
|
||||
.description = "BaS Multichannel DMA driver",
|
||||
.version = 0,
|
||||
.revision = 1,
|
||||
.interface.dma = &dma_interface,
|
||||
},
|
||||
{
|
||||
.type = VIDEO_DRIVER,
|
||||
.name = "RADEON",
|
||||
.description = "BaS RADEON framebuffer driver",
|
||||
.version = 0,
|
||||
.revision = 1,
|
||||
.interface.fb = &framebuffer_interface,
|
||||
},
|
||||
{
|
||||
.type = PCI_DRIVER,
|
||||
.name = "PCI",
|
||||
.description = "BaS PCI_BIOS driver",
|
||||
.version = 0,
|
||||
.revision = 1,
|
||||
.interface.pci = &pci_interface,
|
||||
},
|
||||
/* insert new drivers here */
|
||||
.type = XHDI_DRIVER,
|
||||
.name = "SDCARD",
|
||||
.description = "BaS SD Card driver",
|
||||
.version = 0,
|
||||
.revision = 1,
|
||||
.interface.xhdi = &xhdi_call_interface
|
||||
},
|
||||
{
|
||||
.type = MCD_DRIVER,
|
||||
.name = "MCDDMA",
|
||||
.description = "BaS Multichannel DMA driver",
|
||||
.version = 0,
|
||||
.revision = 1,
|
||||
.interface.dma = &dma_interface,
|
||||
},
|
||||
{
|
||||
.type = VIDEO_DRIVER,
|
||||
.name = "RADEON",
|
||||
.description = "BaS RADEON framebuffer driver",
|
||||
.version = 0,
|
||||
.revision = 1,
|
||||
.interface.fb = &framebuffer_interface,
|
||||
},
|
||||
{
|
||||
.type = PCI_DRIVER,
|
||||
.name = "PCI",
|
||||
.description = "BaS PCI_BIOS driver",
|
||||
.version = 0,
|
||||
.revision = 1,
|
||||
.interface.pci = &pci_interface,
|
||||
},
|
||||
{
|
||||
.type = MMU_DRIVER,
|
||||
.name = "MMU",
|
||||
.description = "BaS MMU driver",
|
||||
.version = 0,
|
||||
.revision = 1,
|
||||
.interface.mmu = NULL,
|
||||
},
|
||||
/* insert new drivers here */
|
||||
|
||||
{
|
||||
.type = END_OF_DRIVERS
|
||||
}
|
||||
{
|
||||
.type = END_OF_DRIVERS
|
||||
}
|
||||
};
|
||||
|
||||
extern void remove_handler(void); /* forward declaration */
|
||||
|
||||
/*
|
||||
* this is the driver table we expose to the OS
|
||||
*/
|
||||
static struct driver_table bas_drivers =
|
||||
{
|
||||
.bas_version = MAJOR_VERSION,
|
||||
.bas_revision = MINOR_VERSION,
|
||||
.remove_handler = NULL,
|
||||
.interfaces = { interfaces }
|
||||
.bas_version = MAJOR_VERSION,
|
||||
.bas_revision = MINOR_VERSION,
|
||||
.remove_handler = remove_handler,
|
||||
.interfaces = interfaces
|
||||
};
|
||||
|
||||
void remove_handler(void)
|
||||
{
|
||||
extern void std_exc_vec(void);
|
||||
uint32_t *trap_0_vector = (uint32_t *) 0x80;
|
||||
|
||||
*trap_0_vector = (uint32_t) std_exc_vec;
|
||||
}
|
||||
|
||||
void __attribute__((interrupt)) get_bas_drivers(void)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"move.l #%[drivers],d0\n\t"
|
||||
: /* no output */
|
||||
: [drivers] "o" (bas_drivers) /* input */
|
||||
: /* clobber */
|
||||
);
|
||||
__asm__ __volatile(
|
||||
/*
|
||||
* sp should now point to the next instruction after the trap
|
||||
* The trap itself is 2 bytes, the four bytes before that must
|
||||
* read '_BAS' or we are not meant by this call
|
||||
*/
|
||||
" move.l a0,-(sp) \n\t" // save registers
|
||||
" move.l d0,-(sp) \n\t"
|
||||
" move.l 12(sp),a0 \n\t" // get return address
|
||||
" move.l -6(a0),d0 \n\t" //
|
||||
" cmp.l #0x5f424153,d0 \n\t" // is it '_BAS'?
|
||||
" beq fetch_drivers \n\t" // yes
|
||||
/*
|
||||
* This seems indeed a "normal" trap #0. Better pass control to "normal" trap #0 processing
|
||||
* If trap #0 isn't set to something sensible, we'll probably crash here, but this must be
|
||||
* prevented on the caller side.
|
||||
*/
|
||||
" move.l (sp)+,d0 \n\t" // restore registers
|
||||
" move.l (sp)+,a0 \n\t"
|
||||
" move.l 0x80,-(sp) \n\t" // fetch vector
|
||||
" rts \n\t" // and jump through it
|
||||
|
||||
"fetch_drivers: \n\t"
|
||||
" move.l #%[drivers],d0 \n\t" // return driver struct in d0
|
||||
" addq.l #4,sp \n\t" // adjust stack
|
||||
" move.l (sp)+,a0 \n\t" // restore register
|
||||
: /* no output */
|
||||
: [drivers] "o" (bas_drivers) /* input */
|
||||
: /* clobber */
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,52 +31,53 @@
|
||||
|
||||
enum driver_type
|
||||
{
|
||||
// BLOCKDEV_DRIVER,
|
||||
// CHARDEV_DRIVER,
|
||||
XHDI_DRIVER,
|
||||
MCD_DRIVER,
|
||||
VIDEO_DRIVER,
|
||||
PCI_DRIVER,
|
||||
END_OF_DRIVERS, /* marks end of driver list */
|
||||
BLOCKDEV_DRIVER,
|
||||
CHARDEV_DRIVER,
|
||||
XHDI_DRIVER,
|
||||
MCD_DRIVER,
|
||||
VIDEO_DRIVER,
|
||||
PCI_DRIVER,
|
||||
MMU_DRIVER,
|
||||
END_OF_DRIVERS = 0xffffffff /* marks end of driver list */
|
||||
};
|
||||
|
||||
struct generic_driver_interface
|
||||
{
|
||||
uint32_t (*init)(void);
|
||||
uint32_t (*read)(void *buf, size_t count);
|
||||
uint32_t (*write)(const void *buf, size_t count);
|
||||
uint32_t (*ioctl)(uint32_t request, ...);
|
||||
uint32_t (*init)(void);
|
||||
uint32_t (*read)(void *buf, size_t count);
|
||||
uint32_t (*write)(const void *buf, size_t count);
|
||||
uint32_t (*ioctl)(uint32_t request, ...);
|
||||
};
|
||||
|
||||
struct dma_driver_interface
|
||||
{
|
||||
int32_t version;
|
||||
int32_t magic;
|
||||
int (*dma_set_initiator)(int initiator);
|
||||
uint32_t (*dma_get_initiator)(int requestor);
|
||||
void (*dma_free_initiator)(int requestor);
|
||||
int (*dma_set_channel)(int requestor, void (*handler)(void));
|
||||
int (*dma_get_channel)(int requestor);
|
||||
void (*dma_free_channel)(int requestor);
|
||||
void (*dma_clear_channel)(int channel);
|
||||
int (*MCD_startDma)(long channel,
|
||||
int8_t *srcAddr, unsigned int srcIncr, int8_t *destAddr, unsigned int destIncr,
|
||||
unsigned int dmaSize, unsigned int xferSize, unsigned int initiator, int priority,
|
||||
unsigned int flags, unsigned int funcDesc);
|
||||
int32_t (*MCD_dmaStatus)(int32_t channel);
|
||||
int32_t (*MCD_XferProgrQuery)(int32_t channel, MCD_XferProg *progRep);
|
||||
int32_t (*MCD_killDma)(int32_t channel);
|
||||
int32_t (*MCD_continDma)(int32_t channel);
|
||||
int32_t (*MCD_pauseDma)(int32_t channel);
|
||||
int32_t (*MCD_resumeDma)(int32_t channel);
|
||||
int32_t (*MCD_csumQuery)(int32_t channel, uint32_t *csum);
|
||||
void *(*dma_malloc)(uint32_t amount);
|
||||
int32_t (*dma_free)(void *addr);
|
||||
int32_t version;
|
||||
int32_t magic;
|
||||
int (*dma_set_initiator)(int initiator);
|
||||
uint32_t (*dma_get_initiator)(int requestor);
|
||||
void (*dma_free_initiator)(int requestor);
|
||||
int (*dma_set_channel)(int requestor, void (*handler)(void));
|
||||
int (*dma_get_channel)(int requestor);
|
||||
void (*dma_free_channel)(int requestor);
|
||||
void (*dma_clear_channel)(int channel);
|
||||
int (*MCD_startDma)(long channel,
|
||||
int8_t *srcAddr, unsigned int srcIncr, int8_t *destAddr, unsigned int destIncr,
|
||||
unsigned int dmaSize, unsigned int xferSize, unsigned int initiator, int priority,
|
||||
unsigned int flags, unsigned int funcDesc);
|
||||
int32_t (*MCD_dmaStatus)(int32_t channel);
|
||||
int32_t (*MCD_XferProgrQuery)(int32_t channel, MCD_XferProg *progRep);
|
||||
int32_t (*MCD_killDma)(int32_t channel);
|
||||
int32_t (*MCD_continDma)(int32_t channel);
|
||||
int32_t (*MCD_pauseDma)(int32_t channel);
|
||||
int32_t (*MCD_resumeDma)(int32_t channel);
|
||||
int32_t (*MCD_csumQuery)(int32_t channel, uint32_t *csum);
|
||||
void *(*dma_malloc)(uint32_t amount);
|
||||
int32_t (*dma_free)(void *addr);
|
||||
};
|
||||
|
||||
|
||||
struct xhdi_driver_interface
|
||||
{
|
||||
uint32_t (*xhdivec)();
|
||||
uint32_t (*xhdivec)();
|
||||
};
|
||||
|
||||
/* Interpretation of offset for color fields: All offsets are from the right,
|
||||
@@ -90,7 +91,7 @@ struct fb_bitfield
|
||||
unsigned long offset; /* beginning of bitfield */
|
||||
unsigned long length; /* length of bitfield */
|
||||
unsigned long msb_right; /* != 0 : Most significant bit is */
|
||||
/* right */
|
||||
/* right */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -103,19 +104,19 @@ struct fb_var_screeninfo
|
||||
unsigned long xres_virtual; /* virtual resolution */
|
||||
unsigned long yres_virtual;
|
||||
unsigned long xoffset; /* offset from virtual to visible */
|
||||
unsigned long yoffset; /* resolution */
|
||||
unsigned long yoffset; /* resolution */
|
||||
|
||||
unsigned long bits_per_pixel; /* guess what */
|
||||
unsigned long bits_per_pixel; /* guess what */
|
||||
unsigned long grayscale; /* != 0 Graylevels instead of colors */
|
||||
|
||||
struct fb_bitfield red; /* bitfield in fb mem if true color, */
|
||||
struct fb_bitfield green; /* else only length is significant */
|
||||
struct fb_bitfield blue;
|
||||
struct fb_bitfield transp; /* transparency */
|
||||
struct fb_bitfield transp; /* transparency */
|
||||
|
||||
unsigned long nonstd; /* != 0 Non standard pixel format */
|
||||
|
||||
unsigned long activate; /* see FB_ACTIVATE_* */
|
||||
unsigned long activate; /* see FB_ACTIVATE_* */
|
||||
|
||||
unsigned long height; /* height of picture in mm */
|
||||
unsigned long width; /* width of picture in mm */
|
||||
@@ -130,7 +131,7 @@ struct fb_var_screeninfo
|
||||
unsigned long lower_margin;
|
||||
unsigned long hsync_len; /* length of horizontal sync */
|
||||
unsigned long vsync_len; /* length of vertical sync */
|
||||
unsigned long sync; /* see FB_SYNC_* */
|
||||
unsigned long sync; /* see FB_SYNC_* */
|
||||
unsigned long vmode; /* see FB_VMODE_* */
|
||||
unsigned long rotate; /* angle we rotate counter clockwise */
|
||||
unsigned long refresh;
|
||||
@@ -143,7 +144,7 @@ struct fb_fix_screeninfo
|
||||
unsigned long smem_start; /* Start of frame buffer mem */
|
||||
/* (physical address) */
|
||||
unsigned long smem_len; /* Length of frame buffer mem */
|
||||
unsigned long type; /* see FB_TYPE_* */
|
||||
unsigned long type; /* see FB_TYPE_* */
|
||||
unsigned long type_aux; /* Interleave for interleaved Planes */
|
||||
unsigned long visual; /* see FB_VISUAL_* */
|
||||
unsigned short xpanstep; /* zero if no hardware panning */
|
||||
@@ -160,7 +161,7 @@ struct fb_fix_screeninfo
|
||||
|
||||
struct fb_chroma
|
||||
{
|
||||
unsigned long redx; /* in fraction of 1024 */
|
||||
unsigned long redx; /* in fraction of 1024 */
|
||||
unsigned long greenx;
|
||||
unsigned long bluex;
|
||||
unsigned long whitex;
|
||||
@@ -203,87 +204,97 @@ struct fb_monspecs
|
||||
|
||||
struct framebuffer_driver_interface
|
||||
{
|
||||
struct fb_info **framebuffer_info; /* pointer to an fb_info struct (defined in include/fb.h) */
|
||||
struct fb_info **framebuffer_info; /* pointer to an fb_info struct (defined in include/fb.h) */
|
||||
};
|
||||
|
||||
struct pci_bios_interface {
|
||||
uint32_t subjar;
|
||||
uint32_t version;
|
||||
/* Although we declare this functions as standard gcc functions (cdecl),
|
||||
* they expect paramenters inside registers (fastcall) unsupported by gcc m68k.
|
||||
* Caller will take care of parameters passing convention.
|
||||
*/
|
||||
int32_t (*find_pci_device) (uint32_t id, uint16_t index);
|
||||
int32_t (*find_pci_classcode) (uint32_t class, uint16_t index);
|
||||
int32_t (*read_config_byte) (int32_t handle, uint16_t reg, uint8_t *address);
|
||||
int32_t (*read_config_word) (int32_t handle, uint16_t reg, uint16_t *address);
|
||||
int32_t (*read_config_longword) (int32_t handle, uint16_t reg, uint32_t *address);
|
||||
uint8_t (*fast_read_config_byte) (int32_t handle, uint16_t reg);
|
||||
uint16_t (*fast_read_config_word) (int32_t handle, uint16_t reg);
|
||||
uint32_t (*fast_read_config_longword) (int32_t handle, uint16_t reg);
|
||||
int32_t (*write_config_byte) (int32_t handle, uint16_t reg, uint16_t val);
|
||||
int32_t (*write_config_word) (int32_t handle, uint16_t reg, uint16_t val);
|
||||
int32_t (*write_config_longword) (int32_t handle, uint16_t reg, uint32_t val);
|
||||
int32_t (*hook_interrupt) (int32_t handle, uint32_t *routine, uint32_t *parameter);
|
||||
int32_t (*unhook_interrupt) (int32_t handle);
|
||||
int32_t (*special_cycle) (uint16_t bus, uint32_t data);
|
||||
int32_t (*get_routing) (int32_t handle);
|
||||
int32_t (*set_interrupt) (int32_t handle);
|
||||
int32_t (*get_resource) (int32_t handle);
|
||||
int32_t (*get_card_used) (int32_t handle, uint32_t *address);
|
||||
int32_t (*set_card_used) (int32_t handle, uint32_t *callback);
|
||||
int32_t (*read_mem_byte) (int32_t handle, uint32_t offset, uint8_t *address);
|
||||
int32_t (*read_mem_word) (int32_t handle, uint32_t offset, uint16_t *address);
|
||||
int32_t (*read_mem_longword) (int32_t handle, uint32_t offset, uint32_t *address);
|
||||
uint8_t (*fast_read_mem_byte) (int32_t handle, uint32_t offset);
|
||||
uint16_t (*fast_read_mem_word) (int32_t handle, uint32_t offset);
|
||||
uint32_t (*fast_read_mem_longword) (int32_t handle, uint32_t offset);
|
||||
int32_t (*write_mem_byte) (int32_t handle, uint32_t offset, uint16_t val);
|
||||
int32_t (*write_mem_word) (int32_t handle, uint32_t offset, uint16_t val);
|
||||
int32_t (*write_mem_longword) (int32_t handle, uint32_t offset, uint32_t val);
|
||||
int32_t (*read_io_byte) (int32_t handle, uint32_t offset, uint8_t *address);
|
||||
int32_t (*read_io_word) (int32_t handle, uint32_t offset, uint16_t *address);
|
||||
int32_t (*read_io_longword) (int32_t handle, uint32_t offset, uint32_t *address);
|
||||
uint8_t (*fast_read_io_byte) (int32_t handle, uint32_t offset);
|
||||
uint16_t (*fast_read_io_word) (int32_t handle, uint32_t offset);
|
||||
uint32_t (*fast_read_io_longword) (int32_t handle, uint32_t offset);
|
||||
int32_t (*write_io_byte) (int32_t handle, uint32_t offset, uint16_t val);
|
||||
int32_t (*write_io_word) (int32_t handle, uint32_t offset, uint16_t val);
|
||||
int32_t (*write_io_longword) (int32_t handle, uint32_t offset, uint32_t val);
|
||||
int32_t (*get_machine_id) (void);
|
||||
int32_t (*get_pagesize) (void);
|
||||
int32_t (*virt_to_bus) (int32_t handle, uint32_t address, PCI_CONV_ADR *pointer);
|
||||
int32_t (*bus_to_virt) (int32_t handle, uint32_t address, PCI_CONV_ADR *pointer);
|
||||
int32_t (*virt_to_phys) (uint32_t address, PCI_CONV_ADR *pointer);
|
||||
int32_t (*phys_to_virt) (uint32_t address, PCI_CONV_ADR *pointer);
|
||||
struct pci_bios_interface
|
||||
{
|
||||
uint32_t subjar;
|
||||
uint32_t version;
|
||||
/* Although we declare this functions as standard gcc functions (cdecl),
|
||||
* they expect paramenters inside registers (fastcall) unsupported by gcc m68k.
|
||||
* Caller will take care of parameters passing convention.
|
||||
*/
|
||||
int32_t (*find_pci_device) (uint32_t id, uint16_t index);
|
||||
int32_t (*find_pci_classcode) (uint32_t class, uint16_t index);
|
||||
int32_t (*read_config_byte) (int32_t handle, uint16_t reg, uint8_t *address);
|
||||
int32_t (*read_config_word) (int32_t handle, uint16_t reg, uint16_t *address);
|
||||
int32_t (*read_config_longword) (int32_t handle, uint16_t reg, uint32_t *address);
|
||||
uint8_t (*fast_read_config_byte) (int32_t handle, uint16_t reg);
|
||||
uint16_t (*fast_read_config_word) (int32_t handle, uint16_t reg);
|
||||
uint32_t (*fast_read_config_longword) (int32_t handle, uint16_t reg);
|
||||
int32_t (*write_config_byte) (int32_t handle, uint16_t reg, uint16_t val);
|
||||
int32_t (*write_config_word) (int32_t handle, uint16_t reg, uint16_t val);
|
||||
int32_t (*write_config_longword) (int32_t handle, uint16_t reg, uint32_t val);
|
||||
int32_t (*hook_interrupt) (int32_t handle, uint32_t *routine, uint32_t *parameter);
|
||||
int32_t (*unhook_interrupt) (int32_t handle);
|
||||
int32_t (*special_cycle) (uint16_t bus, uint32_t data);
|
||||
int32_t (*get_routing) (int32_t handle);
|
||||
int32_t (*set_interrupt) (int32_t handle);
|
||||
int32_t (*get_resource) (int32_t handle);
|
||||
int32_t (*get_card_used) (int32_t handle, uint32_t *address);
|
||||
int32_t (*set_card_used) (int32_t handle, uint32_t *callback);
|
||||
int32_t (*read_mem_byte) (int32_t handle, uint32_t offset, uint8_t *address);
|
||||
int32_t (*read_mem_word) (int32_t handle, uint32_t offset, uint16_t *address);
|
||||
int32_t (*read_mem_longword) (int32_t handle, uint32_t offset, uint32_t *address);
|
||||
uint8_t (*fast_read_mem_byte) (int32_t handle, uint32_t offset);
|
||||
uint16_t (*fast_read_mem_word) (int32_t handle, uint32_t offset);
|
||||
uint32_t (*fast_read_mem_longword) (int32_t handle, uint32_t offset);
|
||||
int32_t (*write_mem_byte) (int32_t handle, uint32_t offset, uint16_t val);
|
||||
int32_t (*write_mem_word) (int32_t handle, uint32_t offset, uint16_t val);
|
||||
int32_t (*write_mem_longword) (int32_t handle, uint32_t offset, uint32_t val);
|
||||
int32_t (*read_io_byte) (int32_t handle, uint32_t offset, uint8_t *address);
|
||||
int32_t (*read_io_word) (int32_t handle, uint32_t offset, uint16_t *address);
|
||||
int32_t (*read_io_longword) (int32_t handle, uint32_t offset, uint32_t *address);
|
||||
uint8_t (*fast_read_io_byte) (int32_t handle, uint32_t offset);
|
||||
uint16_t (*fast_read_io_word) (int32_t handle, uint32_t offset);
|
||||
uint32_t (*fast_read_io_longword) (int32_t handle, uint32_t offset);
|
||||
int32_t (*write_io_byte) (int32_t handle, uint32_t offset, uint16_t val);
|
||||
int32_t (*write_io_word) (int32_t handle, uint32_t offset, uint16_t val);
|
||||
int32_t (*write_io_longword) (int32_t handle, uint32_t offset, uint32_t val);
|
||||
int32_t (*get_machine_id) (void);
|
||||
int32_t (*get_pagesize) (void);
|
||||
int32_t (*virt_to_bus) (int32_t handle, uint32_t address, PCI_CONV_ADR *pointer);
|
||||
int32_t (*bus_to_virt) (int32_t handle, uint32_t address, PCI_CONV_ADR *pointer);
|
||||
int32_t (*virt_to_phys) (uint32_t address, PCI_CONV_ADR *pointer);
|
||||
int32_t (*phys_to_virt) (uint32_t address, PCI_CONV_ADR *pointer);
|
||||
// int32_t reserved[2];
|
||||
};
|
||||
|
||||
struct mmu_driver_interface
|
||||
{
|
||||
int32_t (*map_page_locked)(uint32_t address, uint32_t length, int asid);
|
||||
int32_t (*unlock_page)(uint32_t address, uint32_t length, int asid);
|
||||
int32_t (*report_locked_pages)(uint32_t *num_itlb, uint32_t *num_dtlb);
|
||||
uint32_t (*report_pagesize)(void);
|
||||
};
|
||||
|
||||
union interface
|
||||
{
|
||||
struct generic_driver_interface *gdi;
|
||||
struct xhdi_driver_interface *xhdi;
|
||||
struct dma_driver_interface *dma;
|
||||
struct framebuffer_driver_interface *fb;
|
||||
struct pci_bios_interface *pci;
|
||||
struct generic_driver_interface *gdi;
|
||||
struct xhdi_driver_interface *xhdi;
|
||||
struct dma_driver_interface *dma;
|
||||
struct framebuffer_driver_interface *fb;
|
||||
struct pci_bios_interface *pci;
|
||||
struct mmu_driver_interface *mmu;
|
||||
};
|
||||
|
||||
struct generic_interface
|
||||
{
|
||||
enum driver_type type;
|
||||
char name[16];
|
||||
char description[64];
|
||||
int version;
|
||||
int revision;
|
||||
union interface interface;
|
||||
enum driver_type type;
|
||||
char name[16];
|
||||
char description[64];
|
||||
int version;
|
||||
int revision;
|
||||
union interface interface;
|
||||
};
|
||||
|
||||
struct driver_table
|
||||
{
|
||||
uint32_t bas_version;
|
||||
uint32_t bas_revision;
|
||||
uint32_t (*remove_handler)(); /* calling this will disable the BaS' hook into trap #0 */
|
||||
struct generic_interface *interfaces[];
|
||||
uint32_t bas_version;
|
||||
uint32_t bas_revision;
|
||||
void (*remove_handler)(void); /* calling this will disable the BaS' hook into trap #0 */
|
||||
struct generic_interface *interfaces;
|
||||
};
|
||||
|
||||
|
||||
|
||||
194
net/fecbd.c
194
net/fecbd.c
@@ -11,7 +11,7 @@
|
||||
#include "bas_printf.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#define DBG_FECBD
|
||||
//#define DBG_FECBD
|
||||
#ifdef DBG_FECBD
|
||||
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0)
|
||||
#else
|
||||
@@ -62,94 +62,94 @@ static int iRxbd;
|
||||
*/
|
||||
void fecbd_init(uint8_t ch)
|
||||
{
|
||||
NBUF *nbuf;
|
||||
int i;
|
||||
NBUF *nbuf;
|
||||
int i;
|
||||
|
||||
dbg("\r\n");
|
||||
|
||||
/*
|
||||
* Align Buffer Descriptors to 4-byte boundary
|
||||
*/
|
||||
RxBD = (FECBD *)(((int) unaligned_bds + 3) & 0xFFFFFFFC);
|
||||
TxBD = (FECBD *)((int) RxBD + (sizeof(FECBD) * 2 * NRXBD));
|
||||
/*
|
||||
* Align Buffer Descriptors to 4-byte boundary
|
||||
*/
|
||||
RxBD = (FECBD *)(((int) unaligned_bds + 3) & 0xFFFFFFFC);
|
||||
TxBD = (FECBD *)((int) RxBD + (sizeof(FECBD) * 2 * NRXBD));
|
||||
|
||||
dbg("initialise RX buffer descriptor ring\r\n");
|
||||
|
||||
/*
|
||||
* Initialize the Rx Buffer Descriptor ring
|
||||
*/
|
||||
for (i = 0; i < NRXBD; ++i)
|
||||
{
|
||||
/* Grab a network buffer from the free list */
|
||||
nbuf = nbuf_alloc();
|
||||
if (nbuf == NULL)
|
||||
{
|
||||
/*
|
||||
* Initialize the Rx Buffer Descriptor ring
|
||||
*/
|
||||
for (i = 0; i < NRXBD; ++i)
|
||||
{
|
||||
/* Grab a network buffer from the free list */
|
||||
nbuf = nbuf_alloc();
|
||||
if (nbuf == NULL)
|
||||
{
|
||||
dbg("could not allocate network buffer\r\n");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the BD */
|
||||
RxBD(ch,i).status = RX_BD_E | RX_BD_INTERRUPT;
|
||||
RxBD(ch,i).length = RX_BUF_SZ;
|
||||
RxBD(ch,i).data = nbuf->data;
|
||||
/* Initialize the BD */
|
||||
RxBD(ch,i).status = RX_BD_E | RX_BD_INTERRUPT;
|
||||
RxBD(ch,i).length = RX_BUF_SZ;
|
||||
RxBD(ch,i).data = nbuf->data;
|
||||
|
||||
/* Add the network buffer to the Rx queue */
|
||||
nbuf_add(NBUF_RX_RING, nbuf);
|
||||
}
|
||||
/* Add the network buffer to the Rx queue */
|
||||
nbuf_add(NBUF_RX_RING, nbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the WRAP bit on the last one
|
||||
*/
|
||||
RxBD(ch, i - 1).status |= RX_BD_W;
|
||||
/*
|
||||
* Set the WRAP bit on the last one
|
||||
*/
|
||||
RxBD(ch, i - 1).status |= RX_BD_W;
|
||||
|
||||
dbg("initialise TX buffer descriptor ring\r\n");
|
||||
|
||||
/*
|
||||
* Initialize the Tx Buffer Descriptor ring
|
||||
*/
|
||||
for (i = 0; i < NTXBD; ++i)
|
||||
{
|
||||
TxBD(ch, i).status = TX_BD_INTERRUPT;
|
||||
TxBD(ch, i).length = 0;
|
||||
TxBD(ch, i).data = NULL;
|
||||
}
|
||||
/*
|
||||
* Initialize the Tx Buffer Descriptor ring
|
||||
*/
|
||||
for (i = 0; i < NTXBD; ++i)
|
||||
{
|
||||
TxBD(ch, i).status = TX_BD_INTERRUPT;
|
||||
TxBD(ch, i).length = 0;
|
||||
TxBD(ch, i).data = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the WRAP bit on the last one
|
||||
*/
|
||||
TxBD(ch, i - 1).status |= TX_BD_W;
|
||||
/*
|
||||
* Set the WRAP bit on the last one
|
||||
*/
|
||||
TxBD(ch, i - 1).status |= TX_BD_W;
|
||||
|
||||
/*
|
||||
* Initialize the buffer descriptor indexes
|
||||
*/
|
||||
iTxbd_new = iTxbd_old = iRxbd = 0;
|
||||
/*
|
||||
* Initialize the buffer descriptor indexes
|
||||
*/
|
||||
iTxbd_new = iTxbd_old = iRxbd = 0;
|
||||
}
|
||||
|
||||
void fecbd_dump(uint8_t ch)
|
||||
{
|
||||
#ifdef DBG_FECBD
|
||||
int i;
|
||||
int i;
|
||||
|
||||
xprintf("\n------------ FEC%d BDs -----------\n",ch);
|
||||
xprintf("RxBD Ring\n");
|
||||
for (i = 0; i < NRXBD; i++)
|
||||
{
|
||||
xprintf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n",
|
||||
i, &RxBD(ch, i),
|
||||
RxBD(ch, i).status,
|
||||
RxBD(ch, i).length,
|
||||
RxBD(ch, i).data);
|
||||
}
|
||||
xprintf("TxBD Ring\n");
|
||||
for (i = 0; i < NTXBD; i++)
|
||||
{
|
||||
xprintf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n",
|
||||
i, &TxBD(ch, i),
|
||||
TxBD(ch, i).status,
|
||||
TxBD(ch, i).length,
|
||||
TxBD(ch, i).data);
|
||||
}
|
||||
xprintf("--------------------------------\n\n");
|
||||
xprintf("\n------------ FEC%d BDs -----------\n",ch);
|
||||
xprintf("RxBD Ring\n");
|
||||
for (i = 0; i < NRXBD; i++)
|
||||
{
|
||||
xprintf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n",
|
||||
i, &RxBD(ch, i),
|
||||
RxBD(ch, i).status,
|
||||
RxBD(ch, i).length,
|
||||
RxBD(ch, i).data);
|
||||
}
|
||||
xprintf("TxBD Ring\n");
|
||||
for (i = 0; i < NTXBD; i++)
|
||||
{
|
||||
xprintf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n",
|
||||
i, &TxBD(ch, i),
|
||||
TxBD(ch, i).status,
|
||||
TxBD(ch, i).length,
|
||||
TxBD(ch, i).data);
|
||||
}
|
||||
xprintf("--------------------------------\n\n");
|
||||
#endif /* DBG_FECBD */
|
||||
}
|
||||
|
||||
@@ -165,28 +165,28 @@ void fecbd_dump(uint8_t ch)
|
||||
*/
|
||||
uint32_t fecbd_get_start(uint8_t ch, uint8_t direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case Rx:
|
||||
return (uint32_t)((int)RxBD + (ch * sizeof(FECBD) * NRXBD));
|
||||
case Tx:
|
||||
default:
|
||||
return (uint32_t)((int)TxBD + (ch * sizeof(FECBD) * NTXBD));
|
||||
}
|
||||
switch (direction)
|
||||
{
|
||||
case Rx:
|
||||
return (uint32_t)((int)RxBD + (ch * sizeof(FECBD) * NRXBD));
|
||||
case Tx:
|
||||
default:
|
||||
return (uint32_t)((int)TxBD + (ch * sizeof(FECBD) * NTXBD));
|
||||
}
|
||||
}
|
||||
|
||||
FECBD *fecbd_rx_alloc(uint8_t ch)
|
||||
{
|
||||
int i = iRxbd;
|
||||
int i = iRxbd;
|
||||
|
||||
/* Check to see if the ring of BDs is full */
|
||||
if (RxBD(ch, i).status & RX_BD_E)
|
||||
return NULL;
|
||||
/* Check to see if the ring of BDs is full */
|
||||
if (RxBD(ch, i).status & RX_BD_E)
|
||||
return NULL;
|
||||
|
||||
/* Increment the circular index */
|
||||
iRxbd = (uint8_t)((iRxbd + 1) % NRXBD);
|
||||
/* Increment the circular index */
|
||||
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)
|
||||
{
|
||||
int i = iTxbd_new;
|
||||
int i = iTxbd_new;
|
||||
|
||||
/* Check to see if the ring of BDs is full */
|
||||
if (TxBD(ch, i).status & TX_BD_R)
|
||||
return NULL;
|
||||
/* Check to see if the ring of BDs is full */
|
||||
if (TxBD(ch, i).status & TX_BD_R)
|
||||
return NULL;
|
||||
|
||||
/* Increment the circular index */
|
||||
iTxbd_new = (uint8_t)((iTxbd_new + 1) % NTXBD);
|
||||
/* Increment the circular index */
|
||||
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)
|
||||
{
|
||||
int i = iTxbd_old;
|
||||
int i = iTxbd_old;
|
||||
|
||||
/* Check to see if the ring of BDs is empty */
|
||||
if ((TxBD(ch, i).data == NULL) || (TxBD(ch, i).status & TX_BD_R))
|
||||
return NULL;
|
||||
/* Check to see if the ring of BDs is empty */
|
||||
if ((TxBD(ch, i).data == NULL) || (TxBD(ch, i).status & TX_BD_R))
|
||||
return NULL;
|
||||
|
||||
/* Increment the circular index */
|
||||
iTxbd_old = (uint8_t)((iTxbd_old + 1) % NTXBD);
|
||||
/* Increment the circular index */
|
||||
iTxbd_old = (uint8_t)((iTxbd_old + 1) % NTXBD);
|
||||
|
||||
return &TxBD(ch, i);
|
||||
return &TxBD(ch, i);
|
||||
}
|
||||
|
||||
448
net/ip.c
448
net/ip.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* File: ip.c
|
||||
* File: ip.c
|
||||
* Purpose: Internet Protcol device driver
|
||||
*
|
||||
* Notes:
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#define IP_DEBUG
|
||||
//#define IP_DEBUG
|
||||
#if defined(IP_DEBUG)
|
||||
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
||||
#else
|
||||
@@ -22,300 +22,300 @@
|
||||
|
||||
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++)
|
||||
{
|
||||
info->myip[index] = myip[index];
|
||||
info->gateway[index] = gateway[index];
|
||||
info->netmask[index] = netmask[index];
|
||||
info->broadcast[index] = 0xFF;
|
||||
}
|
||||
for (index = 0; index < sizeof(IP_ADDR); index++)
|
||||
{
|
||||
info->myip[index] = myip[index];
|
||||
info->gateway[index] = gateway[index];
|
||||
info->netmask[index] = netmask[index];
|
||||
info->broadcast[index] = 0xFF;
|
||||
}
|
||||
|
||||
info->rx = 0;
|
||||
info->rx_unsup = 0;
|
||||
info->tx = 0;
|
||||
info->err = 0;
|
||||
info->rx = 0;
|
||||
info->rx_unsup = 0;
|
||||
info->tx = 0;
|
||||
info->err = 0;
|
||||
}
|
||||
|
||||
uint8_t *ip_get_myip(IP_INFO *info)
|
||||
{
|
||||
if (info != 0)
|
||||
{
|
||||
return (uint8_t *) &info->myip[0];
|
||||
}
|
||||
if (info != 0)
|
||||
{
|
||||
return (uint8_t *) &info->myip[0];
|
||||
}
|
||||
dbg("info is NULL!\n\t");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ip_addr_compare(IP_ADDR_P addr1, IP_ADDR_P addr2)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(IP_ADDR); i++)
|
||||
{
|
||||
if (addr1[i] != addr2[i])
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
for (i = 0; i < sizeof(IP_ADDR); i++)
|
||||
{
|
||||
if (addr1[i] != addr2[i])
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t *ip_resolve_route(NIF *nif, IP_ADDR_P destip)
|
||||
{
|
||||
/*
|
||||
* This function determines whether or not an outgoing IP
|
||||
* packet needs to be transmitted on the local net or sent
|
||||
* to the router for transmission.
|
||||
*/
|
||||
IP_INFO *info;
|
||||
IP_ADDR mask, result;
|
||||
IP_ADDR bc = { 255, 255, 255, 255 };
|
||||
int i;
|
||||
/*
|
||||
* This function determines whether or not an outgoing IP
|
||||
* packet needs to be transmitted on the local net or sent
|
||||
* to the router for transmission.
|
||||
*/
|
||||
IP_INFO *info;
|
||||
IP_ADDR mask, result;
|
||||
IP_ADDR bc = { 255, 255, 255, 255 };
|
||||
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)
|
||||
{
|
||||
dbg("destip is broadcast address, no gateway needed\r\n");
|
||||
return destip;
|
||||
}
|
||||
{
|
||||
dbg("destip is broadcast address, no gateway needed\r\n");
|
||||
return destip;
|
||||
}
|
||||
|
||||
/* create mask for local IP */
|
||||
for (i = 0; i < sizeof(IP_ADDR); i++)
|
||||
{
|
||||
mask[i] = info->myip[i] & info->netmask[i];
|
||||
}
|
||||
/* create mask for local IP */
|
||||
for (i = 0; i < sizeof(IP_ADDR); i++)
|
||||
{
|
||||
mask[i] = info->myip[i] & info->netmask[i];
|
||||
}
|
||||
|
||||
/* apply mask to the destination IP */
|
||||
for (i = 0; i < sizeof(IP_ADDR); i++)
|
||||
{
|
||||
result[i] = mask[i] & destip[i];
|
||||
}
|
||||
/* apply mask to the destination IP */
|
||||
for (i = 0; i < sizeof(IP_ADDR); i++)
|
||||
{
|
||||
result[i] = mask[i] & destip[i];
|
||||
}
|
||||
|
||||
/* See if destination IP is local or not */
|
||||
if (ip_addr_compare(mask, result))
|
||||
{
|
||||
/* The destination IP is on the local net */
|
||||
return arp_resolve(nif, ETH_FRM_IP, destip);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The destination IP is not on the local net */
|
||||
return arp_resolve(nif, ETH_FRM_IP, info->gateway);
|
||||
}
|
||||
/* See if destination IP is local or not */
|
||||
if (ip_addr_compare(mask, result))
|
||||
{
|
||||
/* The destination IP is on the local net */
|
||||
return arp_resolve(nif, ETH_FRM_IP, destip);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The destination IP is not on the local net */
|
||||
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)
|
||||
{
|
||||
/*
|
||||
* This function assembles an IP datagram and passes it
|
||||
* onto the hardware to be sent over the network.
|
||||
*/
|
||||
uint8_t *route;
|
||||
ip_frame_hdr *ipframe;
|
||||
/*
|
||||
* This function assembles an IP datagram and passes it
|
||||
* onto the hardware to be sent over the network.
|
||||
*/
|
||||
uint8_t *route;
|
||||
ip_frame_hdr *ipframe;
|
||||
|
||||
/*
|
||||
* Construct the IP header
|
||||
*/
|
||||
ipframe = (ip_frame_hdr*) &pNbuf->data[IP_HDR_OFFSET];
|
||||
/*
|
||||
* Construct the IP header
|
||||
*/
|
||||
ipframe = (ip_frame_hdr*) &pNbuf->data[IP_HDR_OFFSET];
|
||||
|
||||
/* IP version 4, Internet Header Length of 5 32-bit words */
|
||||
ipframe->version_ihl = 0x45;
|
||||
/* IP version 4, Internet Header Length of 5 32-bit words */
|
||||
ipframe->version_ihl = 0x45;
|
||||
|
||||
/* Type of Service == 0, normal and routine */
|
||||
ipframe->service_type = 0x00;
|
||||
/* Type of Service == 0, normal and routine */
|
||||
ipframe->service_type = 0x00;
|
||||
|
||||
/* Total length of data */
|
||||
ipframe->total_length = (uint16_t) (pNbuf->length + IP_HDR_SIZE);
|
||||
/* Total length of data */
|
||||
ipframe->total_length = (uint16_t) (pNbuf->length + IP_HDR_SIZE);
|
||||
|
||||
/* User defined identification */
|
||||
ipframe->identification = 0x0000;
|
||||
/* User defined identification */
|
||||
ipframe->identification = 0x0000;
|
||||
|
||||
/* Fragment Flags and Offset -- Don't fragment, last frag */
|
||||
ipframe->flags_frag_offset = 0x0000;
|
||||
/* Fragment Flags and Offset -- Don't fragment, last frag */
|
||||
ipframe->flags_frag_offset = 0x0000;
|
||||
|
||||
/* Time To Live */
|
||||
ipframe->ttl = 0xFF;
|
||||
/* Time To Live */
|
||||
ipframe->ttl = 0xFF;
|
||||
|
||||
/* Protocol */
|
||||
ipframe->protocol = protocol;
|
||||
/* Protocol */
|
||||
ipframe->protocol = protocol;
|
||||
|
||||
/* Checksum, computed later, zeroed for computation */
|
||||
ipframe->checksum = 0x0000;
|
||||
/* Checksum, computed later, zeroed for computation */
|
||||
ipframe->checksum = 0x0000;
|
||||
|
||||
/* source IP address */
|
||||
ipframe->source_addr[0] = src[0];
|
||||
ipframe->source_addr[1] = src[1];
|
||||
ipframe->source_addr[2] = src[2];
|
||||
ipframe->source_addr[3] = src[3];
|
||||
/* source IP address */
|
||||
ipframe->source_addr[0] = src[0];
|
||||
ipframe->source_addr[1] = src[1];
|
||||
ipframe->source_addr[2] = src[2];
|
||||
ipframe->source_addr[3] = src[3];
|
||||
|
||||
/* dest IP address */
|
||||
ipframe->dest_addr[0] = dest[0];
|
||||
ipframe->dest_addr[1] = dest[1];
|
||||
ipframe->dest_addr[2] = dest[2];
|
||||
ipframe->dest_addr[3] = dest[3];
|
||||
/* dest IP address */
|
||||
ipframe->dest_addr[0] = dest[0];
|
||||
ipframe->dest_addr[1] = dest[1];
|
||||
ipframe->dest_addr[2] = dest[2];
|
||||
ipframe->dest_addr[3] = dest[3];
|
||||
|
||||
/* Compute checksum */
|
||||
ipframe->checksum = ip_chksum((uint16_t *) ipframe, IP_HDR_SIZE);
|
||||
/* Compute checksum */
|
||||
ipframe->checksum = ip_chksum((uint16_t *) ipframe, IP_HDR_SIZE);
|
||||
|
||||
/* Increment the packet length by the size of the IP header */
|
||||
pNbuf->length += IP_HDR_SIZE;
|
||||
/* Increment the packet length by the size of the IP header */
|
||||
pNbuf->length += IP_HDR_SIZE;
|
||||
|
||||
/*
|
||||
* Determine the hardware address of the recipient
|
||||
*/
|
||||
IP_ADDR bc = { 255, 255, 255, 255};
|
||||
if (memcmp(bc, dest, 4) != 0)
|
||||
{
|
||||
route = ip_resolve_route(nif, dest);
|
||||
if (route == NULL)
|
||||
{
|
||||
dbg("Unable to locate %d.%d.%d.%d\r\n",
|
||||
dest[0], dest[1], dest[2], dest[3]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
route = bc;
|
||||
dbg("route = broadcast\r\n");
|
||||
dbg("nif = %p\r\n", nif);
|
||||
dbg("nif->send = %p\r\n", nif->send);
|
||||
}
|
||||
/*
|
||||
* Determine the hardware address of the recipient
|
||||
*/
|
||||
IP_ADDR bc = { 255, 255, 255, 255};
|
||||
if (memcmp(bc, dest, 4) != 0)
|
||||
{
|
||||
route = ip_resolve_route(nif, dest);
|
||||
if (route == NULL)
|
||||
{
|
||||
dbg("Unable to locate %d.%d.%d.%d\r\n",
|
||||
dest[0], dest[1], dest[2], dest[3]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
route = bc;
|
||||
dbg("route = broadcast\r\n");
|
||||
dbg("nif = %p\r\n", nif);
|
||||
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)
|
||||
void dump_ip_frame(ip_frame_hdr *ipframe)
|
||||
{
|
||||
xprintf("Version: %02X\n", ((ipframe->version_ihl & 0x00f0) >> 4));
|
||||
xprintf("IHL: %02X\n", ipframe->version_ihl & 0x000f);
|
||||
xprintf("Service: %02X\n", ipframe->service_type);
|
||||
xprintf("Length: %04X\n", ipframe->total_length);
|
||||
xprintf("Ident: %04X\n", ipframe->identification);
|
||||
xprintf("Flags: %02X\n", ((ipframe->flags_frag_offset & 0xC000) >> 14));
|
||||
xprintf("Frag: %04X\n", ipframe->flags_frag_offset & 0x3FFF);
|
||||
xprintf("TTL: %02X\n", ipframe->ttl);
|
||||
xprintf("Protocol: %02X\n", ipframe->protocol);
|
||||
xprintf("Chksum: %04X\n", ipframe->checksum);
|
||||
xprintf("Source : %d.%d.%d.%d\n",
|
||||
ipframe->source_addr[0],
|
||||
ipframe->source_addr[1],
|
||||
ipframe->source_addr[2],
|
||||
ipframe->source_addr[3]);
|
||||
xprintf("Dest : %d.%d.%d.%d\n",
|
||||
ipframe->dest_addr[0],
|
||||
ipframe->dest_addr[1],
|
||||
ipframe->dest_addr[2],
|
||||
ipframe->dest_addr[3]);
|
||||
xprintf("Options: %08X\n", ipframe->options);
|
||||
xprintf("Version: %02X\n", ((ipframe->version_ihl & 0x00f0) >> 4));
|
||||
xprintf("IHL: %02X\n", ipframe->version_ihl & 0x000f);
|
||||
xprintf("Service: %02X\n", ipframe->service_type);
|
||||
xprintf("Length: %04X\n", ipframe->total_length);
|
||||
xprintf("Ident: %04X\n", ipframe->identification);
|
||||
xprintf("Flags: %02X\n", ((ipframe->flags_frag_offset & 0xC000) >> 14));
|
||||
xprintf("Frag: %04X\n", ipframe->flags_frag_offset & 0x3FFF);
|
||||
xprintf("TTL: %02X\n", ipframe->ttl);
|
||||
xprintf("Protocol: %02X\n", ipframe->protocol);
|
||||
xprintf("Chksum: %04X\n", ipframe->checksum);
|
||||
xprintf("Source : %d.%d.%d.%d\n",
|
||||
ipframe->source_addr[0],
|
||||
ipframe->source_addr[1],
|
||||
ipframe->source_addr[2],
|
||||
ipframe->source_addr[3]);
|
||||
xprintf("Dest : %d.%d.%d.%d\n",
|
||||
ipframe->dest_addr[0],
|
||||
ipframe->dest_addr[1],
|
||||
ipframe->dest_addr[2],
|
||||
ipframe->dest_addr[3]);
|
||||
xprintf("Options: %08X\n", ipframe->options);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
uint16_t ip_chksum(uint16_t *data, int num)
|
||||
{
|
||||
int chksum, ichksum;
|
||||
uint16_t temp;
|
||||
int chksum, ichksum;
|
||||
uint16_t temp;
|
||||
|
||||
chksum = 0;
|
||||
num = num >> 1; /* from bytes to words */
|
||||
for (; num; num--, data++)
|
||||
{
|
||||
temp = *data;
|
||||
ichksum = chksum + temp;
|
||||
ichksum = ichksum & 0x0000FFFF;
|
||||
if ((ichksum < temp) || (ichksum < chksum))
|
||||
{
|
||||
ichksum += 1;
|
||||
ichksum = ichksum & 0x0000FFFF;
|
||||
}
|
||||
chksum = ichksum;
|
||||
}
|
||||
return (uint16_t) ~chksum;
|
||||
chksum = 0;
|
||||
num = num >> 1; /* from bytes to words */
|
||||
for (; num; num--, data++)
|
||||
{
|
||||
temp = *data;
|
||||
ichksum = chksum + temp;
|
||||
ichksum = ichksum & 0x0000FFFF;
|
||||
if ((ichksum < temp) || (ichksum < chksum))
|
||||
{
|
||||
ichksum += 1;
|
||||
ichksum = ichksum & 0x0000FFFF;
|
||||
}
|
||||
chksum = ichksum;
|
||||
}
|
||||
return (uint16_t) ~chksum;
|
||||
}
|
||||
|
||||
static int validate_ip_hdr(NIF *nif, ip_frame_hdr *ipframe)
|
||||
{
|
||||
int index, chksum;
|
||||
IP_INFO *info;
|
||||
int index, chksum;
|
||||
IP_INFO *info;
|
||||
|
||||
/*
|
||||
* Check the IP Version
|
||||
*/
|
||||
if (IP_VERSION(ipframe) != 4)
|
||||
return 0;
|
||||
/*
|
||||
* Check the IP Version
|
||||
*/
|
||||
if (IP_VERSION(ipframe) != 4)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check Internet Header Length
|
||||
*/
|
||||
if (IP_IHL(ipframe) < 5)
|
||||
return 0;
|
||||
/*
|
||||
* Check Internet Header Length
|
||||
*/
|
||||
if (IP_IHL(ipframe) < 5)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check the destination IP address
|
||||
*/
|
||||
info = nif_get_protocol_info(nif,ETH_FRM_IP);
|
||||
for (index = 0; index < sizeof(IP_ADDR); index++)
|
||||
if (info->myip[index] != ipframe->dest_addr[index])
|
||||
return 0;
|
||||
/*
|
||||
* Check the destination IP address
|
||||
*/
|
||||
info = nif_get_protocol_info(nif,ETH_FRM_IP);
|
||||
for (index = 0; index < sizeof(IP_ADDR); index++)
|
||||
if (info->myip[index] != ipframe->dest_addr[index])
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check the checksum
|
||||
*/
|
||||
chksum = (int)((uint16_t) IP_CHKSUM(ipframe));
|
||||
IP_CHKSUM(ipframe) = 0;
|
||||
/*
|
||||
* Check the checksum
|
||||
*/
|
||||
chksum = (int)((uint16_t) IP_CHKSUM(ipframe));
|
||||
IP_CHKSUM(ipframe) = 0;
|
||||
|
||||
if (ip_chksum((uint16_t *) ipframe, IP_IHL(ipframe) * 4) != chksum)
|
||||
return 0;
|
||||
if (ip_chksum((uint16_t *) ipframe, IP_IHL(ipframe) * 4) != chksum)
|
||||
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)
|
||||
{
|
||||
/*
|
||||
* IP packet handler
|
||||
*/
|
||||
ip_frame_hdr *ipframe;
|
||||
/*
|
||||
* IP packet handler
|
||||
*/
|
||||
ip_frame_hdr *ipframe;
|
||||
|
||||
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
|
||||
*/
|
||||
if (!validate_ip_hdr(nif, ipframe))
|
||||
{
|
||||
dbg("not a valid IP packet!\r\n");
|
||||
|
||||
nbuf_free(pNbuf);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Verify valid IP header and destination IP
|
||||
*/
|
||||
if (!validate_ip_hdr(nif, ipframe))
|
||||
{
|
||||
dbg("not a valid IP packet!\r\n");
|
||||
|
||||
pNbuf->offset += (IP_IHL(ipframe) * 4);
|
||||
pNbuf->length = (uint16_t)(IP_LENGTH(ipframe) - (IP_IHL(ipframe) * 4));
|
||||
nbuf_free(pNbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the appriopriate handler
|
||||
*/
|
||||
switch (IP_PROTOCOL(ipframe))
|
||||
{
|
||||
case IP_PROTO_ICMP:
|
||||
// FIXME: icmp_handler(nif, pNbuf);
|
||||
break;
|
||||
case IP_PROTO_UDP:
|
||||
udp_handler(nif,pNbuf);
|
||||
break;
|
||||
default:
|
||||
dbg("no protocol handler registered for protocol %d\r\n",
|
||||
__FUNCTION__, IP_PROTOCOL(ipframe));
|
||||
nbuf_free(pNbuf);
|
||||
break;
|
||||
}
|
||||
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))
|
||||
{
|
||||
case IP_PROTO_ICMP:
|
||||
// FIXME: icmp_handler(nif, pNbuf);
|
||||
break;
|
||||
case IP_PROTO_UDP:
|
||||
udp_handler(nif,pNbuf);
|
||||
break;
|
||||
default:
|
||||
dbg("no protocol handler registered for protocol %d\r\n",
|
||||
__FUNCTION__, IP_PROTOCOL(ipframe));
|
||||
nbuf_free(pNbuf);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
190
net/udp.c
190
net/udp.c
@@ -21,8 +21,8 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t port;
|
||||
void (*handler)(NIF *, NBUF *);
|
||||
uint16_t port;
|
||||
void (*handler)(NIF *, NBUF *);
|
||||
} UDP_BOUND_PORT;
|
||||
|
||||
#define UDP_MAX_PORTS (5) /* plenty for this implementation */
|
||||
@@ -34,151 +34,151 @@ static uint16_t udp_port;
|
||||
|
||||
void udp_init(void)
|
||||
{
|
||||
int index;
|
||||
int index;
|
||||
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
udp_port_table[index].port = 0;
|
||||
udp_port_table[index].handler = 0;
|
||||
}
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
udp_port_table[index].port = 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)
|
||||
{
|
||||
udp_port = init_port;
|
||||
udp_port = init_port;
|
||||
}
|
||||
|
||||
void udp_bind_port(uint16_t port, void (*handler)(NIF *, NBUF *))
|
||||
{
|
||||
int index;
|
||||
int index;
|
||||
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
if (udp_port_table[index].port == 0)
|
||||
{
|
||||
udp_port_table[index].port = port;
|
||||
udp_port_table[index].handler = handler;
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
if (udp_port_table[index].port == 0)
|
||||
{
|
||||
udp_port_table[index].port = port;
|
||||
udp_port_table[index].handler = handler;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void udp_free_port(uint16_t port)
|
||||
{
|
||||
int index;
|
||||
int index;
|
||||
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
if (udp_port_table[index].port == port)
|
||||
{
|
||||
udp_port_table[index].port = 0;
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
if (udp_port_table[index].port == port)
|
||||
{
|
||||
udp_port_table[index].port = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void *udp_port_handler(uint16_t port)
|
||||
{
|
||||
int index;
|
||||
int index;
|
||||
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
if (udp_port_table[index].port == port)
|
||||
{
|
||||
return (void *) udp_port_table[index].handler;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
if (udp_port_table[index].port == port)
|
||||
{
|
||||
return (void *) udp_port_table[index].handler;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t udp_obtain_free_port(void)
|
||||
{
|
||||
uint16_t port;
|
||||
uint16_t port;
|
||||
|
||||
port = udp_port;
|
||||
if (--udp_port <= 255)
|
||||
udp_port = DEFAULT_UDP_PORT;
|
||||
port = udp_port;
|
||||
if (--udp_port <= 255)
|
||||
udp_port = DEFAULT_UDP_PORT;
|
||||
|
||||
return port;
|
||||
return port;
|
||||
}
|
||||
|
||||
int udp_send(NIF *nif, uint8_t *dest, int sport, int dport, NBUF *pNbuf)
|
||||
{
|
||||
uint8_t *myip;
|
||||
uint8_t *myip;
|
||||
|
||||
if (nif == NULL)
|
||||
{
|
||||
dbg("%s: nif is NULL\r\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
if (nif == NULL)
|
||||
{
|
||||
dbg("%s: nif is NULL\r\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function takes data, creates a UDP frame from it and
|
||||
* passes it onto the IP layer
|
||||
*/
|
||||
udp_frame_hdr *udpframe;
|
||||
/*
|
||||
* This function takes data, creates a UDP frame from it and
|
||||
* passes it onto the IP layer
|
||||
*/
|
||||
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 */
|
||||
udpframe->src_port = (uint16_t) sport;
|
||||
/* Set UDP source port */
|
||||
udpframe->src_port = (uint16_t) sport;
|
||||
|
||||
/* Set UDP destination port */
|
||||
udpframe->dest_port = (uint16_t) dport;
|
||||
/* Set UDP destination port */
|
||||
udpframe->dest_port = (uint16_t) dport;
|
||||
|
||||
/* Set length */
|
||||
udpframe->length = (uint16_t) (pNbuf->length + UDP_HDR_SIZE);
|
||||
/* Set length */
|
||||
udpframe->length = (uint16_t) (pNbuf->length + UDP_HDR_SIZE);
|
||||
|
||||
/* No checksum calcualation needed */
|
||||
udpframe->chksum = (uint16_t) 0;
|
||||
/* No checksum calcualation needed */
|
||||
udpframe->chksum = (uint16_t) 0;
|
||||
|
||||
/* Add the length of the UDP packet to the total length of the packet */
|
||||
pNbuf->length += 8;
|
||||
/* Add the length of the UDP packet to the total length of the packet */
|
||||
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("%s: sent UDP request to %d.%d.%d.%d from %d.%d.%d.%d\r\n", __FUNCTION__,
|
||||
dest[0], dest[1], dest[2], dest[3],
|
||||
myip[0], myip[1], myip[2], myip[3]);
|
||||
dbg("%s: sent UDP request to %d.%d.%d.%d from %d.%d.%d.%d\r\n", __FUNCTION__,
|
||||
dest[0], dest[1], dest[2], dest[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)
|
||||
{
|
||||
/*
|
||||
* This function handles incoming UDP packets
|
||||
*/
|
||||
udp_frame_hdr *udpframe;
|
||||
void (*handler)(NIF *, NBUF *);
|
||||
/*
|
||||
* This function handles incoming UDP packets
|
||||
*/
|
||||
udp_frame_hdr *udpframe;
|
||||
void (*handler)(NIF *, NBUF *);
|
||||
|
||||
udpframe = (udp_frame_hdr *) &pNbuf->data[pNbuf->offset];
|
||||
udpframe = (udp_frame_hdr *) &pNbuf->data[pNbuf->offset];
|
||||
|
||||
dbg("%s: packet received\r\n", __FUNCTION__);
|
||||
dbg("%s: packet received\r\n", __FUNCTION__);
|
||||
|
||||
/*
|
||||
* Adjust the length and valid data offset of the packet we are
|
||||
* passing on
|
||||
*/
|
||||
pNbuf->length -= UDP_HDR_SIZE;
|
||||
pNbuf->offset += UDP_HDR_SIZE;
|
||||
/*
|
||||
* Adjust the length and valid data offset of the packet we are
|
||||
* passing on
|
||||
*/
|
||||
pNbuf->length -= UDP_HDR_SIZE;
|
||||
pNbuf->offset += UDP_HDR_SIZE;
|
||||
|
||||
/*
|
||||
* Traverse the list of bound ports to see if there is a higher
|
||||
* level protocol to pass the packet on to
|
||||
*/
|
||||
if ((handler = (void(*)(NIF*, NBUF*)) udp_port_handler(UDP_DEST(udpframe))) != NULL)
|
||||
handler(nif, pNbuf);
|
||||
else
|
||||
{
|
||||
dbg("%s: received UDP packet for non-supported port\n", __FUNCTION__);
|
||||
nbuf_free(pNbuf);
|
||||
}
|
||||
/*
|
||||
* Traverse the list of bound ports to see if there is a higher
|
||||
* level protocol to pass the packet on to
|
||||
*/
|
||||
if ((handler = (void(*)(NIF*, NBUF*)) udp_port_handler(UDP_DEST(udpframe))) != NULL)
|
||||
handler(nif, pNbuf);
|
||||
else
|
||||
{
|
||||
dbg("%s: received UDP packet for non-supported port\n", __FUNCTION__);
|
||||
nbuf_free(pNbuf);
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
1317
sys/exceptions.S
1317
sys/exceptions.S
File diff suppressed because it is too large
Load Diff
208
sys/init_fpga.c
208
sys/init_fpga.c
@@ -40,39 +40,42 @@ extern uint8_t _FPGA_CONFIG_SIZE[];
|
||||
|
||||
/*
|
||||
* 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 int32_t _FPGA_JTAG_LOADED;
|
||||
extern int32_t _FPGA_JTAG_VALID;
|
||||
#define VALID_JTAG 0xaffeaffe
|
||||
|
||||
void config_gpio_for_fpga_config(void)
|
||||
{
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
/*
|
||||
* Configure GPIO FEC1L port directions (needed to load FPGA configuration)
|
||||
*/
|
||||
MCF_GPIO_PDDR_FEC1L = 0 | /* bit 7 = input */
|
||||
0 | /* bit 6 = input */
|
||||
0 | /* bit 5 = input */
|
||||
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_FEC1L2 | /* bit 2 = FPGA_CONFIG => output */
|
||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L1 | /* bit 1 = PRG_CLK (FPGA) => output */
|
||||
0; /* bit 0 => input */
|
||||
/*
|
||||
* Configure GPIO FEC1L port directions (needed to load FPGA configuration)
|
||||
*/
|
||||
MCF_GPIO_PDDR_FEC1L = 0 | /* bit 7 = input */
|
||||
0 | /* bit 6 = input */
|
||||
0 | /* bit 5 = input */
|
||||
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_FEC1L2 | /* bit 2 = FPGA_CONFIG => output */
|
||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L1 | /* bit 1 = PRG_CLK (FPGA) => output */
|
||||
0; /* bit 0 => input */
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
}
|
||||
|
||||
void config_gpio_for_jtag_config(void)
|
||||
{
|
||||
/*
|
||||
* configure FEC1L port directions to enable external JTAG configuration download to FPGA
|
||||
*/
|
||||
MCF_GPIO_PDDR_FEC1L = 0 |
|
||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
|
||||
/* all other bits = input */
|
||||
/*
|
||||
* unfortunately, the GPIO module cannot trigger interrupts. That means FPGA_CONFIG 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...
|
||||
*/
|
||||
/*
|
||||
* configure FEC1L port directions to enable external JTAG configuration download to FPGA
|
||||
*/
|
||||
MCF_GPIO_PDDR_FEC1L = 0 |
|
||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
|
||||
/* all other bits = input */
|
||||
/*
|
||||
* unfortunately, the GPIO module cannot trigger interrupts. That means FPGA_CONFIG 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...
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -80,96 +83,101 @@ void config_gpio_for_jtag_config(void)
|
||||
*/
|
||||
bool init_fpga(void)
|
||||
{
|
||||
uint8_t *fpga_data;
|
||||
volatile int32_t time, start, end;
|
||||
int i;
|
||||
uint8_t *fpga_data;
|
||||
volatile int32_t time, start, end;
|
||||
int i;
|
||||
|
||||
xprintf("FPGA load config (_FPGA_JTAG_LOADED = %x)...", _FPGA_JTAG_LOADED);
|
||||
if (_FPGA_JTAG_LOADED == 1)
|
||||
{
|
||||
xprintf("detected _FPGA_JTAG_LOADED flag. Not overwriting FPGA config.\r\n");
|
||||
xprintf("FPGA load config...\r\n");
|
||||
xprintf("_FPGA_JTAG_LOADED = %x, _FPGA_JTAG_VALID = %x)\r\n", _FPGA_JTAG_LOADED, _FPGA_JTAG_VALID);
|
||||
if (_FPGA_JTAG_LOADED == 1 && _FPGA_JTAG_VALID == VALID_JTAG)
|
||||
{
|
||||
xprintf("detected _FPGA_JTAG_LOADED flag. Not overwriting FPGA config.\r\n");
|
||||
|
||||
/* reset the flag so that next boot will load config again from flash */
|
||||
_FPGA_JTAG_LOADED = 0;
|
||||
return true;
|
||||
}
|
||||
start = MCF_SLT0_SCNT;
|
||||
/* reset the flag so that next boot will load config again from flash */
|
||||
_FPGA_JTAG_LOADED = 0;
|
||||
_FPGA_JTAG_VALID = 0;
|
||||
|
||||
config_gpio_for_fpga_config();
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */
|
||||
return true;
|
||||
}
|
||||
start = MCF_SLT0_SCNT;
|
||||
|
||||
/* 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 */
|
||||
config_gpio_for_fpga_config();
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */
|
||||
|
||||
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)); /* wait until status becomes high */
|
||||
while ((MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS) && (MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE));
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
MCF_GPIO_PODR_FEC1L |= FPGA_CONFIG; /* pull FPGA_CONFIG high to start config cycle */
|
||||
while (!(MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS))
|
||||
; /* wait until status becomes high */
|
||||
|
||||
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;
|
||||
do
|
||||
{
|
||||
uint8_t value = *fpga_data++;
|
||||
for (i = 0; i < 8; i++, value >>= 1)
|
||||
{
|
||||
const uint8_t *fpga_flash_data_end = FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
|
||||
|
||||
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));
|
||||
fpga_data = (uint8_t *) FPGA_FLASH_DATA;
|
||||
do
|
||||
{
|
||||
uint8_t value = *fpga_data++;
|
||||
for (i = 0; i < 8; i++, value >>= 1)
|
||||
{
|
||||
|
||||
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_
|
||||
while (fpga_data++ < fpga_flash_data_end)
|
||||
{
|
||||
/* toggle a little more since it's fun ;) */
|
||||
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
|
||||
}
|
||||
while (fpga_data++ < fpga_flash_data_end)
|
||||
{
|
||||
/* toggle a little more since it's fun ;) */
|
||||
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
|
||||
}
|
||||
#endif /* _NOT_USED_ */
|
||||
end = MCF_SLT0_SCNT;
|
||||
time = (start - end) / (SYSCLK / 1000) / 1000;
|
||||
end = MCF_SLT0_SCNT;
|
||||
time = (start - end) / (SYSCLK / 1000) / 1000;
|
||||
|
||||
xprintf("finished (took %f seconds).\r\n", time / 1000.0);
|
||||
config_gpio_for_jtag_config();
|
||||
return true;
|
||||
}
|
||||
xprintf("FAILED!\r\n");
|
||||
config_gpio_for_jtag_config();
|
||||
return false;
|
||||
xprintf("finished (took %f seconds).\r\n", time / 1000.0);
|
||||
config_gpio_for_jtag_config();
|
||||
return true;
|
||||
}
|
||||
xprintf("FAILED!\r\n");
|
||||
config_gpio_for_jtag_config();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
1496
sys/sysinit.c
1496
sys/sysinit.c
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,7 @@ uint32_t get_timer(void)
|
||||
{
|
||||
return MCF_SLT_SCNT(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* wait for the specified number of us on slice timer 0. Replaces the original routines that had
|
||||
* the number of useconds to wait for hardcoded in their name.
|
||||
@@ -52,8 +53,8 @@ void wait_ms(uint32_t ms)
|
||||
wait(ms * 1000);
|
||||
}
|
||||
/*
|
||||
* the same as above, with a checker function which gets called while
|
||||
* busy waiting and allows for an early return if it returns true
|
||||
* wait for the specified number of us (same as above), but with a checker function
|
||||
* which gets called while busy waiting and allows for an early return if it returns true
|
||||
*/
|
||||
bool waitfor(uint32_t us, checker_func condition)
|
||||
{
|
||||
@@ -65,5 +66,6 @@ bool waitfor(uint32_t us, checker_func condition)
|
||||
if ((res = (*condition)()))
|
||||
return res;
|
||||
} while (MCF_SLT_SCNT(0) - target > 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user