From ae6cc2d36baec9dee3a82d5542354fcac6b7679c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 4 Apr 2008 18:16:06 +0200 Subject: [m68k] Add Freescale Coldfire V4E Architecture support - Added m68k vector, exception & interrupt handlers - Added m68k macros to access m68k movec registers - Added Coldfire support code (MultiChannelDMA) - Added board support for phytec phyCore-MCF baseboard - Added board support for konzeptpark MCB2 prototype Signed-off-by: Carsten Schlote --- arch/m68k/Kconfig | 178 ++ arch/m68k/Makefile | 105 + .../m68k/configs/phycore_kpukdr1_5475num_defconfig | 196 ++ arch/m68k/configs/phycore_mcf54xx_defconfig | 196 ++ arch/m68k/cpu/Makefile | 41 + arch/m68k/cpu/cpu.c | 185 ++ arch/m68k/cpu/cw_console_io.c | 116 + arch/m68k/cpu/early_init_support.c | 41 + arch/m68k/cpu/interrupts.c | 246 ++ arch/m68k/cpu/start-mcfv4e.S | 677 ++++++ arch/m68k/lib/Makefile | 31 + arch/m68k/lib/m68k-linuxboot.c | 176 ++ arch/m68k/lib/m68k-meminit.c | 42 + arch/m68k/lib/m68k-module.c | 110 + arch/m68k/lib/u-boot.lds.S | 92 + arch/m68k/mach-mcfv4e.dox | 39 + arch/m68k/mach-mcfv4e/Kconfig | 18 + arch/m68k/mach-mcfv4e/Makefile | 19 + arch/m68k/mach-mcfv4e/dma_utils.c | 502 ++++ arch/m68k/mach-mcfv4e/fec.c | 1440 ++++++++++++ arch/m68k/mach-mcfv4e/fecbd.c | 232 ++ arch/m68k/mach-mcfv4e/mcdapi/MCD_dmaApi.c | 907 ++++++++ arch/m68k/mach-mcfv4e/mcdapi/MCD_library.dox | 10 + arch/m68k/mach-mcfv4e/mcdapi/MCD_tasks.c | 2449 ++++++++++++++++++++ arch/m68k/mach-mcfv4e/mcdapi/MCD_tasksInit.c | 225 ++ arch/m68k/mach-mcfv4e/mcdapi/Makefile | 26 + arch/m68k/mach-mcfv4e/mcdapi/ReleaseNotes.txt | 27 + arch/m68k/mach-mcfv4e/mcf_clocksource.c | 138 ++ arch/m68k/mach-mcfv4e/mcf_reset_cpu.c | 45 + arch/m68k/mach-mcfv4e/multichannel_dma.c | 51 + arch/m68k/mach-mcfv4e/net/Makefile | 26 + arch/m68k/mach-mcfv4e/net/nbuf.c | 239 ++ arch/m68k/mach-mcfv4e/net/net.c | 156 ++ arch/m68k/mach-mcfv4e/net/queue.c | 128 + 34 files changed, 9109 insertions(+) create mode 100644 arch/m68k/Kconfig create mode 100644 arch/m68k/Makefile create mode 100644 arch/m68k/configs/phycore_kpukdr1_5475num_defconfig create mode 100644 arch/m68k/configs/phycore_mcf54xx_defconfig create mode 100644 arch/m68k/cpu/Makefile create mode 100644 arch/m68k/cpu/cpu.c create mode 100644 arch/m68k/cpu/cw_console_io.c create mode 100644 arch/m68k/cpu/early_init_support.c create mode 100644 arch/m68k/cpu/interrupts.c create mode 100644 arch/m68k/cpu/start-mcfv4e.S create mode 100644 arch/m68k/lib/Makefile create mode 100644 arch/m68k/lib/m68k-linuxboot.c create mode 100644 arch/m68k/lib/m68k-meminit.c create mode 100644 arch/m68k/lib/m68k-module.c create mode 100644 arch/m68k/lib/u-boot.lds.S create mode 100644 arch/m68k/mach-mcfv4e.dox create mode 100644 arch/m68k/mach-mcfv4e/Kconfig create mode 100644 arch/m68k/mach-mcfv4e/Makefile create mode 100644 arch/m68k/mach-mcfv4e/dma_utils.c create mode 100644 arch/m68k/mach-mcfv4e/fec.c create mode 100644 arch/m68k/mach-mcfv4e/fecbd.c create mode 100644 arch/m68k/mach-mcfv4e/mcdapi/MCD_dmaApi.c create mode 100644 arch/m68k/mach-mcfv4e/mcdapi/MCD_library.dox create mode 100644 arch/m68k/mach-mcfv4e/mcdapi/MCD_tasks.c create mode 100644 arch/m68k/mach-mcfv4e/mcdapi/MCD_tasksInit.c create mode 100644 arch/m68k/mach-mcfv4e/mcdapi/Makefile create mode 100644 arch/m68k/mach-mcfv4e/mcdapi/ReleaseNotes.txt create mode 100644 arch/m68k/mach-mcfv4e/mcf_clocksource.c create mode 100644 arch/m68k/mach-mcfv4e/mcf_reset_cpu.c create mode 100644 arch/m68k/mach-mcfv4e/multichannel_dma.c create mode 100644 arch/m68k/mach-mcfv4e/net/Makefile create mode 100644 arch/m68k/mach-mcfv4e/net/nbuf.c create mode 100644 arch/m68k/mach-mcfv4e/net/net.c create mode 100644 arch/m68k/mach-mcfv4e/net/queue.c (limited to 'arch') diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig new file mode 100644 index 0000000000..07cf431dbe --- /dev/null +++ b/arch/m68k/Kconfig @@ -0,0 +1,178 @@ +# +# Default location of link U-Boot Image on M68k/Coldfire +# +config ARCH_TEXT_BASE + hex + default 0x07f00000 if MACH_MCF54xx + default 0x07f00000 if MACH_MCF5445x + help + Vector table for M68k and U-Boot Link Address + + On M68k/Coldfire cores all exceptions and interrupts are routed through + a vector array. This vector is by default at address 0x0000_0000, but + can be moved to any other 1MB aligned address. + + We take advantage of this to move U-Boot out of low memory. Some BDM + debuggers won't like a moved vector base and might need tweaking to + work. + + Note: Respect alignment restrictions for TEXT_BASE, which must be + 1MB aligned (VBR register constrain). + +# +# Internal configurations +# +config BOARDINFO + default "konzeptpark UKD Prototype with Phycore MCF5485" if MACH_KPUKDR1 + default "konzeptpark UKD Prototype with Phycore MCF5475 NUM" if MACH_KPUKDR1_NUM + default "konzeptpark UKD Revision 2 with Phycore MCF5485" if MACH_KPUKDR2 + default "konzeptpark UKD Revision 2 with Phycore MCF5475 NUM" if MACH_KPUKDR2_NUM + default "Phytec Baseboard with Phycore MCF5485" if MACH_PCM982_5485 + default "Phytec Baseboard with Phycore MCF5475" if MACH_PCM982_5475 + default "Phytec Baseboard with Phycore MCF5475 NUM" if MACH_PCM982_5475_NUM + default "Phytec Baseboard with Phycore MCF54455" if MACH_PCM982_54455 + default "!No boardinfo string set!" + +config HAS_EARLY_INIT + bool + default n + +config BOARD_LINKER_SCRIPT + bool + default n + +config GENERIC_LINKER_SCRIPT + bool + default y + depends on !BOARD_LINKER_SCRIPT + +config M68K + bool + select HAS_KALLSYMS + select HAS_MODULES + default y + +config MCFV4E + bool + +config MCFV4M + bool + +config ARCH_MCF54xx + bool + select MCFV4E + +config ARCH_MCF5445x + bool + select MCFV4M + +# +# Board selection +# +choice + prompt "Select your board" + +config MACH_KPUKDR1 + bool "konzeptpark UKD R1 + phyCore MCF5485" + select HAS_CFI + select ARCH_MCF54xx + help + Say Y here if you are using the konzeptpark UKD R1 with a + Phytec Phycore PCM-024 equipped with a Freescale MC5485 Processor + +config MACH_KPUKDR1_NUM + bool "konzeptpark UKD R1 + phyCore MCF5475 NUM" + select HAS_CFI + select ARCH_MCF54xx + help + Say Y here if you are using the konzeptpark UKD R1 with a + Phytec Phycore PCM-024-NUM equipped with a Freescale MC5475 Processor + +config MACH_KPUKDR2 + bool "konzeptpark UKD R2 + phyCore MCF5485" + select HAS_CFI + select ARCH_MCF54xx + help + Say Y here if you are using the konzeptpark UKD R2 with a + Phytec Phycore PCM-024 equipped with a Freescale MC5485 Processor + +config MACH_KPUKDR2_NUM + bool "konzeptpark UKD R2 + phyCore MCF5475 NUM" + select HAS_CFI + select ARCH_MCF54xx + help + Say Y here if you are using the konzeptpark UKD R2 with a + Phytec Phycore PCM-024-NUM equipped with a Freescale MC5475 Processor + +config MACH_PCM982_5485 + bool "Phytec pcm982 + phyCore MCF5485" + select HAS_CFI + select ARCH_MCF54xx + help + Say Y here if you are using the Phytec Phycore PCM-024 equipped + with a Freescale MC5485 Processor + +config MACH_PCM982_5475 + bool "Phytec pcm982 + phyCore MCF5475" + select HAS_CFI + select ARCH_MCF54xx + help + Say Y here if you are using the Phytec Phycore PCM-024 equipped + with a Freescale MC5475 Processor + +config MACH_PCM982_5475_NUM + bool "Phytec pcm982 + phyCore MCF5475 NUM" + select HAS_CFI + select ARCH_MCF54xx + help + Say Y here if you are using the Phytec Phycore PCM-024 equipped + with a Freescale MC5475 Processor (NUM Variant) + +config MACH_PCM982_54455 + bool "Phytec pcm982 + phyCore MCF54455 (experimental)" + select HAS_CFI + select ARCH_MCF5445x + help + Say Y here if you are using the Phytec Phycore PCM-mcf54455 equipped + with a Freescale MC54455 Processor (experimental) + +endchoice + +# +# M68k/Coldfire Subarch Configuration +# +source arch/m68k/mach-mcfv4e/Kconfig + +menu "M68k/Coldfire specific Linux boot settings" + +config CMDLINE_TAG + bool "Send commandline to kernel" + default y + help + If you want to start a 2.6 kernel say y here. + +config SETUP_MEMORY_TAGS + bool "send memory definition to kernel" + default y + help + If you want to start a 2.6 kernel say y here. + +config INITRD_TAG + bool "send initrd params to kernel" + default n + help + If you want to start a 2.6 kernel and use an + initrd image say y here. + +endmenu + +# +# Common U-Boot options +# + +source common/Kconfig +source commands/Kconfig +source net/Kconfig +source drivers/Kconfig +source fs/Kconfig +source lib/Kconfig diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile new file mode 100644 index 0000000000..e376354a45 --- /dev/null +++ b/arch/m68k/Makefile @@ -0,0 +1,105 @@ +# +# (C) Copyright 2007 Carsten Schlote +# See file CREDITS for list of people who contributed to this project. +# +# This file is part of U-Boot V2. +# +# U-Boot V2 is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# U-Boot V2 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with U-Boot V2. If not, see . +# + +CPPFLAGS += -fno-builtin -ffreestanding -nostdinc -Wall \ + -isystem $(gccincdir) -pipe -D __M68K__ \ + -fno-strict-aliasing + + +machine-$(CONFIG_ARCH_MCF54xx) := mcfv4e +board-$(CONFIG_MACH_KPUKDR1) := kp_ukd_r1 +board-$(CONFIG_MACH_KPUKDR1_NUM) := kp_ukd_r1_num +board-$(CONFIG_MACH_KPUKDR2) := kp_ukd_r2 +board-$(CONFIG_MACH_KPUKDR2_NUM) := kp_ukd_r2_num +board-$(CONFIG_MACH_PCM982_5485) := phycore_mcf54xx +board-$(CONFIG_MACH_PCM982_5475) := phycore_mcf54xx +board-$(CONFIG_MACH_PCM982_5475_NUM) := phycore_mcf54xx_num +board-$(CONFIG_MACH_PCM982_54455) := phycore_mcf5445x + +cpu-$(CONFIG_MCFV4E) := mcfv4e +cpu-$(CONFIG_MCFV4M) := mcfv4m + +TEXT_BASE = $(CONFIG_TEXT_BASE) + +CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -P +AFLAGS += -gdwarf-2 -save-temps +# FIXME - remove overide +CFLAGS := -Wall -Wundef -Wstrict-prototypes \ + -msoft-float -mcfv4e -gdwarf-2 -feliminate-unused-debug-types \ + -fmerge-all-constants -Os +# Incompatible code in U-Boot for -std=c99 +LDFLAGS_uboot :=-L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc +# --verbose --stats + +ifeq ($(incdir-y),) +incdir-y := $(machine-y) +endif +INCDIR := arch-$(incdir-y) + +# Update machine arch and proc symlinks if something which affects +# them changed. We use .arch to indicate when they were updated +# last, otherwise make uses the target directory mtime. + +include/asm-m68k/.arch: $(wildcard include/config/arch/*.h) include/config/auto.conf + @echo ' SYMLINK include/asm-m68k/arch -> include/asm-m68k/$(INCDIR)' +ifneq ($(KBUILD_SRC),) + $(Q)mkdir -p include/asm-m68k + $(Q)ln -fsn $(srctree)/include/asm-m68k/$(INCDIR) include/asm-m68k/arch +else + $(Q)ln -fsn $(INCDIR) include/asm-m68k/arch +endif + @echo ' SYMLINK include/asm-m68k/proc -> include/asm-m68k/proc-mcfv4e' +ifneq ($(KBUILD_SRC),) + $(Q)mkdir -p include/asm-m68k + $(Q)ln -fsn $(srctree)/include/asm-m68k/proc-mcfv4e include/asm-m68k/proc +else + $(Q)ln -fsn proc-mcfv4e include/asm-m68k/proc +endif + @touch $@ + + +all: $(KBUILD_IMAGE) + +archprepare: maketools + +PHONY += maketools +maketools: include/asm-m68k/.arch + + +ifneq ($(board-y),) +BOARD := board/$(board-y)/ +else +BOARD := +endif + +ifneq ($(machine-y),) +MACH := arch/m68k/mach-$(machine-y)/ +else +MACH := +endif + +common-y += $(BOARD) $(MACH) +common-y += arch/m68k/lib/ arch/m68k/cpu/ + +lds-$(CONFIG_GENERIC_LINKER_SCRIPT) := arch/m68k/lib/u-boot.lds +lds-$(CONFIG_BOARD_LINKER_SCRIPT) := $(BOARD)/u-boot.lds + +CLEAN_FILES += arch/m68k/lib/u-boot.lds +MRPROPER_FILES += include/asm-m68k/arch include/asm-m68k/proc diff --git a/arch/m68k/configs/phycore_kpukdr1_5475num_defconfig b/arch/m68k/configs/phycore_kpukdr1_5475num_defconfig new file mode 100644 index 0000000000..f867e511da --- /dev/null +++ b/arch/m68k/configs/phycore_kpukdr1_5475num_defconfig @@ -0,0 +1,196 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.0.0-rc4-git +# Tue Feb 19 13:41:25 2008 +# +CONFIG_BOARDINFO="konzeptpark UKD Prototype with Phycore MCF5475 NUM" +# CONFIG_BOARD_LINKER_SCRIPT is not set +CONFIG_GENERIC_LINKER_SCRIPT=y +CONFIG_M68K=y +CONFIG_MCFV4E=y +CONFIG_ARCH_MCF54xx=y +# CONFIG_MACH_KPUKDR1 is not set +CONFIG_MACH_KPUKDR1_NUM=y +# CONFIG_MACH_KPUKDR2 is not set +# CONFIG_MACH_KPUKDR2_NUM is not set +# CONFIG_MACH_PCM982_5485 is not set +# CONFIG_MACH_PCM982_5475 is not set +# CONFIG_MACH_PCM982_5475_NUM is not set +# CONFIG_MACH_PCM982_54455 is not set + +# +# M68k/Coldfire V4E specific settings +# +CONFIG_COPY_LOWMEM_VECTORS=y +# CONFIG_USE_LOWMEM_VECTORS is not set +CONFIG_CMD_REGDUMP_V4E=y +CONFIG_CMD_PCI_V4E=y + +# +# M68k/Coldfire specific Linux boot settings +# +CONFIG_CMDLINE_TAG=y +CONFIG_SETUP_MEMORY_TAGS=y +CONFIG_INITRD_TAG=y +CONFIG_GREGORIAN_CALENDER=y +CONFIG_HAS_KALLSYMS=y +CONFIG_HAS_MODULES=y +CONFIG_CMD_MEMORY=y +CONFIG_ENV_HANDLING=y + +# +# General Settings +# +CONFIG_TEXT_BASE=0x07f00000 +CONFIG_BROKEN=y +CONFIG_EXPERIMENTAL=y +# CONFIG_MODULES is not set +# CONFIG_KALLSYMS is not set +CONFIG_HAS_EARLY_INIT=y +CONFIG_EARLY_INITDATA_RAM_ADDR=0x20000000 +CONFIG_EARLY_INITDATA_RAM_SIZE=0x1f00 +CONFIG_EARLY_INITDATA_SIZE=0x100 +CONFIG_DEBUG_INITCALLS=y +CONFIG_USE_IRQ=y +CONFIG_PROMPT="uboot:" +CONFIG_BAUDRATE=115200 +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_LONGHELP=y +CONFIG_CBSIZE=1024 +CONFIG_MAXARGS=16 +CONFIG_SHELL_HUSH=y +# CONFIG_SHELL_SIMPLE is not set +# CONFIG_GLOB is not set +CONFIG_PROMPT_HUSH_PS2="> " +CONFIG_DYNAMIC_CRC_TABLE=y +CONFIG_ERRNO_MESSAGES=y +CONFIG_TIMESTAMP=y +CONFIG_CONSOLE_ACTIVATE_FIRST=y +CONFIG_EARLY_CONSOLE_PORT="psc0" +CONFIG_EARLY_CONSOLE_BAUDRATE=115200 +# CONFIG_OF_FLAT_TREE is not set +CONFIG_DEFAULT_ENVIRONMENT=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="board/kp_ukd_r1_num/env/" + +# +# Debugging +# +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL=y +# CONFIG_ENABLE_FLASH_NOISE is not set +# CONFIG_ENABLE_PARTITION_NOISE is not set +CONFIG_ENABLE_DEVICE_NOISE=y + +# +# Commands +# + +# +# scripting +# +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_HELP=y +CONFIG_CMD_READLINE=y + +# +# file commands +# +CONFIG_CMD_LS=y +CONFIG_CMD_RM=y +CONFIG_CMD_CAT=y +CONFIG_CMD_MKDIR=y +CONFIG_CMD_RMDIR=y +CONFIG_CMD_CP=y +CONFIG_CMD_PWD=y +CONFIG_CMD_CD=y +CONFIG_CMD_MOUNT=y +CONFIG_CMD_UMOUNT=y + +# +# console +# +CONFIG_CMD_CLEAR=y +CONFIG_CMD_ECHO=y +# CONFIG_CMD_SPLASH is not set + +# +# memory +# +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_CRC=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y + +# +# flash +# +CONFIG_CMD_FLASH=y + +# +# booting +# +CONFIG_CMD_BOOTM=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_TEST=y +CONFIG_NET=y +CONFIG_NET_BOOTP=y +CONFIG_NET_DHCP=y +CONFIG_NET_RARP=y +# CONFIG_NET_SNTP is not set +# CONFIG_NET_NFS is not set +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y + +# +# Drivers +# + +# +# serial drivers +# +CONFIG_DRIVER_SERIAL_MCFV4E=y +CONFIG_MIIPHY=y + +# +# Network drivers +# +CONFIG_DRIVER_NET_MCF54XX=y +# CONFIG_DRIVER_NET_MCF54XX_DEBUG is not set + +# +# SPI drivers +# +CONFIG_SPI=y +# CONFIG_DRIVER_SPI_MC13783 is not set + +# +# flash drivers +# +CONFIG_HAS_CFI=y +CONFIG_DRIVER_CFI=y +# CONFIG_DRIVER_CFI_NEW is not set +CONFIG_DRIVER_CFI_OLD=y +CONFIG_CFI_BUFFER_WRITE=y +# CONFIG_NAND is not set + +# +# Filesystem support +# +CONFIG_FS_CRAMFS=y +CONFIG_ZLIB=y +CONFIG_BZLIB=y +CONFIG_CRC32=y diff --git a/arch/m68k/configs/phycore_mcf54xx_defconfig b/arch/m68k/configs/phycore_mcf54xx_defconfig new file mode 100644 index 0000000000..7670c2095a --- /dev/null +++ b/arch/m68k/configs/phycore_mcf54xx_defconfig @@ -0,0 +1,196 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.0.1-csc +# Thu Mar 27 14:02:15 2008 +# +CONFIG_BOARDINFO="Phytec Baseboard with Phycore MCF5485" +# CONFIG_BOARD_LINKER_SCRIPT is not set +CONFIG_GENERIC_LINKER_SCRIPT=y +CONFIG_M68K=y +CONFIG_MCFV4E=y +CONFIG_ARCH_MCF54xx=y +# CONFIG_MACH_KPUKDR1 is not set +# CONFIG_MACH_KPUKDR1_NUM is not set +# CONFIG_MACH_KPUKDR2 is not set +# CONFIG_MACH_KPUKDR2_NUM is not set +CONFIG_MACH_PCM982_5485=y +# CONFIG_MACH_PCM982_5475 is not set +# CONFIG_MACH_PCM982_5475_NUM is not set +# CONFIG_MACH_PCM982_54455 is not set + +# +# M68k/Coldfire V4E specific settings +# +CONFIG_COPY_LOWMEM_VECTORS=y +# CONFIG_USE_LOWMEM_VECTORS is not set +CONFIG_CMD_REGDUMP_V4E=y +CONFIG_CMD_PCI_V4E=y + +# +# M68k/Coldfire specific Linux boot settings +# +CONFIG_CMDLINE_TAG=y +CONFIG_SETUP_MEMORY_TAGS=y +CONFIG_INITRD_TAG=y +CONFIG_GREGORIAN_CALENDER=y +CONFIG_HAS_KALLSYMS=y +CONFIG_HAS_MODULES=y +CONFIG_CMD_MEMORY=y +CONFIG_ENV_HANDLING=y + +# +# General Settings +# +CONFIG_TEXT_BASE=0x07f00000 +CONFIG_BROKEN=y +CONFIG_EXPERIMENTAL=y +# CONFIG_MODULES is not set +# CONFIG_KALLSYMS is not set +CONFIG_HAS_EARLY_INIT=y +CONFIG_EARLY_INITDATA_RAM_ADDR=0x20000000 +CONFIG_EARLY_INITDATA_RAM_SIZE=0x1f00 +CONFIG_EARLY_INITDATA_SIZE=0x100 +CONFIG_DEBUG_INITCALLS=y +CONFIG_USE_IRQ=y +CONFIG_PROMPT="uboot:" +CONFIG_BAUDRATE=115200 +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_LONGHELP=y +CONFIG_CBSIZE=1024 +CONFIG_MAXARGS=16 +CONFIG_SHELL_HUSH=y +# CONFIG_SHELL_SIMPLE is not set +# CONFIG_GLOB is not set +CONFIG_PROMPT_HUSH_PS2="> " +CONFIG_DYNAMIC_CRC_TABLE=y +CONFIG_ERRNO_MESSAGES=y +CONFIG_TIMESTAMP=y +CONFIG_CONSOLE_ACTIVATE_FIRST=y +CONFIG_EARLY_CONSOLE_PORT="psc0" +CONFIG_EARLY_CONSOLE_BAUDRATE=115200 +# CONFIG_OF_FLAT_TREE is not set +CONFIG_DEFAULT_ENVIRONMENT=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="board/phycore_mcf54xx/env" + +# +# Debugging +# +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL=y +# CONFIG_ENABLE_FLASH_NOISE is not set +# CONFIG_ENABLE_PARTITION_NOISE is not set +CONFIG_ENABLE_DEVICE_NOISE=y + +# +# Commands +# + +# +# scripting +# +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_HELP=y +CONFIG_CMD_READLINE=y + +# +# file commands +# +CONFIG_CMD_LS=y +CONFIG_CMD_RM=y +CONFIG_CMD_CAT=y +CONFIG_CMD_MKDIR=y +CONFIG_CMD_RMDIR=y +CONFIG_CMD_CP=y +CONFIG_CMD_PWD=y +CONFIG_CMD_CD=y +CONFIG_CMD_MOUNT=y +CONFIG_CMD_UMOUNT=y + +# +# console +# +CONFIG_CMD_CLEAR=y +CONFIG_CMD_ECHO=y +# CONFIG_CMD_SPLASH is not set + +# +# memory +# +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_CRC=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y + +# +# flash +# +CONFIG_CMD_FLASH=y + +# +# booting +# +CONFIG_CMD_BOOTM=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_TEST=y +CONFIG_NET=y +CONFIG_NET_BOOTP=y +CONFIG_NET_DHCP=y +CONFIG_NET_RARP=y +# CONFIG_NET_SNTP is not set +# CONFIG_NET_NFS is not set +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y + +# +# Drivers +# + +# +# serial drivers +# +CONFIG_DRIVER_SERIAL_MCFV4E=y +CONFIG_MIIPHY=y + +# +# Network drivers +# +CONFIG_DRIVER_NET_MCF54XX=y +# CONFIG_DRIVER_NET_MCF54XX_DEBUG is not set + +# +# SPI drivers +# +CONFIG_SPI=y +# CONFIG_DRIVER_SPI_MC13783 is not set + +# +# flash drivers +# +CONFIG_HAS_CFI=y +CONFIG_DRIVER_CFI=y +# CONFIG_DRIVER_CFI_NEW is not set +CONFIG_DRIVER_CFI_OLD=y +CONFIG_CFI_BUFFER_WRITE=y +# CONFIG_NAND is not set + +# +# Filesystem support +# +CONFIG_FS_CRAMFS=y +CONFIG_ZLIB=y +CONFIG_BZLIB=y +CONFIG_CRC32=y diff --git a/arch/m68k/cpu/Makefile b/arch/m68k/cpu/Makefile new file mode 100644 index 0000000000..4653534e47 --- /dev/null +++ b/arch/m68k/cpu/Makefile @@ -0,0 +1,41 @@ +# +# (C) Copyright 2007 Carsten Schlote +# See file CREDITS for list of people who contributed to this project. +# +# This file is part of U-Boot V2. +# +# U-Boot V2 is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# U-Boot V2 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with U-Boot V2. If not, see . +# + +obj-y += cpu.o +obj-y += interrupts.o + +# +# Support code for early IO over BDM wigglers +# + +# obj-y += early_init_support.o + +# +# Support for relocated early initdata +# +obj-$(CONFIG_HAS_EARLY_INIT) += early_init_support.o + +# +# Startup codes - try to merge them into single file! +# +obj-$(CONFIG_ARCH_MCF54xx) += start-mcfv4e.o +obj-$(CONFIG_ARCH_MCF5445x) += start-mcfv4m.o + +start-mcfv4e.o : start-mcfv4e.s \ No newline at end of file diff --git a/arch/m68k/cpu/cpu.c b/arch/m68k/cpu/cpu.c new file mode 100644 index 0000000000..5c48add8d9 --- /dev/null +++ b/arch/m68k/cpu/cpu.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * A few helper functions for M6kK/Coldfire + */ +#include +#include +#include +#include // FIXME -stup place +#include + +static uint32_t CACR_shadow = MCF5XXX_CACR_BEC; + +/* + * Reset init value := 0x010C0100 + * MCF5XXX_CACR_DCINVA + * MCF5XXX_CACR_BEC + * MCF5XXX_CACR_BCINVA + * MCF5XXX_CACR_ICINVA + */ + +/** + * Enable processor's instruction cache + */ +void icache_enable (void) +{ + CACR_shadow |= MCF5XXX_CACR_IEC; + mcf5xxx_wr_cacr( CACR_shadow ); +} + +/** + * Disable processor's instruction cache + */ +void icache_disable (void) +{ + CACR_shadow &= ~MCF5XXX_CACR_IEC; + mcf5xxx_wr_cacr( CACR_shadow ); +} + +/** + * Detect processor's current instruction cache status + * @return 0=disabled, 1=enabled + */ +int icache_status (void) +{ + return (CACR_shadow & MCF5XXX_CACR_IEC)?1:0; +} + +/** + * Enable processor's data cache + */ +void dcache_enable (void) +{ + CACR_shadow |= MCF5XXX_CACR_DEC; + mcf5xxx_wr_cacr( CACR_shadow ); +} + +/** + * Disable processor's data cache + */ +void dcache_disable (void) +{ + CACR_shadow &= ~MCF5XXX_CACR_DEC; + mcf5xxx_wr_cacr( CACR_shadow ); +} + +/** + * Detect processor's current instruction cache status + * @return 0=disabled, 1=enabled + */ +int dcache_status (void) +{ + return (CACR_shadow & MCF5XXX_CACR_DEC)?1:0; +} + +/** + * Flush CPU caches to memory + */ +void cpu_cache_flush(void) +{ + uint32_t way, set; + void *addr; + + for ( way=0; way < 4; way++ ) { + addr = (void*)way; + for ( set=0; set < 512; set++ ) { + mcf5xxx_cpushl_bc ( addr ); + addr += 0x10; + } + } +} + +/** + * Flush CPU caches to memory and disable them. + */ +void cpu_cache_disable(void) +{ + uint32_t lastipl; + + lastipl = asm_set_ipl( 7 ); + + cpu_cache_flush(); + mcf5xxx_wr_acr0( 0 ); + mcf5xxx_wr_acr1( 0 ); + mcf5xxx_wr_acr2( 0 ); + mcf5xxx_wr_acr3( 0 ); + + CACR_shadow &= ~MCF5XXX_CACR_IEC; + CACR_shadow &= ~MCF5XXX_CACR_DEC; + mcf5xxx_wr_cacr( CACR_shadow | (MCF5XXX_CACR_DCINVA|MCF5XXX_CACR_ICINVA)); + + lastipl = asm_set_ipl( lastipl ); +} + +/** + * Prepare a "clean" CPU for Linux to run + * @return 0 (always) + * + * This function is called by the generic U-Boot part just before we call + * Linux. It prepares the processor for Linux. + */ +int cleanup_before_linux (void) +{ + /* + * we never enable dcache so we do not need to disable + * it. Linux can be called with icache enabled, so just + * do nothing here + */ + + /* flush I/D-cache */ + cpu_cache_disable(); + + /* reenable icache */ + icache_enable(); + return (0); +} +/** @page m68k_boot_preparation Linux Preparation on M68k/Coldfire + * + * For M68K we never enable data cache so we do not need to disable it again. + * + * Linux can be called with instruction cache enabled. As this is the + * default setting we are running in U-Boot, there's no special preparation + * required. + */ + + +/** Early init of Coldfire V4E CPU + */ +static int cpu_init (void) +{ + /* Enable ICache - branch cache is already on */ + icache_enable(); + + /* + * setup up stacks if necessary + * setup other CPU specifics here to prepare + * handling of exceptions and interrupts + */ +#ifdef CONFIG_USE_IRQ + printf("Prepare CPU interrupts for handlers\n"); + mcf_interrupts_initialize(); +#endif + + return 0; +} + +core_initcall(cpu_init); diff --git a/arch/m68k/cpu/cw_console_io.c b/arch/m68k/cpu/cw_console_io.c new file mode 100644 index 0000000000..b0575e4c8a --- /dev/null +++ b/arch/m68k/cpu/cw_console_io.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Debug output stubs over BDM for Codewarrior + */ +#include +#include +#include +#include +#include + +#ifdef CONFIG_HAS_EARLY_INIT + + +#if 0 // FIXME - make a CW debug port serial driver for u-boot + +/* + * The result of an I/O command can be any one of the following. + */ +typedef enum DSIOResult +{ + kDSIONoError = 0x00, + kDSIOError = 0x01, + kDSIOEOF = 0x02 +} DSIOResult; + +/* + * MessageCommandID + */ +typedef enum MessageCommandID +{ + /* + * target->host support commands + */ + + kDSWriteFile = 0xD0, /* L2 L3 */ + kDSReadFile = 0xD1 /* L2 L3 */ + +} MessageCommandID; + + +enum DSIOResult TransferData( + MessageCommandID msg, + unsigned char *buffer, int size, + int * txsize +) +{ + enum DSIOResult iores = kDSIOError; + unsigned long sized2=0; + + /* -- Call codewarrior stub -- */ + __asm__ __volatile__ ( +" move.l %[cmd],%%d0 \n" +" move.l #0,%%d1 \n" +" move.l %[size],%%d2 \n" +" move.l %[buffer],%%d3 \n" +" trap #14 \n" +" move.l %%d1,%[txsize] \n" +" move.l %%d0,%[res] \n" + : [res] "=r" (iores), [txsize] "=g" (sized2) + : [cmd] "g" (msg), [size] "g" (size), [buffer] "g" (buffer) + : "d2","d3" ); + + if (txsize!=NULL) *txsize=sized2; + return iores; +} + +void *get_early_console_base(const char *name) +{ + return (void*)0xdeadbeef; +} + +static unsigned char early_iobuffer[80]; +static int early_iobuffer_cnt; + +void early_console_putc(void *base, char c) +{ + early_iobuffer[early_iobuffer_cnt++] = c; + if ( ( early_iobuffer_cnt >= sizeof(early_iobuffer)) || + (c == '\n') ) + { + TransferData(kDSWriteFile,early_iobuffer,early_iobuffer_cnt, NULL); + early_iobuffer_cnt = 0; + } +} + +void early_console_init(void *base, int baudrate) +{ + early_iobuffer_cnt = 0; +} + +//void early_console_start(const char *name, int baudrate) +//{ +//} + +#endif + +#endif diff --git a/arch/m68k/cpu/early_init_support.c b/arch/m68k/cpu/early_init_support.c new file mode 100644 index 0000000000..2f6be43539 --- /dev/null +++ b/arch/m68k/cpu/early_init_support.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Early InitData support routines + */ +#include +#include +#include +#include +#include + +#ifdef CONFIG_HAS_EARLY_INIT + +/** Returns relocation offset to early init data + */ +unsigned long reloc_offset(void) +{ + //extern char __early_init_data_begin[]; + //FIXME: return (unsigned long)init_data_ptr - (unsigned long)__early_init_data_begin; + return 0; +} + +#endif diff --git a/arch/m68k/cpu/interrupts.c b/arch/m68k/cpu/interrupts.c new file mode 100644 index 0000000000..16aac38ad5 --- /dev/null +++ b/arch/m68k/cpu/interrupts.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Interrupt routines and supporting code for Coldfire V4E + */ +#include +#include +#include + +#ifdef CONFIG_USE_IRQ +void enable_interrupts(void) +{ + asm_set_ipl(0); +} + +int disable_interrupts(void) +{ + return asm_set_ipl(7) ? 1 : 0; +} +#endif + +/** + */ +static void mcf_bad_mode (void) +{ + panic ("Resetting CPU ...\n"); + mdelay(3000); + reset_cpu (0); +} + +/** + */ +static void mcf_show_regs (struct pt_regs *regs) +{ + unsigned long flags; + flags = condition_codes (regs); + + printf ("pc : [<%08lx>]\n" + "sp : %08lx fp : %08lx\n", + instruction_pointer (regs), + regs->M68K_sp, regs->M68K_a6); + + printf ("d0-d3 : %08lx %08lx %08lx %08lx\n", + regs->M68K_d0, regs->M68K_d1, regs->M68K_d2, regs->M68K_d3); + printf ("d3-d7 : %08lx %08lx %08lx %08lx\n", + regs->M68K_d3, regs->M68K_d4, regs->M68K_d5, regs->M68K_d6); + + printf ("a0-d3 : %08lx %08lx %08lx %08lx\n", + regs->M68K_a0, regs->M68K_a1, regs->M68K_a2, regs->M68K_a3); + printf ("a3-d7 : %08lx %08lx %08lx %08lx\n", + regs->M68K_a3, regs->M68K_a4, regs->M68K_a5, regs->M68K_a6); + + printf ("fp0 : %08lx%08lx fp1 : %08lx%08lx\n", + regs->M68K_fp0+1, regs->M68K_fp0, regs->M68K_fp1+1, regs->M68K_fp1); + printf ("fp2 : %08lx%08lx fp3 : %08lx%08lx\n", + regs->M68K_fp2+1, regs->M68K_fp2, regs->M68K_fp3+1, regs->M68K_fp3); + printf ("fp4 : %08lx%08lx fp5 : %08lx%08lx\n", + regs->M68K_fp4+1, regs->M68K_fp4, regs->M68K_fp5+1, regs->M68K_fp5); + printf ("fp6 : %08lx%08lx fp7 : %08lx%08lx\n", + regs->M68K_fp6+1, regs->M68K_fp6, regs->M68K_fp7+1, regs->M68K_fp7); + + printf ("Flags: %c%c%c%c", + flags & CC_X_BIT ? 'X' : 'x', + flags & CC_N_BIT ? 'N' : 'n', + flags & CC_Z_BIT ? 'Z' : 'z', + flags & CC_V_BIT ? 'V' : 'v', + flags & CC_C_BIT ? 'C' : 'c' ); + + printf (" IRQs %s (%0x) Mode %s\n", + interrupts_enabled (regs) ? "on" : "off", interrupts_enabled (regs), + user_mode (regs) ? "user" : "supervisor"); +} + +void mcf_execute_exception_handler (struct pt_regs *pt_regs) +{ + printf ("unhandled exception\n"); + mcf_show_regs (pt_regs); + mcf_bad_mode (); +} + +#ifndef CONFIG_USE_IRQ + +void mcf_execute_irq_handler (struct pt_regs *pt_regs, int vector) +{ + printf ("interrupt request\n"); + mcf_show_regs (pt_regs); + mcf_bad_mode (); +} + +#else + +#ifndef CONFIG_MAX_ISR_HANDLERS +#define CONFIG_MAX_ISR_HANDLERS (20) +#endif + +typedef struct +{ + int vector; + int (*handler)(void *, void *); + void *hdev; + void *harg; +} +mcfv4e_irq_handler_s; + +mcfv4e_irq_handler_s irq_handler_table[CONFIG_MAX_ISR_HANDLERS]; + +/** Initialize an empty interrupt handler list + */ +void mcf_interrupts_initialize (void) +{ + int index; + for (index = 0; index < CONFIG_MAX_ISR_HANDLERS; index++) + { + irq_handler_table[index].vector = 0; + irq_handler_table[index].handler = 0; + irq_handler_table[index].hdev = 0; + irq_handler_table[index].harg = 0; + } +} + +/** Add an interrupt handler to the handler list + * + * @param vector : M68k exception/interrupt vector number + * @param handler : Pointer to handler function + * @param hdev : Handler specific data + * @param harg : Handler specific arg + */ +int mcf_interrupts_register_handler( + int vector, + int (*handler)(void *, void *), void *hdev, void *harg) +{ + /* + * This function places an interrupt handler in the ISR table, + * thereby registering it so that the low-level handler may call it. + * + * The two parameters are intended for the first arg to be a + * pointer to the device itself, and the second a pointer to a data + * structure used by the device driver for that particular device. + */ + int index; + + if ((vector == 0) || (handler == NULL)) + { + return 0; + } + + for (index = 0; index < CONFIG_MAX_ISR_HANDLERS; index++) + { + if (irq_handler_table[index].vector == vector) + { + /* only one entry of each type per vector */ + return 0; + } + + if (irq_handler_table[index].vector == 0) + { + irq_handler_table[index].vector = vector; + irq_handler_table[index].handler = handler; + irq_handler_table[index].hdev = hdev; + irq_handler_table[index].harg = harg; + return 1; + } + } + return 0; /* no available slots */ +} + +/** Remove an interrupt handler from the handler list + * + * @param type : FIXME + * @param handler : Pointer of handler function to remove. + */ +void mcf_interrupts_remove_handler (int type ,int (*handler)(void *, void *)) +{ + /* + * This routine removes from the ISR table all + * entries that matches 'handler'. + */ + int index; + + for (index = 0; index < CONFIG_MAX_ISR_HANDLERS; index++) + { + if (irq_handler_table[index].handler == handler) + { + irq_handler_table[index].vector = 0; + irq_handler_table[index].handler = 0; + irq_handler_table[index].hdev = 0; + irq_handler_table[index].harg = 0; + } + } +} + +/** Traverse list of registered interrupts and call matching handlers. + * + * @param pt_regs : Pointer to saved register context + * @param vector : M68k exception/interrupt vector number + */ +int mcf_execute_irq_handler (struct pt_regs *pt_regs, int vector) +{ + /* + * This routine searches the ISR table for an entry that matches + * 'vector'. If one is found, then 'handler' is executed. + */ + int index, retval = 0; + + /* + * Try to locate a user-registered Interrupt Service Routine handler. + */ + for (index = 0; index < CONFIG_MAX_ISR_HANDLERS; index++) + { + if (irq_handler_table[index].handler == NULL) + { + printf("\nFault: No handler for IRQ vector %ld found.\n", vector); + break; + } + if (irq_handler_table[index].vector == vector) + { + if (irq_handler_table[index].handler(irq_handler_table[index].hdev,irq_handler_table[index].harg)) + { + retval = 1; + break; + } + } + } + + return retval; +} + +#endif diff --git a/arch/m68k/cpu/start-mcfv4e.S b/arch/m68k/cpu/start-mcfv4e.S new file mode 100644 index 0000000000..c77fe676bb --- /dev/null +++ b/arch/m68k/cpu/start-mcfv4e.S @@ -0,0 +1,677 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Resetcode and exception/interrupt shells for Coldfire V4E + * + * This file contains the common startup code for use on at least Coldfire + * V4E cores: + * - MCF547x + * - MCF548x + */ +#include + + .section ".vectors","a" + +/* + * Define some addresses from your board configuration file + */ + .equ __MBAR,CFG_MBAR_ADDRESS + .globl __MBAR + + .equ __CORE_SRAM0,CFG_CORE0_SRAM_ADDRESS + .equ __CORE_SRAM0_SIZE,CFG_CORE0_SRAM_SIZE + + .equ __CORE_SRAM1,CFG_CORE1_SRAM_ADDRESS + .equ __CORE_SRAM1_SIZE,CFG_CORE1_SRAM_SIZE + + /* + * Preload stack pointer with end of Core SRAM - useable _after_ you have + * setup the MBR register in reset code! + * + * The upper 4 LW of the Core SRAM are left spare - it can be used as + * fixed address temporay storage in the code below (ok, well also to + * fix up stack traces in the debugger) + * + * So we have a stack usable for C code, before we even started SDRAM! + */ + .equ ___SP_INIT,__CORE_SRAM1+__CORE_SRAM1_SIZE-16 + +/* + * Vector table for M68k and U-Boot Link Address + * + * On M68k/Coldfire cores all exceptions and interrupts are routed through + * a vector array. This vector is by default at address 0x0000_0000, but + * can be moved to any other 1MB aligned address. + * + * We take advantage of this to move U-Boot out of low memory. Some BDM + * debuggers won't like a moved vector base and might need tweaking to + * work. + * + * Note: Respect alignment restrictions for TEXT_BASE, which must be + * 1MB aligned. + */ + + .globl _u_boot_start +_u_boot_start: + +VECTOR_TABLE: +_VECTOR_TABLE: +INITSP: .long ___SP_INIT /* Initial SP */ +INITPC: .long 0x410 /* Initial PC */ +vector02: .long _asm_exception_handler /* Access Error */ +vector03: .long _asm_exception_handler /* Address Error */ +vector04: .long _asm_exception_handler /* Illegal Instruction */ +vector05: .long _asm_exception_handler /* Divide by Zero */ +vector06: .long _asm_exception_handler /* Reserved */ +vector07: .long _asm_exception_handler /* Reserved */ +vector08: .long _asm_exception_handler /* Privilege Violation */ +vector09: .long _asm_exception_handler /* Trace */ +vector0A: .long _asm_exception_handler /* Unimplemented A-Line */ +vector0B: .long _asm_exception_handler /* Unimplemented F-Line */ +vector0C: .long _asm_exception_handler /* Non-PC Brkpt Debug Int */ +vector0D: .long _asm_exception_handler /* PC Brkpt Debug Int */ +vector0E: .long _asm_exception_handler /* Format Error */ +vector0F: .long _asm_exception_handler /* Unitialized Int */ +vector10: .long _asm_exception_handler /* Reserved */ +vector11: .long _asm_exception_handler /* Reserved */ +vector12: .long _asm_exception_handler /* Reserved */ +vector13: .long _asm_exception_handler /* Reserved */ +vector14: .long _asm_exception_handler /* Reserved */ +vector15: .long _asm_exception_handler /* Reserved */ +vector16: .long _asm_exception_handler /* Reserved */ +vector17: .long _asm_exception_handler /* Reserved */ +vector18: .long _asm_exception_handler /* Spurious Interrupt */ +vector19: .long _asm_isr_handler /* Autovector Level 1 */ +vector1A: .long _asm_isr_handler /* Autovector Level 2 */ +vector1B: .long _asm_isr_handler /* Autovector Level 3 */ +vector1C: .long _asm_isr_handler /* Autovector Level 4 */ +vector1D: .long _asm_isr_handler /* Autovector Level 5 */ +vector1E: .long _asm_isr_handler /* Autovector Level 6 */ +vector1F: .long _asm_isr_handler /* Autovector Level 7 */ +vector20: .long _asm_exception_handler /* TRAP #0 */ +vector21: .long _asm_exception_handler /* TRAP #1 */ +vector22: .long _asm_exception_handler /* TRAP #2 */ +vector23: .long _asm_exception_handler /* TRAP #3 */ +vector24: .long _asm_exception_handler /* TRAP #4 */ +vector25: .long _asm_exception_handler /* TRAP #5 */ +vector26: .long _asm_exception_handler /* TRAP #6 */ +vector27: .long _asm_exception_handler /* TRAP #7 */ +vector28: .long _asm_exception_handler /* TRAP #8 */ +vector29: .long _asm_exception_handler /* TRAP #9 */ +vector2A: .long _asm_exception_handler /* TRAP #10 */ +vector2B: .long _asm_exception_handler /* TRAP #11 */ +vector2C: .long _asm_exception_handler /* TRAP #12 */ +vector2D: .long _asm_exception_handler /* TRAP #13 */ +vector2E: .long _asm_exception_handler /* TRAP #14 */ +vector2F: .long _dbug_sc_handler /* TRAP #15 - System Call */ +vector30: .long _asm_exception_handler /* Reserved */ +vector31: .long _asm_exception_handler /* Reserved */ +vector32: .long _asm_exception_handler /* Reserved */ +vector33: .long _asm_exception_handler /* Reserved */ +vector34: .long _asm_exception_handler /* Reserved */ +vector35: .long _asm_exception_handler /* Reserved */ +vector36: .long _asm_exception_handler /* Reserved */ +vector37: .long _asm_exception_handler /* Reserved */ +vector38: .long _asm_exception_handler /* Reserved */ +vector39: .long _asm_exception_handler /* Reserved */ +vector3A: .long _asm_exception_handler /* Reserved */ +vector3B: .long _asm_exception_handler /* Reserved */ +vector3C: .long _asm_exception_handler /* Reserved */ +vector3D: .long _asm_exception_handler /* Unsupported Instruction */ +vector3E: .long _asm_exception_handler /* Reserved */ +vector3F: .long _asm_exception_handler /* Reserved */ +vector40: .long _asm_isr_handler /* User Defined Interrupts */ +vector41: .long _asm_isr_handler +vector42: .long _asm_isr_handler +vector43: .long _asm_isr_handler +vector44: .long _asm_isr_handler +vector45: .long _asm_isr_handler +vector46: .long _asm_isr_handler +vector47: .long _asm_isr_handler +vector48: .long _asm_isr_handler +vector49: .long _asm_isr_handler +vector4A: .long _asm_isr_handler +vector4B: .long _asm_isr_handler +vector4C: .long _asm_isr_handler +vector4D: .long _asm_isr_handler +vector4E: .long _asm_isr_handler +vector4F: .long _asm_isr_handler +vector50: .long _asm_isr_handler +vector51: .long _asm_isr_handler +vector52: .long _asm_isr_handler +vector53: .long _asm_isr_handler +vector54: .long _asm_isr_handler +vector55: .long _asm_isr_handler +vector56: .long _asm_isr_handler +vector57: .long _asm_isr_handler +vector58: .long _asm_isr_handler +vector59: .long _asm_isr_handler +vector5A: .long _asm_isr_handler +vector5B: .long _asm_isr_handler +vector5C: .long _asm_isr_handler +vector5D: .long _asm_isr_handler +vector5E: .long _asm_isr_handler +vector5F: .long _asm_isr_handler +vector60: .long _asm_isr_handler +vector61: .long _asm_isr_handler +vector62: .long _asm_isr_handler +vector63: .long _asm_isr_handler +vector64: .long _asm_isr_handler +vector65: .long _asm_isr_handler +vector66: .long _asm_isr_handler +vector67: .long _asm_isr_handler +vector68: .long _asm_isr_handler +vector69: .long _asm_isr_handler +vector6A: .long _asm_isr_handler +vector6B: .long _asm_isr_handler +vector6C: .long _asm_isr_handler +vector6D: .long _asm_isr_handler +vector6E: .long _asm_isr_handler +vector6F: .long _asm_isr_handler +vector70: .long _asm_isr_handler +vector71: .long _asm_isr_handler +vector72: .long _asm_isr_handler +vector73: .long _asm_isr_handler +vector74: .long _asm_isr_handler +vector75: .long _asm_isr_handler +vector76: .long _asm_isr_handler +vector77: .long _asm_isr_handler +vector78: .long _asm_isr_handler +vector79: .long _asm_isr_handler +vector7A: .long _asm_isr_handler +vector7B: .long _asm_isr_handler +vector7C: .long _asm_isr_handler +vector7D: .long _asm_isr_handler +vector7E: .long _asm_isr_handler +vector7F: .long _asm_isr_handler +vector80: .long _asm_isr_handler +vector81: .long _asm_isr_handler +vector82: .long _asm_isr_handler +vector83: .long _asm_isr_handler +vector84: .long _asm_isr_handler +vector85: .long _asm_isr_handler +vector86: .long _asm_isr_handler +vector87: .long _asm_isr_handler +vector88: .long _asm_isr_handler +vector89: .long _asm_isr_handler +vector8A: .long _asm_isr_handler +vector8B: .long _asm_isr_handler +vector8C: .long _asm_isr_handler +vector8D: .long _asm_isr_handler +vector8E: .long _asm_isr_handler +vector8F: .long _asm_isr_handler +vector90: .long _asm_isr_handler +vector91: .long _asm_isr_handler +vector92: .long _asm_isr_handler +vector93: .long _asm_isr_handler +vector94: .long _asm_isr_handler +vector95: .long _asm_isr_handler +vector96: .long _asm_isr_handler +vector97: .long _asm_isr_handler +vector98: .long _asm_isr_handler +vector99: .long _asm_isr_handler +vector9A: .long _asm_isr_handler +vector9B: .long _asm_isr_handler +vector9C: .long _asm_isr_handler +vector9D: .long _asm_isr_handler +vector9E: .long _asm_isr_handler +vector9F: .long _asm_isr_handler +vectorA0: .long _asm_isr_handler +vectorA1: .long _asm_isr_handler +vectorA2: .long _asm_isr_handler +vectorA3: .long _asm_isr_handler +vectorA4: .long _asm_isr_handler +vectorA5: .long _asm_isr_handler +vectorA6: .long _asm_isr_handler +vectorA7: .long _asm_isr_handler +vectorA8: .long _asm_isr_handler +vectorA9: .long _asm_isr_handler +vectorAA: .long _asm_isr_handler +vectorAB: .long _asm_isr_handler +vectorAC: .long _asm_isr_handler +vectorAD: .long _asm_isr_handler +vectorAE: .long _asm_isr_handler +vectorAF: .long _asm_isr_handler +vectorB0: .long _asm_isr_handler +vectorB1: .long _asm_isr_handler +vectorB2: .long _asm_isr_handler +vectorB3: .long _asm_isr_handler +vectorB4: .long _asm_isr_handler +vectorB5: .long _asm_isr_handler +vectorB6: .long _asm_isr_handler +vectorB7: .long _asm_isr_handler +vectorB8: .long _asm_isr_handler +vectorB9: .long _asm_isr_handler +vectorBA: .long _asm_isr_handler +vectorBB: .long _asm_isr_handler +vectorBC: .long _asm_isr_handler +vectorBD: .long _asm_isr_handler +vectorBE: .long _asm_isr_handler +vectorBF: .long _asm_isr_handler +vectorC0: .long _asm_isr_handler +vectorC1: .long _asm_isr_handler +vectorC2: .long _asm_isr_handler +vectorC3: .long _asm_isr_handler +vectorC4: .long _asm_isr_handler +vectorC5: .long _asm_isr_handler +vectorC6: .long _asm_isr_handler +vectorC7: .long _asm_isr_handler +vectorC8: .long _asm_isr_handler +vectorC9: .long _asm_isr_handler +vectorCA: .long _asm_isr_handler +vectorCB: .long _asm_isr_handler +vectorCC: .long _asm_isr_handler +vectorCD: .long _asm_isr_handler +vectorCE: .long _asm_isr_handler +vectorCF: .long _asm_isr_handler +vectorD0: .long _asm_isr_handler +vectorD1: .long _asm_isr_handler +vectorD2: .long _asm_isr_handler +vectorD3: .long _asm_isr_handler +vectorD4: .long _asm_isr_handler +vectorD5: .long _asm_isr_handler +vectorD6: .long _asm_isr_handler +vectorD7: .long _asm_isr_handler +vectorD8: .long _asm_isr_handler +vectorD9: .long _asm_isr_handler +vectorDA: .long _asm_isr_handler +vectorDB: .long _asm_isr_handler +vectorDC: .long _asm_isr_handler +vectorDD: .long _asm_isr_handler +vectorDE: .long _asm_isr_handler +vectorDF: .long _asm_isr_handler +vectorE0: .long _asm_isr_handler +vectorE1: .long _asm_isr_handler +vectorE2: .long _asm_isr_handler +vectorE3: .long _asm_isr_handler +vectorE4: .long _asm_isr_handler +vectorE5: .long _asm_isr_handler +vectorE6: .long _asm_isr_handler +vectorE7: .long _asm_isr_handler +vectorE8: .long _asm_isr_handler +vectorE9: .long _asm_isr_handler +vectorEA: .long _asm_isr_handler +vectorEB: .long _asm_isr_handler +vectorEC: .long _asm_isr_handler +vectorED: .long _asm_isr_handler +vectorEE: .long _asm_isr_handler +vectorEF: .long _asm_isr_handler +vectorF0: .long _asm_isr_handler +vectorF1: .long _asm_isr_handler +vectorF2: .long _asm_isr_handler +vectorF3: .long _asm_isr_handler +vectorF4: .long _asm_isr_handler +vectorF5: .long _asm_isr_handler +vectorF6: .long _asm_isr_handler +vectorF7: .long _asm_isr_handler +vectorF8: .long _asm_isr_handler +vectorF9: .long _asm_isr_handler +vectorFA: .long _asm_isr_handler +vectorFB: .long _asm_isr_handler +vectorFC: .long _asm_isr_handler +vectorFD: .long _asm_isr_handler +vectorFE: .long _asm_isr_handler +vectorFF: .long _asm_isr_handler + +/* + * Leave some bytes spare here for CW debugger (console IO stuff) + */ + .rept 4 + .long 0xdeadbeef + .endr + +/** @func reset Startup Code (reset vector) + * + * The vector array is mapped to address 0 at reset and SP and PC are + * fetched from adress 0 and 4. + * + * For debugger uploads this image will reside in the middle of RAM, leaving + * as much memory for other stuff in low memory available, e.g. Linux and + * an init ramdisk. + * + * For real system resets, the boot rom is mapped to all addresses in + * system, as long as somebody sets up the CS. Now the trick part until + * relocation to RAM is that we must code at the start of your bootrom + * - all link addresses are wrong, so we need the reloc.h stuff to find the + * right address. + * + * The following things happen here: + * * do important init, like SDRAM, only if we don't start from memory! + * * setup Memory and board specific bits prior to relocation. + * * Setup stack + * * relocate U-Boot to ram + * + */ + .globl _start +_start: + .global reset +reset: + /* Mask all IRQs */ + move.w #0x2700,%sr + + /* Initialize MBAR - keep D0/D1 registers */ + move.l #__MBAR,%d2 + movec %d2,%MBAR + nop + + /* Initialize RAMBAR0 - locate it on the data bus */ + move.l #__CORE_SRAM0,%d2 + add.l #0x21,%d2 + movec %d2,%RAMBAR0 + nop + + /* Initialize RAMBAR1 - locate it on the data bus */ + move.l #__CORE_SRAM1,%d2 + add.l #0x21,%d2 + movec %d2,%RAMBAR1 + nop + + /* Point Stack Pointer into Core SRAM temporarily */ + move.l #___SP_INIT,%d2 + move.l %d2,%sp + nop + + /* Invalidate the data, instruction, and branch caches */ + /* Turn on the branch cache */ + move.l #0x010C0100,%d2 + movec %d2,%cacr + nop + + /* Prepare stack top */ + clr.l %sp@(0) + move.l %d0,%sp@(4) + move.l %d1,%sp@(8) + clr.l %sp@(12) + + /* + * This call is intended to give all developers a chance to use a + * standard reset vector file, but also do some special things + * required only on their specific CPU. + */ +#ifdef ARCH_HAS_INIT_LOWLEVEL + bsr.l arch_init_lowlevel + nop +#endif + /* + * If the code vector table is not at TEXT_BASE and so this code + * as well, jump to the address mirror at FLASH ROM start address + * + * So load your image to TEXT_BASE for debugging or flash a binary + * image to your bootflash - code below will take proper action. + */ + lea.l %pc@(VECTOR_TABLE),%a0 + move.l #TEXT_BASE,%a1 + cmp.l %a0,%a1 + beq.s saveland + + /* + * Execution is not at TEXT_BASE. We assume entry to this code by + * a hardware reset and change execution to address of _FLASH_ rom. + */ + lea.l %pc@(saveland),%a0 // Effective ! Address of label below + move.l %a0,%d0 + and.l #0x00ffffff,%d0 // Cut away address high byte + move.l #CFG_FLASH_ADDRESS,%d1 // Get flash address + and.l #0xff000000,%d1 // and just take base for CS0 + or.l %d1,%d0 // Compose new address + move.l %d0,%a0 + jmp %a0@ // Jump to flash rom address! + nop + + /* We now either in SDRAM or FLASH START addresses, save to + change chip selects */ +saveland: + nop + + /* + * Before relocating, we have to setup RAM timing + * because memory timing is board-dependend, you will + * find a lowlevel_init.[c|S] in your board directory. + * + * Do not jump/call other u-boot code here! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bsr.l board_init_lowlevel + nop +#endif + + /* + * relocate U-Boot Code to RAM (including copy of vectors) + */ +relocate: + lea.l %pc@(VECTOR_TABLE),%a0 + move.l #TEXT_BASE,%a1 + move.l #__bss_start,%a3 + cmp.l %a0,%a1 + beq.s skip_relocate + + /* + * Calculate number of long words, and copy them to RAM + */ + move.l %a3,%d2 + sub.l %a1,%d2 + asr.l #2,%d2 +copy_loop: + move.l %a0@+,%a1@+ + subq.l #1,%d2 + bne.s copy_loop + +skip_relocate: + + /* Clear BSS segment in RAM */ +clear_bss: + move.l #__bss_end,%a4 + moveq.l #0,%d2 +clear_loop: + move.l %d2,%a3@+ + cmp.l %a4,%a3 + ble.s clear_loop + + /* + * Relocate Vectors to memory start (address 0) + * + * NOTE: It could be at other places, but debuggers expect + * this table to be at address 0. + */ +#ifdef CONFIG_COPY_LOWMEM_VECTORS +reloc_vectors: + lea.l %pc@(VECTOR_TABLE),%a0 + move.l #0,%a1 + cmp.l %a0,%a1 + beq.s skip_copy_vectors + + move.l #0x100,%d2 +copy_loop_vectors: + move.l %a0@+,%a1@+ + subq.l #1,%d2 + bne.s copy_loop_vectors +skip_copy_vectors: +#endif + +#ifndef CONFIG_USE_LOWMEM_VECTORS + move.l #TEXT_BASE,%d0 + movec %d0,%vbr + nop +#endif + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + /* + * Call other half of initcode in relocated code + * + * You allowed to call other U-Boot code from here + */ + jsr.l board_init_highlevel + nop +#endif + /* + * Now jump to real link address and U-Boot entry point + */ + nop + jmp.l start_uboot + nop + nop + +/* + * Interrupt handling + */ + +/* + * IRQ stack frame. + */ +#define S_FRAME_SIZE 148 + +#define S_SP S_A7 +#define S_SR 144 +#define S_PC 140 + +#define S_FPIAR 136 +#define S_FPSR 132 +#define S_FPCR 128 + +#define S_FP7 120 +#define S_FP6 112 +#define S_FP5 104 +#define S_FP4 96 +#define S_FP3 88 +#define S_FP2 80 +#define S_FP1 72 +#define S_FP0 64 + +#define S_A7 60 +#define S_A6 56 +#define S_A5 52 +#define S_A4 48 +#define S_A3 44 +#define S_A2 40 +#define S_A1 36 +#define S_A0 32 + +#define S_D7 28 +#define S_D6 24 +#define S_D5 20 +#define S_D4 16 +#define S_D3 12 +#define S_D2 8 +#define S_D1 4 +#define S_D0 0 + + +/* + * exception handlers + */ +#ifdef CONFIG_USE_IRQ + .global _dbug_sc_handler +_dbug_sc_handler: + .global _asm_exception_handler +_asm_exception_handler: + move.w #0x2700,%sr /* Disable IRQs */ + + move.l %sp,___SP_INIT /* Remember on top of stack */ + move.l #___SP_INIT,%sp /* Set stack to known area */ + + move.l %a0,%sp@- + lea _asm_context,%a0 + + movem.l %d0-%d7/%a0-%a7,%a0@ + + fmovem %fp0-%fp7,%a0@(S_FP0) + fmove.l %fpcr,%a0@(S_FPCR) + fmove.l %fpsr,%a0@(S_FPSR) + fmove.l %fpiar,%a0@(S_FPIAR) + + move.l %sp@+,%a0@(S_A0) + move.l %sp@,%a1 + move.l %a1,%a0@(S_SP) + move.l %a1@(4),%a0@(S_PC) + move.w %a1@(2),%a0@(S_SR) + + jsr cpu_cache_flush + nop + + move.l %a1,%sp@- + jsr mcf_execute_exception_handler + + + lea _asm_context,%a0 + move.l %a0@(S_SP),%sp + + move.l %a0@(S_D1),%d1 + move.l %a0@(S_D0),%d0 + move.l %a0@(S_A1),%a1 + move.l %a0@(S_A0),%a0 + + rte + nop + nop + + .global _asm_isr_handler +_asm_isr_handler: + link %a6,#-16 + movem.l %d0-%d1/%a0-%a1,%sp@ + + move.w %a6@(4),%d0 + lsr.l #2,%d0 + andi.l #0x0000FF,%d0 + move.l %d0,%sp@- + move.l #0,%a0 + move.l %a0,%sp@- + jsr mcf_execute_irq_handler + lea %sp@(8),%sp + cmpi.l #1,%d0 + beq handled + +nothandled: + movem.l %sp@,%d0-%d1/%a0-%a1 + unlk %a6 + jmp _asm_exception_handler + nop + +handled: + movem.l %sp@,%d0-%d1/%a0-%a1 + unlk %a6 + rte + nop + nop + +#else + + .global _dbug_sc_handler +_dbug_sc_handler: + .global _asm_exception_handler +_asm_exception_handler: + nop + // FIXME - do something useful here + rte + + .global _asm_isr_handler +_asm_isr_handler: + nop + // FIXME - do something useful here + rte + +#endif + + .data +_asm_context: + .space S_FRAME_SIZE,0x55 + + + .end diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile new file mode 100644 index 0000000000..52ea7e9542 --- /dev/null +++ b/arch/m68k/lib/Makefile @@ -0,0 +1,31 @@ +# +# (C) Copyright 2007 Carsten Schlote +# See file CREDITS for list of people who contributed to this project. +# +# This file is part of U-Boot V2. +# +# U-Boot V2 is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# U-Boot V2 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with U-Boot V2. If not, see . +# + +# +# Architecture dependant stubs and callbacks +# + +obj-y += m68k-meminit.o + +obj-$(CONFIG_CMD_BOOTM) += m68k-linuxboot.o + +obj-$(CONFIG_MODULES) += m68k-module.o + +extra-$(CONFIG_GENERIC_LINKER_SCRIPT) += u-boot.lds diff --git a/arch/m68k/lib/m68k-linuxboot.c b/arch/m68k/lib/m68k-linuxboot.c new file mode 100644 index 0000000000..63b0cc134d --- /dev/null +++ b/arch/m68k/lib/m68k-linuxboot.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file Linux boot preparation code. + * + * This file is responsible to start a linux kernel on + * Coldfire targets. + * + * @note Only Colilo mode supported yet. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +static int m68k_architecture = MACH_TYPE_GENERIC; + + +/* + * Setup M68k/Coldfire bootrecord info + */ +#if defined (CONFIG_SETUP_MEMORY_TAGS) || \ + defined (CONFIG_CMDLINE_TAG) || \ + defined (CONFIG_INITRD_TAG) + + +static void setup_boot_record(char* start_boot_rec, const char* command_line) +{ + struct bi_record* record; + + *start_boot_rec++ = 'C'; + *start_boot_rec++ = 'o'; + *start_boot_rec++ = 'L'; + *start_boot_rec++ = 'i'; + *start_boot_rec++ = 'L'; + *start_boot_rec++ = 'o'; + + record = (struct bi_record*) start_boot_rec; + + /* specify memory layout */ +#ifdef CONFIG_SETUP_MEMORY_TAGS + record->tag = BI_MEMCHUNK; + record->data[0] = 0; + record->data[1] = 64 * 1024 * 1024; // TODO: to be changed for different boards + record->size = sizeof (record->tag) + sizeof (record->size) + + sizeof (record->data[0]) + sizeof (record->data[0]); + record = (struct bi_record *) ((void *) record + record->size); +#endif + + /* add a kernel command line */ +#ifdef CONFIG_CMDLINE_TAG + record->tag = BI_COMMAND_LINE; + strcpy ((char *) &record->data, command_line); + record->size = sizeof (record->tag) + sizeof (record->size) + + max (sizeof (record->data[0]), strlen (command_line)+1); + record = (struct bi_record *) ((void *) record + record->size); +#endif + + /* Add reference to initrd */ +#ifdef CONFIG_INITRD_TAG +#endif + + /* Mark end of tags */ + record->tag = 0; + record->data[0] = 0; + record->data[1] = 0; + record->size = sizeof(record->tag) + sizeof (record->size) + + sizeof (record->data[0]) + sizeof (record->data[0]); +} + +#else +#define setup_boot_record(start_boot_rec,command_line) while (0) { } + +#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ + + +static int do_bootm_linux(struct image_data *data) +{ + image_header_t *os_header = &data->os->header; + void (*theKernel)(int zero, int arch, uint params); + const char *commandline = getenv ("bootargs"); + uint32_t loadaddr,loadsize; + + if (os_header->ih_type == IH_TYPE_MULTI) { + printf("Multifile images not handled at the moment\n"); + return -1; + } + + printf("commandline: %s\n", commandline); + + theKernel = (void (*)(int,int,uint))ntohl((os_header->ih_ep)); + + debug ("## Transferring control to Linux (at address %08lx) ...\n", + (ulong) theKernel); + + loadaddr = (uint32_t)ntohl(os_header->ih_load); + loadsize = (uint32_t)ntohl(os_header->ih_size); + setup_boot_record( (char*)(loadaddr+loadsize),(char*)commandline); + + if (relocate_image(data->os, (void *)loadaddr)) + return -1; + + /* we assume that the kernel is in place */ + printf ("\nStarting kernel image at 0x%08x size 0x%08x eentry 0x%08x\n\n", + loadaddr, loadsize, (ulong) theKernel); + + /* Bring board into inactive post-reset state again */ + cleanup_before_linux (); + + /* Jump to kernel entry point */ + theKernel (0, m68k_architecture, 0xdeadbeaf); + + enable_interrupts(); + printf("Error: Loaded kernel returned. Probably it couldn't\n" + "find it's bootrecord.\n"); + return -1; +} + +/* + * Register handler for m68k Kernel Images + */ +static int image_handle_cmdline_parse(struct image_data *data, int opt, char *optarg) +{ + switch (opt) + { + case 'a': + m68k_architecture = simple_strtoul(optarg, NULL, 0); + return 0; + default: + return 1; + } +} + +static struct image_handler handler = +{ + .cmdline_options = "a:", + .cmdline_parse = image_handle_cmdline_parse, + .help_string = " -a use architecture number ", + + .bootm = do_bootm_linux, + .image_type = IH_OS_LINUX, +}; + +static int m68klinux_register_image_handler(void) +{ + return register_image_handler(&handler); +} + +late_initcall(m68klinux_register_image_handler); diff --git a/arch/m68k/lib/m68k-meminit.c b/arch/m68k/lib/m68k-meminit.c new file mode 100644 index 0000000000..b7905c2851 --- /dev/null +++ b/arch/m68k/lib/m68k-meminit.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Init for memory allocator on m68k/Coldfire + */ +#include +#include +#include +#include +#include + +/** Initialize mem allocator on M68k/Coldfire + */ +int m68k_mem_malloc_init(void) +{ + /* Pass start and end address of managed memory */ + + mem_malloc_init((void *)(&_u_boot_start - CFG_MALLOC_LEN), + (void *)&_u_boot_start); + + return 0; +} + +core_initcall(m68k_mem_malloc_init); diff --git a/arch/m68k/lib/m68k-module.c b/arch/m68k/lib/m68k-module.c new file mode 100644 index 0000000000..e1fe461a3a --- /dev/null +++ b/arch/m68k/lib/m68k-module.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Moduleloader Subsystem + * + * These relocation stubs are taken from Linux 2.6.10 They are used by the + * higher level ELF loader code to place ELF files to arbitrary addresses. + */ +#include +#include +#include +#include + +int apply_relocate(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_68K_32: + /* We add the value into the location given */ + *location += sym->st_value; + break; + case R_68K_PC32: + /* Add the value, subtract its postition */ + *location += sym->st_value - (uint32_t)location; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate_add section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_68K_32: + /* We add the value into the location given */ + *location = rel[i].r_addend + sym->st_value; + break; + case R_68K_PC32: + /* Add the value, subtract its postition */ + *location = rel[i].r_addend + sym->st_value - (uint32_t)location; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} diff --git a/arch/m68k/lib/u-boot.lds.S b/arch/m68k/lib/u-boot.lds.S new file mode 100644 index 0000000000..823e17a9de --- /dev/null +++ b/arch/m68k/lib/u-boot.lds.S @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Generic Linker file for M68k targets + */ +#include + +OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", + "elf32-m68k") +OUTPUT_ARCH(m68k) +ENTRY(_start) +SECTIONS +{ + . = TEXT_BASE; + . = ALIGN(4); + + /* Start of vector, text and rodata section */ + _stext = .; + _text = .; + + /* M68k/CF style vector table */ + .vectors : + { + *(.vectors) + } + + .text : + { + *(.text .stub .text.*) + } =0x4e754e75 + + . = ALIGN(4); + .rodata : + { + *(.rodata .rodata.*) + } =0xdeadbeef + + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { U_BOOT_CMDS } + __u_boot_cmd_end = .; + + __u_boot_initcalls_start = .; + .u_boot_initcalls : { INITCALLS } + __u_boot_initcalls_end = .; + + __usymtab_start = .; + __usymtab : { U_BOOT_SYMS } + __usymtab_end = .; + + /* End of text and rodata section */ + . = ALIGN(4); + _etext = .; + + . = ALIGN(4); + .got : { *(.got) } + . = ALIGN(4); + + . = ALIGN(4); + __early_init_data_begin = .; + .early_init_data : { *(.early_init_data) } + __early_init_data_end = .; + + .data : { *(.data .data.*) } + + . = ALIGN(4); + __bss_start = .; + .bss (NOLOAD) : { *(.bss .bass.*) } + __bss_end =.; + _end = .; + + . = ALIGN(4); + _u_boot_heap_start = .; +} diff --git a/arch/m68k/mach-mcfv4e.dox b/arch/m68k/mach-mcfv4e.dox new file mode 100644 index 0000000000..0ecfbc2c9d --- /dev/null +++ b/arch/m68k/mach-mcfv4e.dox @@ -0,0 +1,39 @@ +/* This document is intended to provide the developer with information + * how to integrate a new CPU (MACH) into this part of the U-Boot tree + */ + +/** @page dev_m68k_mach M68k/Coldfire based CPU (MACH) into the tree + +FIXME - fill in further info about Coldfire and so on. Check code + for compliance with the specs given below - move code otherwise. + +@par What's happens when the reset signal is gone + +@note Code running immediately after reset runs at an address it is not linked + to: "runtime address != link address". You should only use branches and + do not refer to fixed data. This implies the use of assembler code only. + +The M68k CPU starts at lable \ in one of the corresponding start-*.S +files. After some basic hardware setup it can call a function +\ if not disabled. This call is intended to give all +developers a chance to use a standard reset vector file, but also do some +special things required only on their specific CPU. + +After handling some MMU, Stack or similiar issues, \ can +be called (if not disabled). This is a board specific function for SDRAM setup +for example. As its board specific, your can do whatever you need to bring +your board up. As stack is already set to internal core RAM, this routine can +be C. + +@note: You are not allowed to call other code here, because we are not running + at link address. + +When \ returns it will be assumed that there is now +working RAM that can be used for all further steps. + +Next step is relocation of U-Boot itself. It gets copied to the end of +available RAM and the last assembly instruction is a jump to \. + +At this point of time: "runtime address == link address". + +*/ diff --git a/arch/m68k/mach-mcfv4e/Kconfig b/arch/m68k/mach-mcfv4e/Kconfig new file mode 100644 index 0000000000..aaba27e5e8 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/Kconfig @@ -0,0 +1,18 @@ + +menu "M68k/Coldfire V4E specific settings" + +config COPY_LOWMEM_VECTORS + bool "Copy vectors to SDRAM address 0" + default y + help + This copies the vector table to SDRAM address 0 (default address) + +config USE_LOWMEM_VECTORS + bool "Use vectors at SDRAM address 0" + default n + depends on COPY_LOWMEM_VECTORS + help + This copies the vector table to SDRAM address 0 (default address) and + also uses this vector location + +endmenu diff --git a/arch/m68k/mach-mcfv4e/Makefile b/arch/m68k/mach-mcfv4e/Makefile new file mode 100644 index 0000000000..f75834be54 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/Makefile @@ -0,0 +1,19 @@ +# +# Generic code for Coldfire V4E targets (MCF547x/MCF548x) +# +obj-y += mcf_clocksource.o +obj-y += mcf_reset_cpu.o + +# +# FEC support +# +obj-y += multichannel_dma.o +obj-y += dma_utils.o +obj-y += fec.o +obj-y += fecbd.o + +# +# FreeScale MultiDMA Library +# +obj-y += mcdapi/ +obj-y += net/ diff --git a/arch/m68k/mach-mcfv4e/dma_utils.c b/arch/m68k/mach-mcfv4e/dma_utils.c new file mode 100644 index 0000000000..15b520abc2 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/dma_utils.c @@ -0,0 +1,502 @@ +/* + * File: dma_utils.c + * Purpose: General purpose utilities for the multi-channel DMA + * + * Notes: The methodology used in these utilities assumes that + * no single initiator will be tied to more than one + * task/channel + */ + +#include +#include +#include +#include +#include + +#include + +/* + * This global keeps track of which initiators have been + * used of the available assignments. Initiators 0-15 are + * hardwired. Initiators 16-31 are multiplexed and controlled + * via the Initiatior Mux Control Registe (IMCR). The + * assigned requestor is stored with the associated initiator + * number. + */ +static int8_t used_reqs[32] = +{ + DMA_ALWAYS, DMA_DSPI_RX, DMA_DSPI_TX, DMA_DREQ0, + DMA_PSC0_RX, DMA_PSC0_TX, DMA_USBEP0, DMA_USBEP1, + DMA_USBEP2, DMA_USBEP3, DMA_PCI_TX, DMA_PCI_RX, + DMA_PSC1_RX, DMA_PSC1_TX, DMA_I2C_RX, DMA_I2C_TX, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; + +/* + * This global keeps track of which channels have been assigned + * to tasks. This methology assumes that no single initiator + * will be tied to more than one task/channel + */ +typedef struct +{ + int req; + void (*handler)(void); +} DMA_CHANNEL_STRUCT; + +static DMA_CHANNEL_STRUCT dma_channel[NCHANNELS] = +{ + {-1,NULL}, {-1,NULL}, {-1,NULL}, {-1,NULL}, + {-1,NULL}, {-1,NULL}, {-1,NULL}, {-1,NULL}, + {-1,NULL}, {-1,NULL}, {-1,NULL}, {-1,NULL}, + {-1,NULL}, {-1,NULL}, {-1,NULL}, {-1,NULL} +}; + +/* + * Enable all DMA interrupts + * + * Parameters: + * pri Interrupt Priority + * lvl Interrupt Level + */ +void +dma_irq_enable(uint8_t lvl, uint8_t pri) +{ +//FIXME ASSERT(lvl > 0 && lvl < 8); +//FIXME ASSERT(pri < 8); + + /* Setup the DMA ICR (#48) */ + MCF_INTC_ICR48 = 0 + | MCF_INTC_ICRn_IP(pri) + | MCF_INTC_ICRn_IL(lvl); + + /* Unmask all task interrupts */ + MCF_DMA_DIMR = 0; + + /* Clear the interrupt pending register */ + MCF_DMA_DIPR = 0; + + /* Unmask the DMA interrupt in the interrupt controller */ + MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK48; +} + +/* + * Disable all DMA interrupts + */ +void +dma_irq_disable(void) +{ + /* Mask all task interrupts */ + MCF_DMA_DIMR = (uint32_t)~0; + + /* Clear any pending task interrupts */ + MCF_DMA_DIPR = (uint32_t)~0; + + /* Mask the DMA interrupt in the interrupt controller */ + MCF_INTC_IMRH |= MCF_INTC_IMRH_INT_MASK48; +} + +/* + * Attempt to enable the provided Initiator in the Initiator + * Mux Control Register + * + * Parameters: + * initiator Initiator identifier + * + * Return Value: + * 1 if unable to make the assignment + * 0 successful + */ +int +dma_set_initiator(int initiator) +{ + switch (initiator) + { + /* These initiators are always active */ + case DMA_ALWAYS: + case DMA_DSPI_RX: + case DMA_DSPI_TX: + case DMA_DREQ0: + case DMA_PSC0_RX: + case DMA_PSC0_TX: + case DMA_USBEP0: + case DMA_USBEP1: + case DMA_USBEP2: + case DMA_USBEP3: + case DMA_PCI_TX: + case DMA_PCI_RX: + case DMA_PSC1_RX: + case DMA_PSC1_TX: + case DMA_I2C_RX: + case DMA_I2C_TX: + break; + case DMA_FEC0_RX: + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC16(3)) + | MCF_DMA_IMCR_SRC16_FEC0RX; + used_reqs[16] = DMA_FEC0_RX; + break; + case DMA_FEC0_TX: + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC17(3)) + | MCF_DMA_IMCR_SRC17_FEC0TX; + used_reqs[17] = DMA_FEC0_TX; + break; + case DMA_FEC1_RX: + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC20(3)) + | MCF_DMA_IMCR_SRC20_FEC1RX; + used_reqs[20] = DMA_FEC1_RX; + break; + case DMA_FEC1_TX: + if (used_reqs[21] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC21(3)) + | MCF_DMA_IMCR_SRC21_FEC1TX; + used_reqs[21] = DMA_FEC1_TX; + } + else if (used_reqs[25] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC25(3)) + | MCF_DMA_IMCR_SRC25_FEC1TX; + used_reqs[25] = DMA_FEC1_TX; + } + else if (used_reqs[31] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC31(3)) + | MCF_DMA_IMCR_SRC31_FEC1TX; + used_reqs[31] = DMA_FEC1_TX; + } + else /* No empty slots */ + return 1; + break; + case DMA_DREQ1: + if (used_reqs[29] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC29(3)) + | MCF_DMA_IMCR_SRC29_DREQ1; + used_reqs[29] = DMA_DREQ1; + } + else if (used_reqs[21] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC21(3)) + | MCF_DMA_IMCR_SRC21_DREQ1; + used_reqs[21] = DMA_DREQ1; + } + else /* No empty slots */ + return 1; + break; + case DMA_CTM0: + if (used_reqs[24] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC24(3)) + | MCF_DMA_IMCR_SRC24_CTM0; + used_reqs[24] = DMA_CTM0; + } + else /* No empty slots */ + return 1; + break; + case DMA_CTM1: + if (used_reqs[25] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC25(3)) + | MCF_DMA_IMCR_SRC25_CTM1; + used_reqs[25] = DMA_CTM1; + } + else /* No empty slots */ + return 1; + break; + case DMA_CTM2: + if (used_reqs[26] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC26(3)) + | MCF_DMA_IMCR_SRC26_CTM2; + used_reqs[26] = DMA_CTM2; + } + else /* No empty slots */ + return 1; + break; + case DMA_CTM3: + if (used_reqs[27] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC27(3)) + | MCF_DMA_IMCR_SRC27_CTM3; + used_reqs[27] = DMA_CTM3; + } + else /* No empty slots */ + return 1; + break; + case DMA_CTM4: + if (used_reqs[28] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC28(3)) + | MCF_DMA_IMCR_SRC28_CTM4; + used_reqs[28] = DMA_CTM4; + } + else /* No empty slots */ + return 1; + break; + case DMA_CTM5: + if (used_reqs[29] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC29(3)) + | MCF_DMA_IMCR_SRC29_CTM5; + used_reqs[29] = DMA_CTM5; + } + else /* No empty slots */ + return 1; + break; + case DMA_CTM6: + if (used_reqs[30] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC30(3)) + | MCF_DMA_IMCR_SRC30_CTM6; + used_reqs[30] = DMA_CTM6; + } + else /* No empty slots */ + return 1; + break; + case DMA_CTM7: + if (used_reqs[31] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC31(3)) + | MCF_DMA_IMCR_SRC31_CTM7; + used_reqs[31] = DMA_CTM7; + } + else /* No empty slots */ + return 1; + break; + case DMA_USBEP4: + if (used_reqs[26] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC26(3)) + | MCF_DMA_IMCR_SRC26_USBEP4; + used_reqs[26] = DMA_USBEP4; + } + else /* No empty slots */ + return 1; + break; + case DMA_USBEP5: + if (used_reqs[27] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC27(3)) + | MCF_DMA_IMCR_SRC27_USBEP5; + used_reqs[27] = DMA_USBEP5; + } + else /* No empty slots */ + return 1; + break; + case DMA_USBEP6: + if (used_reqs[28] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC28(3)) + | MCF_DMA_IMCR_SRC28_USBEP6; + used_reqs[28] = DMA_USBEP6; + } + else /* No empty slots */ + return 1; + break; + case DMA_PSC2_RX: + if (used_reqs[28] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC28(3)) + | MCF_DMA_IMCR_SRC28_PSC2RX; + used_reqs[28] = DMA_PSC2_RX; + } + else /* No empty slots */ + return 1; + break; + case DMA_PSC2_TX: + if (used_reqs[29] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC29(3)) + | MCF_DMA_IMCR_SRC29_PSC2TX; + used_reqs[29] = DMA_PSC2_TX; + } + else /* No empty slots */ + return 1; + break; + case DMA_PSC3_RX: + if (used_reqs[30] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC30(3)) + | MCF_DMA_IMCR_SRC30_PSC3RX; + used_reqs[30] = DMA_PSC3_RX; + } + else /* No empty slots */ + return 1; + break; + case DMA_PSC3_TX: + if (used_reqs[31] == 0) + { + MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC31(3)) + | MCF_DMA_IMCR_SRC31_PSC3TX; + used_reqs[31] = DMA_PSC3_TX; + } + else /* No empty slots */ + return 1; + break; + default: + return 1; + } + return 0; +} + +/* + * Return the initiator number for the given requestor + * + * Parameters: + * requestor Initiator/Requestor identifier + * + * Return Value: + * The initiator number (0-31) if initiator has been assigned + * 0 (always initiator) otherwise + */ +uint32_t +dma_get_initiator(int requestor) +{ + uint32_t i; + + for (i=0; i>=1) + { + if (interrupts & 0x1) + { + /* If there is a handler, call it */ + if (dma_channel[i].handler != NULL) + dma_channel[i].handler(); + } + } + + enable_interrupts(); // board_irq_enable(); + return 1; +} diff --git a/arch/m68k/mach-mcfv4e/fec.c b/arch/m68k/mach-mcfv4e/fec.c new file mode 100644 index 0000000000..551f00f005 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/fec.c @@ -0,0 +1,1440 @@ +/* + * File: fec.c + * Purpose: Driver for the Fast Ethernet Controller (FEC) + * + * Notes: + */ +#include +#include + +#include +#include +#include +#include +#include +#include + + +#define TRUE 1 +#define FALSE 0 +#define ASSERT(x) if (!(x)) hang(); +#define nop() __asm__ __volatile__("nop\n") + + +FEC_EVENT_LOG fec_log[2]; + +/* + * Write a value to a PHY's MII register. + * + * Parameters: + * ch FEC channel + * phy_addr Address of the PHY. + * reg_addr Address of the register in the PHY. + * data Data to be written to the PHY register. + * + * Return Values: + * 1 on failure + * 0 on success. + * + * Please refer to your PHY manual for registers and their meanings. + * mii_write() polls for the FEC's MII interrupt event (which should + * be masked from the interrupt handler) and clears it. If after a + * suitable amount of time the event isn't triggered, a value of 0 + * is returned. + */ +int +fec_mii_write(uint8_t ch, uint8_t phy_addr, uint8_t reg_addr, uint16_t data) +{ + int timeout; + uint32_t eimr; + + ASSERT(ch == 0 || ch == 1); + + /* + * Clear the MII interrupt bit + */ + MCF_FEC_EIR(ch) = MCF_FEC_EIR_MII; + + /* + * Write to the MII Management Frame Register to kick-off + * the MII write + */ + MCF_FEC_MMFR(ch) = 0 + | MCF_FEC_MMFR_ST_01 + | MCF_FEC_MMFR_OP_WRITE + | MCF_FEC_MMFR_PA(phy_addr) + | MCF_FEC_MMFR_RA(reg_addr) + | MCF_FEC_MMFR_TA_10 + | MCF_FEC_MMFR_DATA(data); + + /* + * Mask the MII interrupt + */ + eimr = MCF_FEC_EIMR(ch); + MCF_FEC_EIMR(ch) &= ~MCF_FEC_EIMR_MII; + + /* + * Poll for the MII interrupt (interrupt should be masked) + */ + for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++) + { + if (MCF_FEC_EIR(ch) & MCF_FEC_EIR_MII) + break; + } + if(timeout == FEC_MII_TIMEOUT) + return 1; + + /* + * Clear the MII interrupt bit + */ + MCF_FEC_EIR(ch) = MCF_FEC_EIR_MII; + + /* + * Restore the EIMR + */ + MCF_FEC_EIMR(ch) = eimr; + + return 0; +} + +/* + * Read a value from a PHY's MII register. + * + * Parameters: + * ch FEC channel + * phy_addr Address of the PHY. + * reg_addr Address of the register in the PHY. + * data Pointer to storage for the Data to be read + * from the PHY register (passed by reference) + * + * Return Values: + * 1 on failure + * 0 on success. + * + * Please refer to your PHY manual for registers and their meanings. + * mii_read() polls for the FEC's MII interrupt event (which should + * be masked from the interrupt handler) and clears it. If after a + * suitable amount of time the event isn't triggered, a value of 0 + * is returned. + */ +int +fec_mii_read(uint8_t ch, uint8_t phy_addr, uint8_t reg_addr, uint16_t *data) +{ + int timeout; + + ASSERT(ch == 0 || ch == 1); + + /* + * Clear the MII interrupt bit + */ + MCF_FEC_EIR(ch) = MCF_FEC_EIR_MII; + + /* + * Write to the MII Management Frame Register to kick-off + * the MII read + */ + MCF_FEC_MMFR(ch) = 0 + | MCF_FEC_MMFR_ST_01 + | MCF_FEC_MMFR_OP_READ + | MCF_FEC_MMFR_PA(phy_addr) + | MCF_FEC_MMFR_RA(reg_addr) + | MCF_FEC_MMFR_TA_10; + + /* + * Poll for the MII interrupt (interrupt should be masked) + */ + for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++) + { + if (MCF_FEC_EIR(ch) & MCF_FEC_EIR_MII) + break; + } + + if(timeout == FEC_MII_TIMEOUT) + return 1; + + /* + * Clear the MII interrupt bit + */ + MCF_FEC_EIR(ch) = MCF_FEC_EIR_MII; + + *data = (uint16_t)(MCF_FEC_MMFR(ch) & 0x0000FFFF); + + return 0; +} + +/* + * Initialize the MII interface controller + * + * Parameters: + * ch FEC channel + * sys_clk System Clock Frequency (in MHz) + */ +void +fec_mii_init(uint8_t ch, uint32_t sys_clk) +{ + ASSERT(ch == 0 || ch == 1); + + /* + * Initialize the MII clock (EMDC) frequency + * + * Desired MII clock is 2.5MHz + * MII Speed Setting = System_Clock / (2.5MHz * 2) + * (plus 1 to make sure we round up) + */ + MCF_FEC_MSCR(ch) = MCF_FEC_MSCR_MII_SPEED((sys_clk/5)+1); +} + +/* Initialize the MIB counters + * + * Parameters: + * ch FEC channel + */ +void +fec_mib_init(uint8_t ch) +{ + ASSERT(ch == 0 || ch == 1); +//To do +} + +/* Display the MIB counters + * + * Parameters: + * ch FEC channel + */ +void +fec_mib_dump(uint8_t ch) +{ + ASSERT(ch == 0 || ch == 1); +//To do +} + +/* Initialize the FEC log + * + * Parameters: + * ch FEC channel + */ +void +fec_log_init(uint8_t ch) +{ + ASSERT(ch == 0 || ch == 1); + memset(&fec_log[ch],0,sizeof(FEC_EVENT_LOG)); +} + +/* Display the FEC log + * + * Parameters: + * ch FEC channel + */ +void +fec_log_dump(uint8_t ch) +{ + ASSERT(ch == 0 || ch == 1); + printf("\n FEC%d Log\n---------------\n",ch); + printf("Total: %4d\n",fec_log[ch].total); + printf("hberr: %4d\n",fec_log[ch].hberr); + printf("babr: %4d\n",fec_log[ch].babr); + printf("babt: %4d\n",fec_log[ch].babt); + printf("gra: %4d\n",fec_log[ch].gra); + printf("txf: %4d\n",fec_log[ch].txf); + printf("mii: %4d\n",fec_log[ch].mii); + printf("lc: %4d\n",fec_log[ch].lc); + printf("rl: %4d\n",fec_log[ch].rl); + printf("xfun: %4d\n",fec_log[ch].xfun); + printf("xferr: %4d\n",fec_log[ch].xferr); + printf("rferr: %4d\n",fec_log[ch].rferr); + printf("dtxf: %4d\n",fec_log[ch].dtxf); + printf("drxf: %4d\n",fec_log[ch].drxf); + printf("\nRFSW:\n"); + printf("inv: %4d\n",fec_log[ch].rfsw_inv); + printf("m: %4d\n",fec_log[ch].rfsw_m); + printf("bc: %4d\n",fec_log[ch].rfsw_bc); + printf("mc: %4d\n",fec_log[ch].rfsw_mc); + printf("lg: %4d\n",fec_log[ch].rfsw_lg); + printf("no: %4d\n",fec_log[ch].rfsw_no); + printf("cr: %4d\n",fec_log[ch].rfsw_cr); + printf("ov: %4d\n",fec_log[ch].rfsw_ov); + printf("tr: %4d\n",fec_log[ch].rfsw_tr); + printf("---------------\n\n"); +} + +/* + * Display some of the registers for debugging + * + * Parameters: + * ch FEC channel + */ +void +fec_debug_dump(uint8_t ch) +{ + printf("\n------------- FEC%d -------------\n",ch); + printf("EIR %08x \n",MCF_FEC_EIR(ch)); + printf("EIMR %08x \n",MCF_FEC_EIMR(ch)); + printf("ECR %08x \n",MCF_FEC_ECR(ch)); + printf("RCR %08x \n",MCF_FEC_RCR(ch)); + printf("R_HASH %08x \n",MCF_FEC_R_HASH(ch)); + printf("TCR %08x \n",MCF_FEC_TCR(ch)); + printf("FECTFWR %08x \n",MCF_FEC_FECTFWR(ch)); + printf("FECRFSR %08x \n",MCF_FEC_FECRFSR(ch)); + printf("FECRFCR %08x \n",MCF_FEC_FECRFCR(ch)); + printf("FECRLRFP %08x \n",MCF_FEC_FECRLRFP(ch)); + printf("FECRLWFP %08x \n",MCF_FEC_FECRLWFP(ch)); + printf("FECRFAR %08x \n",MCF_FEC_FECRFAR(ch)); + printf("FECRFRP %08x \n",MCF_FEC_FECRFRP(ch)); + printf("FECRFWP %08x \n",MCF_FEC_FECRFWP(ch)); + printf("FECTFSR %08x \n",MCF_FEC_FECTFSR(ch)); + printf("FECTFCR %08x \n",MCF_FEC_FECTFCR(ch)); + printf("FECTLRFP %08x \n",MCF_FEC_FECTLRFP(ch)); + printf("FECTLWFP %08x \n",MCF_FEC_FECTLWFP(ch)); + printf("FECTFAR %08x \n",MCF_FEC_FECTFAR(ch)); + printf("FECTFRP %08x \n",MCF_FEC_FECTFRP(ch)); + printf("FECTFWP %08x \n",MCF_FEC_FECTFWP(ch)); + printf("FRST %08x \n",MCF_FEC_FRST(ch)); + printf("--------------------------------\n\n"); +} + +/* + * Set the duplex on the selected FEC controller + * + * Parameters: + * ch FEC channel + * duplex FEC_MII_FULL_DUPLEX or FEC_MII_HALF_DUPLEX + */ +void +fec_duplex (uint8_t ch, uint8_t duplex) +{ + ASSERT(ch == 0 || ch == 1); + + switch (duplex) + { + case FEC_MII_HALF_DUPLEX: + MCF_FEC_RCR(ch) |= MCF_FEC_RCR_DRT; + MCF_FEC_TCR(ch) &= (uint32_t)~MCF_FEC_TCR_FDEN; + break; + case FEC_MII_FULL_DUPLEX: + default: + MCF_FEC_RCR(ch) &= (uint32_t)~MCF_FEC_RCR_DRT; + MCF_FEC_TCR(ch) |= MCF_FEC_TCR_FDEN; + break; + } +} + +/* + * Generate the hash table settings for the given address + * + * Parameters: + * addr 48-bit (6 byte) Address to generate the hash for + * + * Return Value: + * The 6 most significant bits of the 32-bit CRC result + */ +uint8_t +fec_hash_address(const uint8_t *addr) +{ + uint32_t crc; + uint8_t byte; + int i, j; + + crc = 0xFFFFFFFF; + for(i=0; i<6; ++i) + { + byte = addr[i]; + for(j=0; j<8; ++j) + { + if((byte & 0x01)^(crc & 0x01)) + { + crc >>= 1; + crc = crc ^ 0xEDB88320; + } + else + crc >>= 1; + byte >>= 1; + } + } + return (uint8_t)(crc >> 26); +} + +/* + * Set the Physical (Hardware) Address and the Individual Address + * Hash in the selected FEC + * + * Parameters: + * ch FEC channel + * pa Physical (Hardware) Address for the selected FEC + */ +void +fec_set_address (uint8_t ch, const uint8_t *pa) +{ + uint8_t crc; + + ASSERT(ch == 0 || ch == 1); + + /* + * Set the Physical Address + */ + MCF_FEC_PALR(ch) = (uint32_t)((pa[0]<<24) | (pa[1]<<16) | (pa[2]<<8) | pa[3]); + MCF_FEC_PAUR(ch) = (uint32_t)((pa[4]<<24) | (pa[5]<<16)); + + /* + * Calculate and set the hash for given Physical Address + * in the Individual Address Hash registers + */ + crc = fec_hash_address(pa); + if(crc >= 32) + MCF_FEC_IAUR(ch) |= (uint32_t)(1 << (crc - 32)); + else + MCF_FEC_IALR(ch) |= (uint32_t)(1 << crc); +} + +/* + * Reset the selected FEC controller + * + * Parameters: + * ch FEC channel + */ +void +fec_reset (uint8_t ch) +{ + int i; + + ASSERT(ch == 0 || ch == 1); + + /* Clear any events in the FIFO status registers */ + MCF_FEC_FECRFSR(ch) = (0 + | MCF_FEC_FECRFSR_OF + | MCF_FEC_FECRFSR_UF + | MCF_FEC_FECRFSR_RXW + | MCF_FEC_FECRFSR_FAE + | MCF_FEC_FECRFSR_IP); + MCF_FEC_FECTFSR(ch) = (0 + | MCF_FEC_FECRFSR_OF + | MCF_FEC_FECRFSR_UF + | MCF_FEC_FECRFSR_RXW + | MCF_FEC_FECRFSR_FAE + | MCF_FEC_FECRFSR_IP); + + /* Reset the FIFOs */ + MCF_FEC_FRST(ch) |= MCF_FEC_FRST_SW_RST; + MCF_FEC_FRST(ch) &= ~MCF_FEC_FRST_SW_RST; + + /* Set the Reset bit and clear the Enable bit */ + MCF_FEC_ECR(ch) = MCF_FEC_ECR_RESET; + + /* Wait at least 8 clock cycles */ + for (i=0; i<10; ++i) + nop(); +} + +/* + * Initialize the selected FEC + * + * Parameters: + * ch FEC channel + * mode External interface mode (MII, 7-wire, or internal loopback) + * pa Physical (Hardware) Address for the selected FEC + */ +void +fec_init (uint8_t ch, uint8_t mode, const uint8_t *pa) +{ + ASSERT(ch == 0 || ch == 1); + + /* + * Enable all the external interface signals + */ + if (mode == FEC_MODE_7WIRE) + { + if (ch == 1) + MCF_GPIO_PAR_FECI2CIRQ |= MCF_GPIO_PAR_FECI2CIRQ_PAR_E17; + else + MCF_GPIO_PAR_FECI2CIRQ |= MCF_GPIO_PAR_FECI2CIRQ_PAR_E07; + } + else if (mode == FEC_MODE_MII) + { + if (ch == 1) + MCF_GPIO_PAR_FECI2CIRQ |= 0 + | MCF_GPIO_PAR_FECI2CIRQ_PAR_E1MDC_EMDC + | MCF_GPIO_PAR_FECI2CIRQ_PAR_E1MDIO_EMDIO + | MCF_GPIO_PAR_FECI2CIRQ_PAR_E1MII + | MCF_GPIO_PAR_FECI2CIRQ_PAR_E17; + else + MCF_GPIO_PAR_FECI2CIRQ |= 0 + | MCF_GPIO_PAR_FECI2CIRQ_PAR_E0MDC + | MCF_GPIO_PAR_FECI2CIRQ_PAR_E0MDIO + | MCF_GPIO_PAR_FECI2CIRQ_PAR_E0MII + | MCF_GPIO_PAR_FECI2CIRQ_PAR_E07; + } + + /* + * Clear the Individual and Group Address Hash registers + */ + MCF_FEC_IALR(ch) = 0; + MCF_FEC_IAUR(ch) = 0; + MCF_FEC_GALR(ch) = 0; + MCF_FEC_GAUR(ch) = 0; + + /* + * Set the Physical Address for the selected FEC + */ + fec_set_address(ch, pa); + + /* + * Mask all FEC interrupts + */ + MCF_FEC_EIMR(ch) = MCF_FEC_EIMR_MASK_ALL; + + /* + * Clear all FEC interrupt events + */ + MCF_FEC_EIR(ch) = MCF_FEC_EIR_CLEAR_ALL; + + /* + * Initialize the Receive Control Register + */ + MCF_FEC_RCR(ch) = 0 + | MCF_FEC_RCR_MAX_FL(ETH_MAX_FRM) + #ifdef FEC_PROMISCUOUS + | MCF_FEC_RCR_PROM + #endif + | MCF_FEC_RCR_FCE; + + if (mode == FEC_MODE_MII) + MCF_FEC_RCR(ch) |= MCF_FEC_RCR_MII_MODE; + + else if (mode == FEC_MODE_LOOPBACK) + MCF_FEC_RCR(ch) |= MCF_FEC_RCR_LOOP; + + /* + * Initialize the Transmit Control Register + */ + MCF_FEC_TCR(ch) = MCF_FEC_TCR_FDEN; + + /* + * Set Rx FIFO alarm and granularity + */ + MCF_FEC_FECRFCR(ch) = 0 + | MCF_FEC_FECRFCR_FRM + | MCF_FEC_FECRFCR_RXW_MSK + | MCF_FEC_FECRFCR_GR(7); + MCF_FEC_FECRFAR(ch) = MCF_FEC_FECRFAR_ALARM(768); + + /* + * Set Tx FIFO watermark, alarm and granularity + */ + MCF_FEC_FECTFCR(ch) = 0 + | MCF_FEC_FECTFCR_FRM + | MCF_FEC_FECTFCR_TXW_MSK + | MCF_FEC_FECTFCR_GR(7); + MCF_FEC_FECTFAR(ch) = MCF_FEC_FECTFAR_ALARM(256); + MCF_FEC_FECTFWR(ch) = MCF_FEC_FECTFWR_X_WMRK_256; + + /* + * Enable the transmitter to append the CRC + */ + MCF_FEC_CTCWR(ch) = 0 + | MCF_FEC_CTCWR_TFCW + | MCF_FEC_CTCWR_CRC; +} + +/* + * Start the FEC Rx DMA task + * + * Parameters: + * ch FEC channel + * rxbd First Rx buffer descriptor in the chain + */ +void +fec_rx_start(uint8_t ch, int8_t *rxbd) +{ + uint32_t initiator; + int channel, result; + + ASSERT(ch == 0 || ch == 1); + + /* + * Make the initiator assignment + */ + result = dma_set_initiator(DMA_FEC_RX(ch)); + ASSERT(result == 0); + + /* + * Grab the initiator number + */ + initiator = dma_get_initiator(DMA_FEC_RX(ch)); + + /* + * Determine the DMA channel running the task for the + * selected FEC + */ + channel = dma_set_channel(DMA_FEC_RX(ch), + (ch == 0) ? fec0_rx_frame : fec1_rx_frame); + ASSERT(channel != -1); + + /* + * Start the Rx DMA task + */ + /* + * Start the Rx DMA task + */ + MCD_startDma(channel, + (s8*)rxbd, + 0, + (s8*)MCF_FEC_FECRFDR_ADDR(ch), + 0, + RX_BUF_SZ, + 0, + initiator, + FECRX_DMA_PRI(ch), + 0 + | MCD_FECRX_DMA + | MCD_INTERRUPT + | MCD_TT_FLAGS_CW + | MCD_TT_FLAGS_RL + | MCD_TT_FLAGS_SP + , + 0 + | MCD_NO_CSUM + | MCD_NO_BYTE_SWAP + ); +} + +/* + * Continue the Rx DMA task + * + * This routine is called after the DMA task has halted after + * encountering an Rx buffer descriptor that wasn't marked as + * ready. There is no harm in calling the DMA continue routine + * if the DMA is not halted. + * + * Parameters: + * ch FEC channel + */ +void +fec_rx_continue(uint8_t ch) +{ + int channel; + + ASSERT(ch == 0 || ch == 1); + + /* + * Determine the DMA channel running the task for the + * selected FEC + */ + channel = dma_get_channel(DMA_FEC_RX(ch)); + ASSERT(channel != -1); + + /* + * Continue/restart the DMA task + */ + MCD_continDma(channel); +} + +/* + * Stop all frame receptions on the selected FEC + * + * Parameters: + * ch FEC channel + */ +void +fec_rx_stop (uint8_t ch) +{ + uint32_t mask; + int channel; + + ASSERT(ch == 0 || ch == 1); + + /* Save off the EIMR value */ + mask = MCF_FEC_EIMR(ch); + + /* Mask all interrupts */ + MCF_FEC_EIMR(ch) = 0; + + /* + * Determine the DMA channel running the task for the + * selected FEC + */ + channel = dma_get_channel(DMA_FEC_RX(ch)); + ASSERT(channel != -1); + + /* Kill the FEC Rx DMA task */ + MCD_killDma(channel); + + /* + * Free up the FEC requestor from the software maintained + * initiator list + */ + dma_free_initiator(DMA_FEC_RX(ch)); + + /* Free up the DMA channel */ + dma_free_channel(DMA_FEC_RX(ch)); + + /* Restore the interrupt mask register value */ + MCF_FEC_EIMR(ch) = mask; +} + +/* + * Receive Frame interrupt handler - this handler is called by the + * DMA interrupt handler indicating that a packet was successfully + * transferred out of the Rx FIFO. + * + * Parameters: + * nif Pointer to Network Interface structure + * ch FEC channel + */ +NBUF * +fec_rx_frame(uint8_t ch, NIF *nif) +{ +// ETH_HDR *eth_hdr; + FECBD *pRxBD; + NBUF *cur_nbuf, *new_nbuf; + int keep; + + while ((pRxBD = fecbd_rx_alloc(ch)) != NULL) + { + fec_log[ch].drxf++; + keep = TRUE; + + /* + * Check the Receive Frame Status Word for errors + * - The L bit should always be set + * - No undefined bits should be set + * - The upper 5 bits of the length should be cleared + */ + if (!(pRxBD->status & RX_BD_L) || (pRxBD->status & 0x0608) + || (pRxBD->length & 0xF800)) + { + keep = FALSE; + fec_log[ch].rfsw_inv++; + } + else if (pRxBD->status & RX_BD_ERROR) + { + keep = FALSE; + if (pRxBD->status & RX_BD_NO) + fec_log[ch].rfsw_no++; + if (pRxBD->status & RX_BD_CR) + fec_log[ch].rfsw_cr++; + if (pRxBD->status & RX_BD_OV) + fec_log[ch].rfsw_ov++; + if (pRxBD->status & RX_BD_TR) + fec_log[ch].rfsw_tr++; + } + else + { + if (pRxBD->status & RX_BD_LG) + fec_log[ch].rfsw_lg++; + if (pRxBD->status & RX_BD_M) + fec_log[ch].rfsw_m++; + if (pRxBD->status & RX_BD_BC) + fec_log[ch].rfsw_bc++; + if (pRxBD->status & RX_BD_MC) + fec_log[ch].rfsw_mc++; + } + + if (keep) + { + /* + * Pull the network buffer off the Rx ring queue + */ + cur_nbuf = nbuf_remove(NBUF_RX_RING); + ASSERT(cur_nbuf); + ASSERT(cur_nbuf->data == pRxBD->data); + + /* + * Copy the buffer descriptor information to the network buffer + */ +// cur_nbuf->length = (pRxBD->length - (ETH_HDR_LEN + ETH_CRC_LEN)); +// cur_nbuf->offset = ETH_HDR_LEN; + cur_nbuf->length = (pRxBD->length - (ETH_CRC_LEN)); + cur_nbuf->offset = 0; + + /* + * Get a new buffer pointer for this buffer descriptor + */ + new_nbuf = nbuf_alloc(); + if (new_nbuf == NULL) + { + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + printf("nbuf_alloc() failed\n"); + #endif + /* + * Can't allocate a new network buffer, so we + * have to trash the received data and reuse the buffer + * hoping that some buffers will free up in the system + * and this frame will be re-transmitted by the host + */ + pRxBD->length = RX_BUF_SZ; + pRxBD->status &= (RX_BD_W | RX_BD_INTERRUPT); + pRxBD->status |= RX_BD_E; + nbuf_add(NBUF_RX_RING, cur_nbuf); + fec_rx_continue(ch); + continue; + } + + /* + * Add the new network buffer to the Rx ring queue + */ + nbuf_add(NBUF_RX_RING, new_nbuf); + + /* + * Re-initialize the buffer descriptor - pointing it + * to the new data buffer. The previous data buffer + * will be passed up the stack + */ + pRxBD->data = new_nbuf->data; + pRxBD->length = RX_BUF_SZ; + pRxBD->status &= (RX_BD_W | RX_BD_INTERRUPT); + pRxBD->status |= RX_BD_E; + + + /* + * Let the DMA know that there is a new Rx BD (in case the + * ring was full and the DMA was waiting for an empty one) + */ + fec_rx_continue(ch); + + /* + * Get pointer to the frame data inside the network buffer + */ +// eth_hdr = (ETH_HDR *)cur_nbuf->data; + + /* + * Pass the received packet up the network stack if the + * protocol is supported in our network interface (NIF) + */ +//FIXME if (nif_protocol_exist(nif,eth_hdr->type)) +// { +// nif_protocol_handler(nif, eth_hdr->type, cur_nbuf); +// } +// else +// nbuf_free(cur_nbuf); + return(cur_nbuf); + } + else + { + /* + * This frame isn't a keeper + * Reset the status and length, but don't need to get another + * buffer since we are trashing the data in the current one + */ + pRxBD->length = RX_BUF_SZ; + pRxBD->status &= (RX_BD_W | RX_BD_INTERRUPT); + pRxBD->status |= RX_BD_E; + + /* + * Move the current buffer from the beginning to the end of the + * Rx ring queue + */ + cur_nbuf = nbuf_remove(NBUF_RX_RING); + nbuf_add(NBUF_RX_RING, cur_nbuf); + + /* + * Let the DMA know that there are new Rx BDs (in case + * it is waiting for an empty one) + */ + fec_rx_continue(ch); + } + } + return NULL; +} + +void +fec0_rx_frame(void) +{ +// extern NIF nif1; +// fec_rx_frame(0, 0); +} + +void +fec1_rx_frame(void) +{ +// extern NIF nif1; +// fec_rx_frame(1, 0); +} + +/* + * Start the FEC Tx DMA task + * + * Parameters: + * ch FEC channel + * txbd First Tx buffer descriptor in the chain + */ +void +fec_tx_start(uint8_t ch, int8_t *txbd) +{ + uint32_t initiator; + int channel, result; + void fec0_tx_frame(void); + void fec1_tx_frame(void); + + /* + * Make the initiator assignment + */ + result = dma_set_initiator(DMA_FEC_TX(ch)); + ASSERT(result == 0); + + /* + * Grab the initiator number + */ + initiator = dma_get_initiator(DMA_FEC_TX(ch)); + ASSERT(initiator != 0); + + /* + * Determine the DMA channel running the task for the + * selected FEC + */ + channel = dma_set_channel(DMA_FEC_TX(ch), + (ch == 0) ? fec0_tx_frame : fec1_tx_frame); + ASSERT(channel != -1); + + /* + * Start the Tx DMA task + */ + MCD_startDma(channel, + (s8*)txbd, + 0, + (s8*)MCF_FEC_FECTFDR_ADDR(ch), + 0, + ETH_MTU, + 0, + initiator, + FECTX_DMA_PRI(ch), + 0 + | MCD_FECTX_DMA + | MCD_INTERRUPT + | MCD_TT_FLAGS_CW + | MCD_TT_FLAGS_RL + | MCD_TT_FLAGS_SP + , + 0 + | MCD_NO_CSUM + | MCD_NO_BYTE_SWAP + ); +} + +/* + * Continue the Tx DMA task + * + * This routine is called after the DMA task has halted after + * encountering an Tx buffer descriptor that wasn't marked as + * ready. There is no harm in calling the continue DMA routine + * if the DMA was not paused. + * + * Parameters: + * ch FEC channel + */ +void +fec_tx_continue(uint8_t ch) +{ + int channel; + + /* + * Determine the DMA channel running the task for the + * selected FEC + */ + channel = dma_get_channel(DMA_FEC_TX(ch)); + ASSERT(channel > 0); + + /* + * Continue/restart the DMA task + */ + MCD_continDma((int)channel); +} + +/* + * Stop all transmissions on the selected FEC and kill the DMA task + * + * Parameters: + * ch FEC channel + */ +void +fec_tx_stop (uint8_t ch) +{ + uint32_t mask; + int channel; + + ASSERT(ch == 0 || ch == 1); + + /* Save off the EIMR value */ + mask = MCF_FEC_EIMR(ch); + + /* Mask all interrupts */ + MCF_FEC_EIMR(ch) = 0; + + /* If the Ethernet is still enabled... */ + if (MCF_FEC_ECR(ch) & MCF_FEC_ECR_ETHER_EN) + { + /* Issue the Graceful Transmit Stop */ + MCF_FEC_TCR(ch) |= MCF_FEC_TCR_GTS; + + /* Wait for the Graceful Stop Complete interrupt */ + while(!(MCF_FEC_EIR(ch) & MCF_FEC_EIR_GRA)) + { + if (!(MCF_FEC_ECR(ch) & MCF_FEC_ECR_ETHER_EN)) + break; + } + + /* Clear the Graceful Stop Complete interrupt */ + MCF_FEC_EIR(ch) = MCF_FEC_EIR_GRA; + } + + /* + * Determine the DMA channel running the task for the + * selected FEC + */ + channel = dma_get_channel(DMA_FEC_TX(ch)); + ASSERT(channel > 0); + + /* Kill the FEC Tx DMA task */ + MCD_killDma(channel); + + /* + * Free up the FEC requestor from the software maintained + * initiator list + */ + dma_free_initiator(DMA_FEC_TX(ch)); + + /* Free up the DMA channel */ + dma_free_channel(DMA_FEC_TX(ch)); + + /* Restore the interrupt mask register value */ + MCF_FEC_EIMR(ch) = mask; +} + +/* + * Trasmit Frame interrupt handler - this handler is called by the + * DMA interrupt handler indicating that a packet was successfully + * transferred to the Tx FIFO. + * + * Parameters: + * ch FEC channel + */ +void +fec_tx_frame(uint8_t ch) +{ + FECBD *pTxBD; + NBUF *pNbuf; + + while ((pTxBD = fecbd_tx_free(ch)) != NULL) + { + fec_log[ch].dtxf++; + + /* + * Grab the network buffer associated with this buffer descriptor + */ + pNbuf = nbuf_remove(NBUF_TX_RING); + ASSERT(pNbuf); + ASSERT(pNbuf->data == pTxBD->data); + + /* + * Free up the network buffer that was just transmitted + */ + nbuf_free(pNbuf); + + /* + * Re-initialize the Tx BD + */ + pTxBD->data = NULL; + pTxBD->length = 0; + } +} + +void +fec0_tx_frame(void) +{ + fec_tx_frame(0); +} + +void +fec1_tx_frame(void) +{ + fec_tx_frame(1); +} + +/* + * Send a packet out the selected FEC + * + * Parameters: + * ch FEC channel + * nif Pointer to Network Interface (NIF) structure + * dst Destination MAC Address + * src Source MAC Address + * type Ethernet Frame Type + * length Number of bytes to be transmitted (doesn't include type, + * src, or dest byte count) + * pkt Pointer packet network buffer + * + * Return Value: + * 1 success + * 0 otherwise + */ +int +fec_send (uint8_t ch, NIF *nif, uint8_t *dst, uint8_t *src, uint16_t type, NBUF *nbuf) +{ + FECBD *pTxBD; + ASSERT(ch == 0 || ch == 1); + + /* Check the length */ + if ((nbuf->length + ETH_HDR_LEN) > ETH_MTU) + return 0; + + /* + * Copy the destination address, source address, and Ethernet + * type into the packet + */ +// memcpy(&nbuf->data[0], dst, 6); +// memcpy(&nbuf->data[6], src, 6); +// memcpy(&nbuf->data[12], &type, 2); + + /* + * Grab the next available Tx Buffer Descriptor + */ + while ((pTxBD = fecbd_tx_alloc(ch)) == NULL) {}; + + /* + * Put the network buffer into the Tx waiting queue + */ + nbuf_add(NBUF_TX_RING, nbuf); + + /* + * Setup the buffer descriptor for transmission + */ + pTxBD->data = nbuf->data; + pTxBD->length = nbuf->length; // + ETH_HDR_LEN; + pTxBD->status |= (TX_BD_R | TX_BD_L); + + /* + * Continue the Tx DMA task (in case it was waiting for a new + * TxBD to be ready + */ + fec_tx_continue(ch); + + return 1; +} + +int +fec0_send(NIF *nif, uint8_t *dst, uint8_t *src, uint16_t type, NBUF *nbuf) +{ + return fec_send(0, nif, dst, src, type, nbuf); +} + +int +fec1_send(NIF *nif, uint8_t *dst, uint8_t *src, uint16_t type, NBUF *nbuf) +{ + return fec_send(1, nif, dst, src, type, nbuf); +} + +/* + * Enable interrupts on the selected FEC + * + * Parameters: + * ch FEC channel + * pri Interrupt Priority + * lvl Interrupt Level + */ +void +fec_irq_enable(uint8_t ch, uint8_t lvl, uint8_t pri) +{ + ASSERT(ch == 0 || ch == 1); + ASSERT(lvl > 0 && lvl < 8); + ASSERT(pri < 8); + + /* + * Setup the appropriate ICR + */ + MCF_INTC_ICRn((ch == 0) ? 39 : 38) = (uint8_t)(0 + | MCF_INTC_ICRn_IP(pri) + | MCF_INTC_ICRn_IL(lvl)); + + /* + * Clear any pending FEC interrupt events + */ + MCF_FEC_EIR(ch) = MCF_FEC_EIR_CLEAR_ALL; + + /* + * Unmask all FEC interrupts + */ + MCF_FEC_EIMR(ch) = MCF_FEC_EIMR_UNMASK_ALL; + + /* + * Unmask the FEC interrupt in the interrupt controller + */ + if (ch == 0) + MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK39; + else + MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK38; +} + +/* + * Disable interrupts on the selected FEC + * + * Parameters: + * ch FEC channel + */ +void +fec_irq_disable(uint8_t ch) +{ + ASSERT(ch == 0 || ch == 1); + + /* + * Mask all FEC interrupts + */ + MCF_FEC_EIMR(ch) = MCF_FEC_EIMR_MASK_ALL; + + /* + * Mask the FEC interrupt in the interrupt controller + */ + if (ch == 0) + MCF_INTC_IMRH |= MCF_INTC_IMRH_INT_MASK39; + else + MCF_INTC_IMRH |= MCF_INTC_IMRH_INT_MASK38; +} + +/* + * FEC interrupt handler + * All interrupts are multiplexed into a single vector for each + * FEC module. The lower level interrupt handler passes in the + * channel to this handler. Note that the receive interrupt is + * generated by the Multi-channel DMA FEC Rx task. + * + * Parameters: + * ch FEC channel + */ +static void +fec_irq_handler(uint8_t ch) +{ + uint32_t event, eir; + + /* + * Determine which interrupt(s) asserted by AND'ing the + * pending interrupts with those that aren't masked. + */ + eir = MCF_FEC_EIR(ch); + event = eir & MCF_FEC_EIMR(ch); + + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + if (event != eir) + printf("Pending but not enabled: 0x%08X\n",(event ^ eir)); + #endif + + /* + * Clear the event(s) in the EIR immediately + */ + MCF_FEC_EIR(ch) = event; + + if (event & MCF_FEC_EIR_RFERR) + { + fec_log[ch].total++; + fec_log[ch].rferr++; + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + printf("RFERR\n"); + printf("FECRFSR%d = 0x%08x\n",ch,MCF_FEC_FECRFSR(ch)); + fec_eth_stop(ch); + #endif + } + if (event & MCF_FEC_EIR_XFERR) + { + fec_log[ch].total++; + fec_log[ch].xferr++; + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + printf("XFERR\n"); + #endif + } + if (event & MCF_FEC_EIR_XFUN) + { + fec_log[ch].total++; + fec_log[ch].xfun++; + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + printf("XFUN\n"); + fec_eth_stop(ch); + #endif + } + if (event & MCF_FEC_EIR_RL) + { + fec_log[ch].total++; + fec_log[ch].rl++; + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + printf("RL\n"); + #endif + } + if (event & MCF_FEC_EIR_LC) + { + fec_log[ch].total++; + fec_log[ch].lc++; + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + printf("LC\n"); + #endif + } + if (event & MCF_FEC_EIR_MII) + { + fec_log[ch].mii++; + } + if (event & MCF_FEC_EIR_TXF) + { + fec_log[ch].txf++; + } + if (event & MCF_FEC_EIR_GRA) + { + fec_log[ch].gra++; + } + if (event & MCF_FEC_EIR_BABT) + { + fec_log[ch].total++; + fec_log[ch].babt++; + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + printf("BABT\n"); + #endif + } + if (event & MCF_FEC_EIR_BABR) + { + fec_log[ch].total++; + fec_log[ch].babr++; + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + printf("BABR\n"); + #endif + } + if (event & MCF_FEC_EIR_HBERR) + { + fec_log[ch].total++; + fec_log[ch].hberr++; + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + printf("HBERR\n"); + #endif + } +} + +int +fec0_interrupt_handler(void* arg1, void* arg2) +{ + (void) arg1; + (void) arg2; + fec_irq_handler(0); + return 1; +} + +int +fec1_interrupt_handler(void* arg1, void* arg2) +{ + (void) arg1; + (void) arg2; + fec_irq_handler(1); + return 1; +} + +/* + * Configure the selected Ethernet port and enable all operations + * + * Parameters: + * ch FEC channel + * trcvr Transceiver mode (MII, 7-Wire or internal loopback) + * speed Maximum operating speed (MII only) + * duplex Full or Half-duplex (MII only) + * mac Physical (MAC) Address + */ +void +fec_eth_setup(uint8_t ch, uint8_t trcvr, uint8_t speed, uint8_t duplex, const uint8_t *mac) +{ + ASSERT(ch == 0 || ch == 1); + + /* + * Disable FEC interrupts + */ + fec_irq_disable(ch); + + /* + * Initialize the event log + */ + fec_log_init(ch); + + /* + * Initialize the network buffers and fec buffer descriptors + */ + nbuf_init(); + fecbd_init(ch); + + /* + * Initialize the FEC + */ + fec_reset(ch); + fec_init(ch,trcvr,mac); + + if (trcvr == FEC_MODE_MII) + { + /* + * Initialize the MII interface + */ + fec_mii_init(ch, CFG_SYSTEM_CORE_CLOCK); + } + + /* + * Initialize and enable FEC interrupts + */ + fec_irq_enable(ch, FEC_INTC_LVL(ch), FEC_INTC_PRI(ch)); + + /* + * Enable the multi-channel DMA tasks + */ + fec_rx_start(ch, (int8_t*)fecbd_get_start(ch,Rx)); + fec_tx_start(ch, (int8_t*)fecbd_get_start(ch,Tx)); + + /* + * Enable the FEC channel + */ + MCF_FEC_ECR(ch) |= MCF_FEC_ECR_ETHER_EN; +} +/* + * Reset the selected Ethernet port + * + * Parameters: + * ch FEC channel + */ +void +fec_eth_reset(uint8_t ch) +{ +// To do +} + +/* + * Stop the selected Ethernet port + * + * Parameters: + * ch FEC channel + */ +void +fec_eth_stop(uint8_t ch) +{ + int level; + + /* + * Disable interrupts + */ + level = asm_set_ipl(7); + + /* + * Gracefully disable the receiver and transmitter + */ + fec_tx_stop(ch); + fec_rx_stop(ch); + + /* + * Disable FEC interrupts + */ + fec_irq_disable(ch); + + /* + * Disable the FEC channel + */ + MCF_FEC_ECR(ch) &= ~MCF_FEC_ECR_ETHER_EN; + + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + nbuf_debug_dump(); + fec_log_dump(ch); + #endif + + /* + * Flush the network buffers + */ + nbuf_flush(); + + /* + * Restore interrupt level + */ + asm_set_ipl(level); +} diff --git a/arch/m68k/mach-mcfv4e/fecbd.c b/arch/m68k/mach-mcfv4e/fecbd.c new file mode 100644 index 0000000000..26fb16d98d --- /dev/null +++ b/arch/m68k/mach-mcfv4e/fecbd.c @@ -0,0 +1,232 @@ +/* + * File: fecbd.c + * Purpose: Provide a simple buffer management driver + * + * Notes: + */ +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ASSERT(x) if (!(x)) hang(); + +/* + * This implements a simple static buffer descriptor + * ring for each channel and each direction + * + * FEC Buffer Descriptors need to be aligned to a 4-byte boundary. + * In order to accomplish this, data is over-allocated and manually + * aligned at runtime + * + * Enough space is allocated for each of the two FEC channels to have + * NRXBD Rx BDs and NTXBD Tx BDs + * + */ +FECBD unaligned_bds[(2 * NRXBD) + (2 * NTXBD) + 1]; + +/* + * These pointers are used to reference into the chunck of data set + * aside for buffer descriptors + */ +FECBD *RxBD; +FECBD *TxBD; + +/* + * Macros to easier access to the BD ring + */ +#define RxBD(ch,i) RxBD[(ch * NRXBD) + i] +#define TxBD(ch,i) TxBD[(ch * NTXBD) + i] + +/* + * Buffer descriptor indexes + */ +static int iTxbd_new; +static int iTxbd_old; +static int iRxbd; + +/* + * Initialize the FEC Buffer Descriptor ring + * Buffer Descriptor format is defined by the MCDAPI + * + * Parameters: + * ch FEC channel + */ +void +fecbd_init(uint8_t ch) +{ + NBUF *nbuf; + int i; + + /* + * Align Buffer Descriptors to 4-byte boundary + */ + RxBD = (FECBD *)(((int)unaligned_bds + 3) & 0xFFFFFFFC); + TxBD = (FECBD *)((int)RxBD + (sizeof(FECBD) * 2 * NRXBD)); + + /* + * Initialize the Rx Buffer Descriptor ring + */ + for (i = 0; i < NRXBD; ++i) + { + /* Grab a network buffer from the free list */ + nbuf = nbuf_alloc(); + ASSERT(nbuf); + + /* 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); + } + + /* + * Set the WRAP bit on the last one + */ + RxBD(ch,i-1).status |= RX_BD_W; + + /* + * 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; + + /* + * Initialize the buffer descriptor indexes + */ + iTxbd_new = iTxbd_old = iRxbd = 0; +} + +void +fecbd_dump(uint8_t ch) +{ + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + int i; + + printf("\n------------ FEC%d BDs -----------\n",ch); + printf("RxBD Ring\n"); + for (i=0; i +#include +#include +#include + +/* + * This is an API-internal pointer to the DMA's registers + */ +dmaRegs *MCD_dmaBar; + +/* + * These are the real and model task tables as generated by the + * build process + */ +extern TaskTableEntry MCD_realTaskTableSrc[NCHANNELS]; +extern TaskTableEntry MCD_modelTaskTableSrc[NUMOFVARIANTS]; + +/* + * However, this (usually) gets relocated to on-chip SRAM, at which + * point we access them as these tables + */ +volatile TaskTableEntry *MCD_taskTable; +TaskTableEntry *MCD_modelTaskTable; + + +/* + * MCD_chStatus[] is an array of status indicators for remembering + * whether a DMA has ever been attempted on each channel, pausing + * status, etc. + */ +static int MCD_chStatus[NCHANNELS] = +{ + MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, + MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, + MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, + MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA +}; + +/* + * Prototypes for local functions + */ +static void MCD_memcpy (int *dest, int *src, u32 size); +static void MCD_resmActions (int channel); + +/* + * Buffer descriptors used for storage of progress info for single Dmas + * Also used as storage for the DMA for CRCs for single DMAs + * Otherwise, the DMA does not parse these buffer descriptors + */ +#ifdef MCD_INCLUDE_EU +extern MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; +#else +MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; +#endif +MCD_bufDesc *MCD_relocBuffDesc; + + +/* + * Defines for the debug control register's functions + */ +#define DBG_CTL_COMP1_TASK (0x00002000) /* have comparator 1 look for a task # */ +#define DBG_CTL_ENABLE (DBG_CTL_AUTO_ARM | \ + DBG_CTL_BREAK | \ + DBG_CTL_INT_BREAK | \ + DBG_CTL_COMP1_TASK) +#define DBG_CTL_DISABLE (DBG_CTL_AUTO_ARM | \ + DBG_CTL_INT_BREAK | \ + DBG_CTL_COMP1_TASK) +#define DBG_KILL_ALL_STAT (0xFFFFFFFF) + +/* + * Offset to context save area where progress info is stored + */ +#define CSAVE_OFFSET 10 + +/* + * Defines for Byte Swapping + */ +#define MCD_BYTE_SWAP_KILLER 0xFFF8888F +#define MCD_NO_BYTE_SWAP_ATALL 0x00040000 + +/* + * Execution Unit Identifiers + */ +#define MAC 0 /* legacy - not used */ +#define LUAC 1 /* legacy - not used */ +#define CRC 2 /* legacy - not used */ +#define LURC 3 /* Logic Unit with CRC */ + +/* + * Task Identifiers + */ +#define TASK_CHAINNOEU 0 +#define TASK_SINGLENOEU 1 +#ifdef MCD_INCLUDE_EU +#define TASK_CHAINEU 2 +#define TASK_SINGLEEU 3 +#define TASK_FECRX 4 +#define TASK_FECTX 5 +#else +#define TASK_CHAINEU 0 +#define TASK_SINGLEEU 1 +#define TASK_FECRX 2 +#define TASK_FECTX 3 +#endif + +/* + * Structure to remember which variant is on which channel + * TBD- need this? + */ +typedef struct MCD_remVariants_struct MCD_remVariant; +struct MCD_remVariants_struct +{ + int remDestRsdIncr[NCHANNELS]; /* -1,0,1 */ + int remSrcRsdIncr[NCHANNELS]; /* -1,0,1 */ + s16 remDestIncr[NCHANNELS]; /* DestIncr */ + s16 remSrcIncr[NCHANNELS]; /* srcIncr */ + u32 remXferSize[NCHANNELS]; /* xferSize */ +}; + +/* + * Structure to remember the startDma parameters for each channel + */ +MCD_remVariant MCD_remVariants; + +/* + * Function: MCD_initDma + * Purpose: Initializes the DMA API by setting up a pointer to the DMA + * registers, relocating and creating the appropriate task + * structures, and setting up some global settings + * Arguments: + * dmaBarAddr - pointer to the multichannel DMA registers + * taskTableDest - location to move DMA task code and structs to + * flags - operational parameters + * Return Value: + * MCD_TABLE_UNALIGNED if taskTableDest is not 512-byte aligned + * MCD_OK otherwise + */ +extern u32 MCD_funcDescTab0[]; + +int MCD_initDma (dmaRegs *dmaBarAddr, void *taskTableDest, u32 flags) +{ + int i; + TaskTableEntry *entryPtr; + + /* setup the local pointer to register set */ + MCD_dmaBar = dmaBarAddr; + + /* do we need to move/create a task table */ + if ((flags & MCD_RELOC_TASKS) != 0) + { + int fixedSize; + u32 *fixedPtr; + /*int *tablePtr = taskTableDest;TBD*/ + int varTabsOffset, funcDescTabsOffset, contextSavesOffset; + int taskDescTabsOffset; + int taskTableSize, varTabsSize, funcDescTabsSize, contextSavesSize; + int taskDescTabSize; + + int i; + + /* check if physical address is aligned on 512 byte boundary */ + if (((u32)taskTableDest & 0x000001ff) != 0) + return(MCD_TABLE_UNALIGNED); + + MCD_taskTable = taskTableDest; /* set up local pointer to task Table */ + + /* + * Create a task table: + * - compute aligned base offsets for variable tables and + * function descriptor tables, then + * - loop through the task table and setup the pointers + * - copy over model task table with the the actual task descriptor + * tables + */ + + taskTableSize = NCHANNELS * sizeof(TaskTableEntry); + /* align variable tables to size */ + varTabsOffset = taskTableSize + (u32)taskTableDest; + if ((varTabsOffset & (VAR_TAB_SIZE - 1)) != 0) + varTabsOffset = (varTabsOffset + VAR_TAB_SIZE) & (~VAR_TAB_SIZE); + /* align function descriptor tables */ + varTabsSize = NCHANNELS * VAR_TAB_SIZE; + funcDescTabsOffset = varTabsOffset + varTabsSize; + + if ((funcDescTabsOffset & (FUNCDESC_TAB_SIZE - 1)) != 0) + funcDescTabsOffset = (funcDescTabsOffset + FUNCDESC_TAB_SIZE) & + (~FUNCDESC_TAB_SIZE); + + funcDescTabsSize = FUNCDESC_TAB_NUM * FUNCDESC_TAB_SIZE; + contextSavesOffset = funcDescTabsOffset + funcDescTabsSize; + contextSavesSize = (NCHANNELS * CONTEXT_SAVE_SIZE); + fixedSize = taskTableSize + varTabsSize + funcDescTabsSize + + contextSavesSize; + + /* zero the thing out */ + fixedPtr = (u32 *)taskTableDest; + for (i = 0;i<(fixedSize/4);i++) + fixedPtr[i] = 0; + + entryPtr = (TaskTableEntry*)MCD_taskTable; + /* set up fixed pointers */ + for (i = 0; i < NCHANNELS; i++) + { + entryPtr[i].varTab = (u32)varTabsOffset; /* update ptr to local value */ + entryPtr[i].FDTandFlags = (u32)funcDescTabsOffset | MCD_TT_FLAGS_DEF; + entryPtr[i].contextSaveSpace = (u32)contextSavesOffset; + varTabsOffset += VAR_TAB_SIZE; +#ifdef MCD_INCLUDE_EU /* if not there is only one, just point to the same one */ + funcDescTabsOffset += FUNCDESC_TAB_SIZE; +#endif + contextSavesOffset += CONTEXT_SAVE_SIZE; + } + /* copy over the function descriptor table */ + for ( i = 0; i < FUNCDESC_TAB_NUM; i++) + { + MCD_memcpy((void*)(entryPtr[i].FDTandFlags & ~MCD_TT_FLAGS_MASK), + (void*)MCD_funcDescTab0, FUNCDESC_TAB_SIZE); + } + + /* copy model task table to where the context saves stuff leaves off*/ + MCD_modelTaskTable = (TaskTableEntry*)contextSavesOffset; + + MCD_memcpy ((void*)MCD_modelTaskTable, (void*)MCD_modelTaskTableSrc, + NUMOFVARIANTS * sizeof(TaskTableEntry)); + + entryPtr = MCD_modelTaskTable; /* point to local version of + model task table */ + taskDescTabsOffset = (u32)MCD_modelTaskTable + + (NUMOFVARIANTS * sizeof(TaskTableEntry)); + + /* copy actual task code and update TDT ptrs in local model task table */ + for (i = 0; i < NUMOFVARIANTS; i++) + { + taskDescTabSize = entryPtr[i].TDTend - entryPtr[i].TDTstart + 4; + MCD_memcpy ((void*)taskDescTabsOffset, (void*)entryPtr[i].TDTstart, taskDescTabSize); + entryPtr[i].TDTstart = (u32)taskDescTabsOffset; + taskDescTabsOffset += taskDescTabSize; + entryPtr[i].TDTend = (u32)taskDescTabsOffset - 4; + } +#ifdef MCD_INCLUDE_EU /* Tack single DMA BDs onto end of code so API controls + where they are since DMA might write to them */ + MCD_relocBuffDesc = (MCD_bufDesc*)(entryPtr[NUMOFVARIANTS - 1].TDTend + 4); +#else /* DMA does not touch them so they can be wherever and we don't need to + waste SRAM on them */ + MCD_relocBuffDesc = MCD_singleBufDescs; +#endif + } + else + { + /* point the would-be relocated task tables and the + buffer descriptors to the ones the linker generated */ + + if (((u32)MCD_realTaskTableSrc & 0x000001ff) != 0) + return(MCD_TABLE_UNALIGNED); + + /* need to add code to make sure that every thing else is aligned properly TBD*/ + /* this is problematic if we init more than once or after running tasks, + need to add variable to see if we have aleady init'd */ + entryPtr = MCD_realTaskTableSrc; + for (i = 0; i < NCHANNELS; i++) + { + if (((entryPtr[i].varTab & (VAR_TAB_SIZE - 1)) != 0) || + ((entryPtr[i].FDTandFlags & (FUNCDESC_TAB_SIZE - 1)) != 0)) + return(MCD_TABLE_UNALIGNED); + } + + MCD_taskTable = MCD_realTaskTableSrc; + MCD_modelTaskTable = MCD_modelTaskTableSrc; + MCD_relocBuffDesc = MCD_singleBufDescs; + } + + + /* Make all channels as totally inactive, and remember them as such: */ + + MCD_dmaBar->taskbar = (u32) MCD_taskTable; + for (i = 0; i < NCHANNELS; i++) + { + MCD_dmaBar->taskControl[i] = 0x0; + MCD_chStatus[i] = MCD_NO_DMA; + } + + /* Set up pausing mechanism to inactive state: */ + MCD_dmaBar->debugComp1 = 0; /* no particular values yet for either comparator registers */ + MCD_dmaBar->debugComp2 = 0; + MCD_dmaBar->debugControl = DBG_CTL_DISABLE; + MCD_dmaBar->debugStatus = DBG_KILL_ALL_STAT; + + /* enable or disable commbus prefetch, really need an ifdef or + something to keep from trying to set this in the 8220 */ + if ((flags & MCD_COMM_PREFETCH_EN) != 0) + MCD_dmaBar->ptdControl &= ~PTD_CTL_COMM_PREFETCH; + else + MCD_dmaBar->ptdControl |= PTD_CTL_COMM_PREFETCH; + + return(MCD_OK); +} + +/* Function: MCD_dmaStatus + * Purpose: Returns the status of the DMA on the requested channel + * Arguments: channel - channel number + * Returns: Predefined status indicators + */ +int MCD_dmaStatus (int channel) +{ + u16 tcrValue; + + if((channel < 0) || (channel >= NCHANNELS)) + return(MCD_CHANNEL_INVALID); + + tcrValue = MCD_dmaBar->taskControl[channel]; + if ((tcrValue & TASK_CTL_EN) == 0) + { /* nothing running */ + /* if last reported with task enabled */ + if ( MCD_chStatus[channel] == MCD_RUNNING + || MCD_chStatus[channel] == MCD_IDLE) + MCD_chStatus[channel] = MCD_DONE; + } + else /* something is running */ + { + /* There are three possibilities: paused, running or idle. */ + if ( MCD_chStatus[channel] == MCD_RUNNING + || MCD_chStatus[channel] == MCD_IDLE) + { + MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; + /* This register is selected to know which initiator is + actually asserted. */ + if ((MCD_dmaBar->ptdDebug >> channel ) & 0x1 ) + MCD_chStatus[channel] = MCD_RUNNING; + else + MCD_chStatus[channel] = MCD_IDLE; + /* do not change the status if it is already paused. */ + } + } + return MCD_chStatus[channel]; +} + +/* Function: MCD_startDma + * Ppurpose: Starts a particular kind of DMA + * Arguments: see below + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + */ + +int MCD_startDma ( + int channel, /* the channel on which to run the DMA */ + s8 *srcAddr, /* the address to move data from, or physical buffer-descriptor address */ + s16 srcIncr, /* the amount to increment the source address per transfer */ + s8 *destAddr, /* the address to move data to */ + s16 destIncr, /* the amount to increment the destination address per transfer */ + u32 dmaSize, /* the number of bytes to transfer independent of the transfer size */ + u32 xferSize, /* the number bytes in of each data movement (1, 2, or 4) */ + u32 initiator, /* what device initiates the DMA */ + int priority, /* priority of the DMA */ + u32 flags, /* flags describing the DMA */ + u32 funcDesc /* a description of byte swapping, bit swapping, and CRC actions */ +#ifdef MCD_NEED_ADDR_TRANS + s8 *srcAddrVirt /* virtual buffer descriptor address TBD*/ +#endif +) +{ + int srcRsdIncr, destRsdIncr; + int *cSave; + short xferSizeIncr; + int tcrCount = 0; +#ifdef MCD_INCLUDE_EU + u32 *realFuncArray; +#endif + + if((channel < 0) || (channel >= NCHANNELS)) + return(MCD_CHANNEL_INVALID); + + /* tbd - need to determine the proper response to a bad funcDesc when not + including EU functions, for now, assign a benign funcDesc, but maybe + should return an error */ +#ifndef MCD_INCLUDE_EU + funcDesc = MCD_FUNC_NOEU1; +#endif + +#ifdef MCD_DEBUG +printf("startDma:Setting up params\n"); +#endif + /* Set us up for task-wise priority. We don't technically need to do this on every start, but + since the register involved is in the same longword as other registers that users are in control + of, setting it more than once is probably preferable. That since the documentation doesn't seem + to be completely consistent about the nature of the PTD control register. */ + MCD_dmaBar->ptdControl |= (u16) 0x8000; +#if 1 /* Not sure what we need to keep here rtm TBD */ + /* Calculate additional parameters to the regular DMA calls. */ + srcRsdIncr = srcIncr < 0 ? -1 : (srcIncr > 0 ? 1 : 0); + destRsdIncr = destIncr < 0 ? -1 : (destIncr > 0 ? 1 : 0); + + xferSizeIncr = (xferSize & 0xffff) | 0x20000000; + + /* Remember for each channel which variant is running. */ + MCD_remVariants.remSrcRsdIncr[channel] = srcRsdIncr; + MCD_remVariants.remDestRsdIncr[channel] = destRsdIncr; + MCD_remVariants.remDestIncr[channel] = destIncr; + MCD_remVariants.remSrcIncr[channel] = srcIncr; + MCD_remVariants.remXferSize[channel] = xferSize; +#endif + + cSave = (int*)(MCD_taskTable[channel].contextSaveSpace) + CSAVE_OFFSET + CURRBD; + +#ifdef MCD_INCLUDE_EU /* may move this to EU specific calls */ + realFuncArray = (u32 *) (MCD_taskTable[channel].FDTandFlags & 0xffffff00); + /* Modify the LURC's normal and byte-residue-loop functions according to parameter. */ + realFuncArray[(LURC*16)] = xferSize == 4 ? + funcDesc : xferSize == 2 ? + funcDesc & 0xfffff00f : funcDesc & 0xffff000f; + realFuncArray[(LURC*16+1)] = (funcDesc & MCD_BYTE_SWAP_KILLER) | MCD_NO_BYTE_SWAP_ATALL; +#endif + /* Write the initiator field in the TCR, and also set the initiator-hold + bit. Note that,due to a hardware quirk, this could collide with an + MDE access to the initiator-register file, so we have to verify that the write + reads back correctly. */ + + MCD_dmaBar->taskControl[channel] = + (initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM; + + while(((MCD_dmaBar->taskControl[channel] & 0x1fff) != + ((initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM)) && + (tcrCount < 1000)) + { + tcrCount++; + /*MCD_dmaBar->ptd_tcr[channel] = (initiator << 8) | 0x0020;*/ + MCD_dmaBar->taskControl[channel] = + (initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM; + } + + MCD_dmaBar->priority[channel] = (u8)priority & PRIORITY_PRI_MASK; + /* should be albe to handle this stuff with only one write to ts reg - tbd */ + if (channel < 8 && channel >= 0) + { + MCD_dmaBar->taskSize0 &= ~(0xf << (7-channel)*4); + MCD_dmaBar->taskSize0 |= (xferSize & 3) << (((7 - channel)*4) + 2); + MCD_dmaBar->taskSize0 |= (xferSize & 3) << ((7 - channel)*4); + } + else + { + MCD_dmaBar->taskSize1 &= ~(0xf << (15-channel)*4); + MCD_dmaBar->taskSize1 |= (xferSize & 3) << (((15 - channel)*4) + 2); + MCD_dmaBar->taskSize1 |= (xferSize & 3) << ((15 - channel)*4); + } + + /* setup task table flags/options which mostly control the line buffers */ + MCD_taskTable[channel].FDTandFlags &= ~MCD_TT_FLAGS_MASK; + MCD_taskTable[channel].FDTandFlags |= (MCD_TT_FLAGS_MASK & flags); + + if (flags & MCD_FECTX_DMA) + { + /* TDTStart and TDTEnd */ + MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_FECTX].TDTstart; + MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_FECTX].TDTend; + MCD_startDmaENetXmit(srcAddr, srcAddr, destAddr, MCD_taskTable, channel); + } + else if (flags & MCD_FECRX_DMA) + { + /* TDTStart and TDTEnd */ + MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_FECRX].TDTstart; + MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_FECRX].TDTend; + MCD_startDmaENetRcv(srcAddr, srcAddr, destAddr, MCD_taskTable, channel); + } + else if(flags & MCD_SINGLE_DMA) + { + /* this buffer descriptor is used for storing off initial parameters for later + progress query calculation and for the DMA to write the resulting checksum + The DMA does not use this to determine how to operate, that info is passed + with the init routine*/ + MCD_relocBuffDesc[channel].srcAddr = srcAddr; + MCD_relocBuffDesc[channel].destAddr = destAddr; + MCD_relocBuffDesc[channel].lastDestAddr = destAddr; /* definitely not its final value */ + MCD_relocBuffDesc[channel].dmaSize = dmaSize; + MCD_relocBuffDesc[channel].flags = 0; /* not used */ + MCD_relocBuffDesc[channel].csumResult = 0; /* not used */ + MCD_relocBuffDesc[channel].next = 0; /* not used */ + + /* Initialize the progress-querying stuff to show no progress:*/ + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET] = (int)srcAddr; + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET] = (int)destAddr; + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0; + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET] = + (u32) &(MCD_relocBuffDesc[channel]); + /* tbd - need to keep the user from trying to call the EU routine + when MCD_INCLUDE_EU is not defined */ + if( funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) + { + /* TDTStart and TDTEnd */ + MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_SINGLENOEU].TDTstart; + MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_SINGLENOEU].TDTend; + MCD_startDmaSingleNoEu(srcAddr, srcIncr, destAddr, destIncr, dmaSize, + xferSizeIncr, flags, (int *)&(MCD_relocBuffDesc[channel]), cSave, + MCD_taskTable, channel); + } + else + { + /* TDTStart and TDTEnd */ + MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_SINGLEEU].TDTstart; + MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_SINGLEEU].TDTend; + MCD_startDmaSingleEu(srcAddr, srcIncr, destAddr, destIncr, dmaSize, + xferSizeIncr, flags, (int *)&(MCD_relocBuffDesc[channel]), cSave, + MCD_taskTable, channel); + } + } + else + { /* chained DMAS */ + /* Initialize the progress-querying stuff to show no progress:*/ +#if 1 /* (!defined(MCD_NEED_ADDR_TRANS)) */ + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET] + = (int)((MCD_bufDesc*) srcAddr)->srcAddr; + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET] + = (int)((MCD_bufDesc*) srcAddr)->destAddr; +#else /* if using address translation, need the virtual addr of the first buffdesc */ + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET] + = (int)((MCD_bufDesc*) srcAddrVirt)->srcAddr; + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET] + = (int)((MCD_bufDesc*) srcAddrVirt)->destAddr; +#endif + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0; + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET] = (u32) srcAddr; + + if( funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) + { + /*TDTStart and TDTEnd*/ + MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_CHAINNOEU].TDTstart; + MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_CHAINNOEU].TDTend; + MCD_startDmaChainNoEu((int *)srcAddr, srcIncr, destIncr, xferSize, + xferSizeIncr, cSave, MCD_taskTable, channel); + } + else + { + /*TDTStart and TDTEnd*/ + MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_CHAINEU].TDTstart; + MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_CHAINEU].TDTend; + MCD_startDmaChainEu((int *)srcAddr, srcIncr, destIncr, xferSize, + xferSizeIncr, cSave, MCD_taskTable, channel); + } + } + MCD_chStatus[channel] = MCD_IDLE; + return(MCD_OK); +} + +/* Function: MCD_XferProgrQuery + * Purpose: Returns progress of DMA on requested channel + * Arguments: channel - channel to retrieve progress for + * progRep - pointer to user supplied MCD_XferProg struct + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + * + * Notes: + * MCD_XferProgrQuery() upon completing or after aborting a DMA, or + * while the DMA is in progress, this function returns the first + * DMA-destination address not (or not yet) used in the DMA. When + * encountering a non-ready buffer descriptor, the information for + * the last completed descriptor is returned. + * + * MCD_XferProgQuery() has to avoid the possibility of getting + * partially-updated information in the event that we should happen + * to query DMA progress just as the DMA is updating it. It does that + * by taking advantage of the fact context is not saved frequently for + * the most part. We therefore read it at least twice until we get the + * same information twice in a row. + * + * Because a small, but not insignificant, amount of time is required + * to write out the progress-query information, especially upon + * completion of the DMA, it would be wise to guarantee some time lag + * between successive readings of the progress-query information. + */ + +/* + * How many iterations of the loop below to execute to stabilize values + */ +#define STABTIME 0 + +int MCD_XferProgrQuery (int channel, MCD_XferProg *progRep) +{ + MCD_XferProg prevRep; + int again; /* true if we are to try again to get consistent results */ + int i; /* used as a time-waste counter */ + int destDiffBytes; /* Total number of bytes that we think actually got xfered. */ + int numIterations; /* number of iterations */ + int bytesNotXfered; /* bytes that did not get xfered. */ + s8 *LWAlignedInitDestAddr, *LWAlignedCurrDestAddr; + int subModVal, addModVal; /* Mode values to added and subtracted from the + final destAddr */ + + if((channel < 0) || (channel >= NCHANNELS)) + return(MCD_CHANNEL_INVALID); + + /* Read a trial value for the progress-reporting values*/ + prevRep.lastSrcAddr = + (s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET]; + prevRep.lastDestAddr = + (s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET]; + prevRep.dmaSize = ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET]; + prevRep.currBufDesc = + (MCD_bufDesc*) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET]; + /* Repeatedly reread those values until they match previous values: */ + do { + /* Waste a little bit of time to ensure stability: */ + for (i = 0; i < STABTIME; i++) + i += i >> 2; /* make sure this loop does something so that it doesn't get optimized out */ + /* Check them again: */ + progRep->lastSrcAddr = + (s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET]; + progRep->lastDestAddr = + (s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET]; + progRep->dmaSize = ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET]; + progRep->currBufDesc = + (MCD_bufDesc*) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET]; + /* See if they match: */ + if ( prevRep.lastSrcAddr != progRep->lastSrcAddr + || prevRep.lastDestAddr != progRep->lastDestAddr + || prevRep.dmaSize != progRep->dmaSize + || prevRep.currBufDesc != progRep->currBufDesc) + { + /* If they don't match, remember previous values and try again:*/ + prevRep.lastSrcAddr = progRep->lastSrcAddr; + prevRep.lastDestAddr = progRep->lastDestAddr; + prevRep.dmaSize = progRep->dmaSize; + prevRep.currBufDesc = progRep->currBufDesc; + again = MCD_TRUE; + } + else + again = MCD_FALSE; + } while (again == MCD_TRUE); + + + /* Update the dCount, srcAddr and destAddr */ + /* To calculate dmaCount, we consider destination address. C + overs M1,P1,Z for destination */ + switch(MCD_remVariants.remDestRsdIncr[channel]) { + case MINUS1: + subModVal = ((int)progRep->lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); + addModVal = ((int)progRep->currBufDesc->destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); + LWAlignedInitDestAddr = (progRep->currBufDesc->destAddr) - addModVal; + LWAlignedCurrDestAddr = (progRep->lastDestAddr) - subModVal; + destDiffBytes = LWAlignedInitDestAddr - LWAlignedCurrDestAddr; + bytesNotXfered = (destDiffBytes/MCD_remVariants.remDestIncr[channel]) * + ( MCD_remVariants.remDestIncr[channel] + + MCD_remVariants.remXferSize[channel]); + progRep->dmaSize = destDiffBytes - bytesNotXfered + addModVal - subModVal; + break; + case ZERO: + progRep->lastDestAddr = progRep->currBufDesc->destAddr; + break; + case PLUS1: + /* This value has to be subtracted from the final calculated dCount. */ + subModVal = ((int)progRep->currBufDesc->destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); + /* These bytes are already in lastDestAddr. */ + addModVal = ((int)progRep->lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); + LWAlignedInitDestAddr = (progRep->currBufDesc->destAddr) - subModVal; + LWAlignedCurrDestAddr = (progRep->lastDestAddr) - addModVal; + destDiffBytes = (progRep->lastDestAddr - LWAlignedInitDestAddr); + numIterations = ( LWAlignedCurrDestAddr - LWAlignedInitDestAddr)/MCD_remVariants.remDestIncr[channel]; + bytesNotXfered = numIterations * + ( MCD_remVariants.remDestIncr[channel] + - MCD_remVariants.remXferSize[channel]); + progRep->dmaSize = destDiffBytes - bytesNotXfered - subModVal; + break; + default: + break; + } + + /* This covers M1,P1,Z for source */ + switch(MCD_remVariants.remSrcRsdIncr[channel]) { + case MINUS1: + progRep->lastSrcAddr = + progRep->currBufDesc->srcAddr + + ( MCD_remVariants.remSrcIncr[channel] * + (progRep->dmaSize/MCD_remVariants.remXferSize[channel])); + break; + case ZERO: + progRep->lastSrcAddr = progRep->currBufDesc->srcAddr; + break; + case PLUS1: + progRep->lastSrcAddr = + progRep->currBufDesc->srcAddr + + ( MCD_remVariants.remSrcIncr[channel] * + (progRep->dmaSize/MCD_remVariants.remXferSize[channel])); + break; + default: break; + } + + return(MCD_OK); +} + +/* MCD_resmActions() does the majority of the actions of a DMA resume. + * It is called from MCD_killDma() and MCD_resumeDma(). It has to be + * a separate function because the kill function has to negate the task + * enable before resuming it, but the resume function has to do nothing + * if there is no DMA on that channel (i.e., if the enable bit is 0). + */ +static void MCD_resmActions (int channel) +{ + MCD_dmaBar->debugControl = DBG_CTL_DISABLE; + MCD_dmaBar->debugStatus = MCD_dmaBar->debugStatus; + MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; /* This register is selected to know + which initiator is actually asserted. */ + if((MCD_dmaBar->ptdDebug >> channel ) & 0x1) + MCD_chStatus[channel] = MCD_RUNNING; + else + MCD_chStatus[channel] = MCD_IDLE; +} + +/* Function: MCD_killDma + * Purpose: Halt the DMA on the requested channel, without any + * intention of resuming the DMA. + * Arguments: channel - requested channel + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + * + * Notes: + * A DMA may be killed from any state, including paused state, and it + * always goes to the MCD_HALTED state even if it is killed while in + * the MCD_NO_DMA or MCD_IDLE states. + */ +int MCD_killDma (int channel) +{ + /* MCD_XferProg progRep; */ + + if((channel < 0) || (channel >= NCHANNELS)) + return(MCD_CHANNEL_INVALID); + + MCD_dmaBar->taskControl[channel] = 0x0; + MCD_resumeDma (channel); + /* + * This must be after the write to the TCR so that the task doesn't + * start up again momentarily, and before the status assignment so + * as to override whatever MCD_resumeDma() may do to the channel + * status. + */ + MCD_chStatus[channel] = MCD_HALTED; + + /* + * Update the current buffer descriptor's lastDestAddr field + * + * MCD_XferProgrQuery (channel, &progRep); + * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; + */ + return(MCD_OK); +} + +/* Function: MCD_continDma + * Purpose: Continue a DMA which as stopped due to encountering an + * unready buffer descriptor. + * Arguments: channel - channel to continue the DMA on + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + * + * Notes: + * This routine does not check to see if there is a task which can + * be continued. Also this routine should not be used with single DMAs. + */ +int MCD_continDma (int channel) +{ + if((channel < 0) || (channel >= NCHANNELS)) + return(MCD_CHANNEL_INVALID); + + MCD_dmaBar->taskControl[channel] |= TASK_CTL_EN; + MCD_chStatus[channel] = MCD_RUNNING; + + return(MCD_OK); +} + +/* + * MCD_pauseDma() and MCD_resumeDma() below use the DMA's debug unit + * to freeze a task and resume it. We freeze a task by breakpointing + * on the stated task. That is, not any specific place in the task, + * but any time that task executes. In particular, when that task + * executes, we want to freeze that task and only that task. + * + * The bits of the debug control register influence interrupts vs. + * breakpoints as follows: + * - Bits 14 and 0 enable or disable debug functions. If enabled, you + * will get the interrupt but you may or may not get a breakpoint. + * - Bits 2 and 1 decide whether you also get a breakpoint in addition + * to an interrupt. + * + * The debug unit can do these actions in response to either internally + * detected breakpoint conditions from the comparators, or in response + * to the external breakpoint pin, or both. + * - Bits 14 and 1 perform the above-described functions for + * internally-generated conditions, i.e., the debug comparators. + * - Bits 0 and 2 perform the above-described functions for external + * conditions, i.e., the breakpoint external pin. + * + * Note that, although you "always" get the interrupt when you turn + * the debug functions, the interrupt can nevertheless, if desired, be + * masked by the corresponding bit in the PTD's IMR. Note also that + * this means that bits 14 and 0 must enable debug functions before + * bits 1 and 2, respectively, have any effect. + * + * NOTE: It's extremely important to not pause more than one DMA channel + * at a time. + ********************************************************************/ + +/* Function: MCD_pauseDma + * Purpose: Pauses the DMA on a given channel (if any DMA is running + * on that channel). + * Arguments: channel + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + */ +int MCD_pauseDma (int channel) +{ + /* MCD_XferProg progRep; */ + + if((channel < 0) || (channel >= NCHANNELS)) + return(MCD_CHANNEL_INVALID); + + if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) + { + MCD_dmaBar->debugComp1 = channel; + MCD_dmaBar->debugControl = DBG_CTL_ENABLE | (1 << (channel + 16)); + MCD_chStatus[channel] = MCD_PAUSED; + + /* + * Update the current buffer descriptor's lastDestAddr field + * + * MCD_XferProgrQuery (channel, &progRep); + * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; + */ + } + return(MCD_OK); +} + +/* Function: MCD_resumeDma + * Purpose: Resumes the DMA on a given channel (if any DMA is + * running on that channel). + * Arguments: channel - channel on which to resume DMA + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + */ +int MCD_resumeDma (int channel) +{ + if((channel < 0) || (channel >= NCHANNELS)) + return(MCD_CHANNEL_INVALID); + + if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) + MCD_resmActions (channel); + + return(MCD_OK); +} + +/* Function: MCD_csumQuery + * Purpose: Provide the checksum after performing a non-chained DMA + * Arguments: channel - channel to report on + * csum - pointer to where to write the checksum/CRC + * Returns: MCD_ERROR if the channel is invalid, else MCD_OK + * + * Notes: + * + */ +int MCD_csumQuery (int channel, u32 *csum) +{ +#ifdef MCD_INCLUDE_EU + if((channel < 0) || (channel >= NCHANNELS)) + return(MCD_CHANNEL_INVALID); + + *csum = MCD_relocBuffDesc[channel].csumResult; + return(MCD_OK); +#else + return(MCD_ERROR); +#endif +} + +/* Function: MCD_getCodeSize + * Purpose: Provide the size requirements of the microcoded tasks + * Returns: Size in bytes + */ +int MCD_getCodeSize(void) +{ +#ifdef MCD_INCLUDE_EU + return(0x2b5c); +#else + return(0x173c); +#endif +} + +/* Function: MCD_getVersion + * Purpose: Provide the version string and number + * Arguments: longVersion - user supplied pointer to a pointer to a char + * which points to the version string + * Returns: Version number and version string (by reference) + */ +char MCD_versionString[] = "Multi-channel DMA API Alpha v0.3 (2004-04-26)"; +#define MCD_REV_MAJOR 0x00 +#define MCD_REV_MINOR 0x03 + +int MCD_getVersion(char **longVersion) +{ + *longVersion = MCD_versionString; + return((MCD_REV_MAJOR << 8) | MCD_REV_MINOR); +} + +/* Private version of memcpy() + * Note that everything this is used for is longword-aligned. + */ +static void MCD_memcpy (int *dest, int *src, u32 size) +{ + u32 i; + + for (i = 0; i < size; i += sizeof(int), dest++, src++) + *dest = *src; +} diff --git a/arch/m68k/mach-mcfv4e/mcdapi/MCD_library.dox b/arch/m68k/mach-mcfv4e/mcdapi/MCD_library.dox new file mode 100644 index 0000000000..ec3a730730 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/mcdapi/MCD_library.dox @@ -0,0 +1,10 @@ +/** @page mcfv4e_MCDlib MultiChannelDMA library for Coldfire V4e + * + * The MCD library is taken as is from sources publically available from + * FreeScale Semiconductors az http://www.freescale.com + * + * It is slight reformatted and cleaned up, but otherwise unchanged to support + * later merged with updated MCD library releases. + * + * See the PDF document supplied with the library for API documentation + */ diff --git a/arch/m68k/mach-mcfv4e/mcdapi/MCD_tasks.c b/arch/m68k/mach-mcfv4e/mcdapi/MCD_tasks.c new file mode 100644 index 0000000000..3bfed232d7 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/mcdapi/MCD_tasks.c @@ -0,0 +1,2449 @@ +/* + * File: MCD_tasks.c + * Purpose: Contains task code and structures for Multi-channel DMA + * + * Notes: + */ +#include +#include + +u32 MCD_varTab0[]; +u32 MCD_varTab1[]; +u32 MCD_varTab2[]; +u32 MCD_varTab3[]; +u32 MCD_varTab4[]; +u32 MCD_varTab5[]; +u32 MCD_varTab6[]; +u32 MCD_varTab7[]; +u32 MCD_varTab8[]; +u32 MCD_varTab9[]; +u32 MCD_varTab10[]; +u32 MCD_varTab11[]; +u32 MCD_varTab12[]; +u32 MCD_varTab13[]; +u32 MCD_varTab14[]; +u32 MCD_varTab15[]; + +u32 MCD_funcDescTab0[]; +#ifdef MCD_INCLUDE_EU +u32 MCD_funcDescTab1[]; +u32 MCD_funcDescTab2[]; +u32 MCD_funcDescTab3[]; +u32 MCD_funcDescTab4[]; +u32 MCD_funcDescTab5[]; +u32 MCD_funcDescTab6[]; +u32 MCD_funcDescTab7[]; +u32 MCD_funcDescTab8[]; +u32 MCD_funcDescTab9[]; +u32 MCD_funcDescTab10[]; +u32 MCD_funcDescTab11[]; +u32 MCD_funcDescTab12[]; +u32 MCD_funcDescTab13[]; +u32 MCD_funcDescTab14[]; +u32 MCD_funcDescTab15[]; +#endif + +u32 MCD_contextSave0[]; +u32 MCD_contextSave1[]; +u32 MCD_contextSave2[]; +u32 MCD_contextSave3[]; +u32 MCD_contextSave4[]; +u32 MCD_contextSave5[]; +u32 MCD_contextSave6[]; +u32 MCD_contextSave7[]; +u32 MCD_contextSave8[]; +u32 MCD_contextSave9[]; +u32 MCD_contextSave10[]; +u32 MCD_contextSave11[]; +u32 MCD_contextSave12[]; +u32 MCD_contextSave13[]; +u32 MCD_contextSave14[]; +u32 MCD_contextSave15[]; + +u32 MCD_realTaskTableSrc[] = +{ + 0x00000000, + 0x00000000, + (u32)MCD_varTab0, /* Task 0 Variable Table */ + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ + 0x00000000, + 0x00000000, + (u32)MCD_contextSave0, /* Task 0 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab1, /* Task 1 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab1, /* Task 1 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave1, /* Task 1 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab2, /* Task 2 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab2, /* Task 2 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave2, /* Task 2 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab3, /* Task 3 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab3, /* Task 3 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave3, /* Task 3 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab4, /* Task 4 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab4, /* Task 4 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave4, /* Task 4 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab5, /* Task 5 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab5, /* Task 5 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave5, /* Task 5 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab6, /* Task 6 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab6, /* Task 6 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave6, /* Task 6 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab7, /* Task 7 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab7, /* Task 7 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave7, /* Task 7 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab8, /* Task 8 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab8, /* Task 8 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave8, /* Task 8 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab9, /* Task 9 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab9, /* Task 9 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave9, /* Task 9 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab10, /* Task 10 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab10, /* Task 10 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave10, /* Task 10 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab11, /* Task 11 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab11, /* Task 11 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave11, /* Task 11 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab12, /* Task 12 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab12, /* Task 12 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave12, /* Task 12 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab13, /* Task 13 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab13, /* Task 13 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave13, /* Task 13 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab14, /* Task 14 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab14, /* Task 14 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave14, /* Task 14 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_varTab15, /* Task 15 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32)MCD_funcDescTab15, /* Task 15 Function Descriptor Table & Flags */ +#else + (u32)MCD_funcDescTab0, /* Task 0 Function Descriptor Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32)MCD_contextSave15, /* Task 15 context save space */ + 0x00000000, +}; + + +u32 MCD_varTab0[] = +{ /* Task 0 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + + +u32 MCD_varTab1[] = +{ /* Task 1 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab2[]= +{ /* Task 2 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab3[]= +{ /* Task 3 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab4[]= +{ /* Task 4 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab5[]= +{ /* Task 5 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab6[]= +{ /* Task 6 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab7[]= +{ /* Task 7 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab8[]= +{ /* Task 8 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab9[]= +{ /* Task 9 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab10[]= +{ /* Task 10 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab11[]= +{ /* Task 11 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab12[]= +{ /* Task 12 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab13[]= +{ /* Task 13 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab14[]= +{ /* Task 14 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab15[]= +{ /* Task 15 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_funcDescTab0[]= +{ /* Task 0 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +#ifdef MCD_INCLUDE_EU +u32 MCD_funcDescTab1[]= +{ /* Task 1 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab2[]= +{ /* Task 2 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab3[]= +{ /* Task 3 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab4[]= +{ /* Task 4 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab5[]= +{ /* Task 5 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab6[]= +{ /* Task 6 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab7[]= +{ /* Task 7 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab8[]= +{ /* Task 8 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab9[]= +{ /* Task 9 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab10[]= +{ /* Task 10 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab11[]= +{ /* Task 11 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab12[]= +{ /* Task 12 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab13[]= +{ /* Task 13 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab14[]= +{ /* Task 14 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; + +u32 MCD_funcDescTab15[]= +{ /* Task 15 Function Descriptor Table */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, /* mainFunc(), EU# 3 */ + 0xa0000000, /* rsduFunc(), EU# 3 */ + 0xa0000000, /* crcAccumVal(), EU# 3 */ + 0x20000000, /* setCrcAccum(), EU# 3 */ + 0x21800000, /* and(), EU# 3 */ + 0x21e00000, /* or(), EU# 3 */ + 0x20400000, /* add(), EU# 3 */ + 0x20500000, /* sub(), EU# 3 */ + 0x205a0000, /* andNot(), EU# 3 */ + 0x20a00000, /* shiftR(), EU# 3 */ + 0x202fa000, /* andReadyBit(), EU# 3 */ + 0x202f9000, /* andNotReadyBit(), EU# 3 */ + 0x202ea000, /* andWrapBit(), EU# 3 */ + 0x202da000, /* andLastBit(), EU# 3 */ + 0x202e2000, /* andInterruptBit(), EU# 3 */ + 0x202f2000, /* andCrcRestartBit(), EU# 3 */ +}; +#endif /*MCD_INCLUDE_EU*/ + +u32 MCD_contextSave0[128]; /* Task 0 context save space */ +u32 MCD_contextSave1[128]; /* Task 1 context save space */ +u32 MCD_contextSave2[128]; /* Task 2 context save space */ +u32 MCD_contextSave3[128]; /* Task 3 context save space */ +u32 MCD_contextSave4[128]; /* Task 4 context save space */ +u32 MCD_contextSave5[128]; /* Task 5 context save space */ +u32 MCD_contextSave6[128]; /* Task 6 context save space */ +u32 MCD_contextSave7[128]; /* Task 7 context save space */ +u32 MCD_contextSave8[128]; /* Task 8 context save space */ +u32 MCD_contextSave9[128]; /* Task 9 context save space */ +u32 MCD_contextSave10[128]; /* Task 10 context save space */ +u32 MCD_contextSave11[128]; /* Task 11 context save space */ +u32 MCD_contextSave12[128]; /* Task 12 context save space */ +u32 MCD_contextSave13[128]; /* Task 13 context save space */ +u32 MCD_contextSave14[128]; /* Task 14 context save space */ +u32 MCD_contextSave15[128]; /* Task 15 context save space */ + + +u32 MCD_ChainNoEu_TDT[]; +u32 MCD_SingleNoEu_TDT[]; +#ifdef MCD_INCLUDE_EU +u32 MCD_ChainEu_TDT[]; +u32 MCD_SingleEu_TDT[]; +#endif +u32 MCD_ENetRcv_TDT[]; +u32 MCD_ENetXmit_TDT[]; + +u32 MCD_modelTaskTableSrc[]= +{ + (u32)MCD_ChainNoEu_TDT, + (u32)&((u8*)MCD_ChainNoEu_TDT)[0x0000016c], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_SingleNoEu_TDT, + (u32)&((u8*)MCD_SingleNoEu_TDT)[0x000000d4], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +#ifdef MCD_INCLUDE_EU + (u32)MCD_ChainEu_TDT, + (u32)&((u8*)MCD_ChainEu_TDT)[0x000001b4], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_SingleEu_TDT, + (u32)&((u8*)MCD_SingleEu_TDT)[0x00000124], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +#endif + (u32)MCD_ENetRcv_TDT, + (u32)&((u8*)MCD_ENetRcv_TDT)[0x0000009c], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + (u32)MCD_ENetXmit_TDT, + (u32)&((u8*)MCD_ENetXmit_TDT)[0x000000d0], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; +u32 MCD_ChainNoEu_TDT[]= +{ + 0x80004000, /* 0000(:370): LCDEXT: idx0 = 0x00000000; ; */ + 0x8118801b, /* 0004(:370): LCD: idx1 = var2; idx1 once var0; idx1 += inc3 */ + 0xb8c60018, /* 0008(:371): LCD: idx2 = *(idx1 + var12); idx2 once var0; idx2 += inc3 */ + 0x10002b10, /* 000C(:372): DRD1A: var10 = idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x7000000d, /* 0010(:373): DRD2A: EU0=0 EU1=0 EU2=0 EU3=13 EXT MORE init=0 WS=0 RS=0 */ + 0x018cf89f, /* 0014(:373): DRD2B1: var6 = EU3(); EU3(idx2) */ + 0x6000000a, /* 0018(:374): DRD2A: EU0=0 EU1=0 EU2=0 EU3=10 EXT init=0 WS=0 RS=0 */ + 0x080cf89f, /* 001C(:374): DRD2B1: idx0 = EU3(); EU3(idx2) */ + 0x000001f8, /* 0020(:0): NOP */ + 0x98180364, /* 0024(:378): LCD: idx0 = idx0; idx0 == var13; idx0 += inc4 */ + 0x8118801b, /* 0028(:380): LCD: idx1 = var2; idx1 once var0; idx1 += inc3 */ + 0xf8c6001a, /* 002C(:381): LCDEXT: idx2 = *(idx1 + var12 + 8); idx2 once var0; idx2 += inc3 */ + 0xb8c6601b, /* 0030(:382): LCD: idx3 = *(idx1 + var12 + 12); ; idx3 += inc3 */ + 0x10002710, /* 0034(:384): DRD1A: var9 = idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x00000f18, /* 0038(:385): DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */ + 0xb8c6001d, /* 003C(:387): LCD: idx2 = *(idx1 + var12 + 20); idx2 once var0; idx2 += inc3 */ + 0x10001310, /* 0040(:388): DRD1A: var4 = idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x60000007, /* 0044(:389): DRD2A: EU0=0 EU1=0 EU2=0 EU3=7 EXT init=0 WS=0 RS=0 */ + 0x014cf88b, /* 0048(:389): DRD2B1: var5 = EU3(); EU3(idx2,var11) */ + 0x98c6001c, /* 004C(:391): LCD: idx2 = idx1 + var12 + 4; idx2 once var0; idx2 += inc3 */ + 0x00000710, /* 0050(:392): DRD1A: var1 = idx2; FN=0 init=0 WS=0 RS=0 */ + 0x98c70018, /* 0054(:393): LCD: idx2 = idx1 + var14; idx2 once var0; idx2 += inc3 */ + 0x10001f10, /* 0058(:394): DRD1A: var7 = idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x0000c818, /* 005C(:395): DRD1A: *idx2 = var3; FN=0 init=0 WS=0 RS=0 */ + 0x000001f8, /* 0060(:0): NOP */ + 0xc1476018, /* 0064(:399): LCDEXT: idx1 = var2 + var14; ; idx1 += inc3 */ + 0xc003231d, /* 0068(:399): LCDEXT: idx2 = var0, idx3 = var6; idx3 == var12; idx2 += inc3, idx3 += inc5 */ + 0x811a601b, /* 006C(:400): LCD: idx4 = var2; ; idx4 += inc3 */ + 0xc1862102, /* 0070(:403): LCDEXT: idx5 = var3, idx6 = var12; idx6 < var4; idx5 += inc0, idx6 += inc2 */ + 0x849be009, /* 0074(:403): LCD: idx7 = var9; ; idx7 += inc1 */ + 0x03fed7b8, /* 0078(:406): DRD1A: *idx7; FN=0 init=31 WS=3 RS=3 */ + 0xda9b001b, /* 007C(:408): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 0080(:408): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x1000cb20, /* 0084(:409): DRD1A: *idx2 = idx4; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 0088(:410): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88f, /* 008C(:410): DRD2B1: idx2 = EU3(); EU3(idx2,var15) */ + 0x1000cb28, /* 0090(:411): DRD1A: *idx2 = idx5; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 0094(:412): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88f, /* 0098(:412): DRD2B1: idx2 = EU3(); EU3(idx2,var15) */ + 0x1000cb30, /* 009C(:413): DRD1A: *idx2 = idx6; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00A0(:414): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88f, /* 00A4(:414): DRD2B1: idx2 = EU3(); EU3(idx2,var15) */ + 0x1000cb38, /* 00A8(:415): DRD1A: *idx2 = idx7; FN=0 MORE init=0 WS=0 RS=0 */ + 0x0000c728, /* 00AC(:416): DRD1A: *idx1 = idx5; FN=0 init=0 WS=0 RS=0 */ + 0x000001f8, /* 00B0(:0): NOP */ + 0xc1476018, /* 00B4(:420): LCDEXT: idx1 = var2 + var14; ; idx1 += inc3 */ + 0xc003241d, /* 00B8(:420): LCDEXT: idx2 = var0, idx3 = var6; idx3 == var16; idx2 += inc3, idx3 += inc5 */ + 0x811a601b, /* 00BC(:421): LCD: idx4 = var2; ; idx4 += inc3 */ + 0xda9b001b, /* 00C0(:424): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 00C4(:424): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x0000d3a0, /* 00C8(:425): DRD1A: *idx4; FN=0 init=0 WS=0 RS=0 */ + 0xc1862102, /* 00CC(:427): LCDEXT: idx5 = var3, idx6 = var12; idx6 < var4; idx5 += inc0, idx6 += inc2 */ + 0x849be009, /* 00D0(:427): LCD: idx7 = var9; ; idx7 += inc1 */ + 0x0bfed7b8, /* 00D4(:430): DRD1A: *idx7; FN=0 TFD init=31 WS=3 RS=3 */ + 0xda9b001b, /* 00D8(:432): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 00DC(:432): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x1000cb20, /* 00E0(:433): DRD1A: *idx2 = idx4; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00E4(:434): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88f, /* 00E8(:434): DRD2B1: idx2 = EU3(); EU3(idx2,var15) */ + 0x1000cb28, /* 00EC(:435): DRD1A: *idx2 = idx5; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00F0(:436): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88f, /* 00F4(:436): DRD2B1: idx2 = EU3(); EU3(idx2,var15) */ + 0x1000cb30, /* 00F8(:437): DRD1A: *idx2 = idx6; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00FC(:438): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88f, /* 0100(:438): DRD2B1: idx2 = EU3(); EU3(idx2,var15) */ + 0x1000cb38, /* 0104(:439): DRD1A: *idx2 = idx7; FN=0 MORE init=0 WS=0 RS=0 */ + 0x0000c728, /* 0108(:440): DRD1A: *idx1 = idx5; FN=0 init=0 WS=0 RS=0 */ + 0x000001f8, /* 010C(:0): NOP */ + 0x8118801b, /* 0110(:444): LCD: idx1 = var2; idx1 once var0; idx1 += inc3 */ + 0xd8c60018, /* 0114(:446): LCDEXT: idx2 = idx1 + var12; idx2 once var0; idx2 += inc3 */ + 0x98c6601c, /* 0118(:446): LCD: idx3 = idx1 + var12 + 4; ; idx3 += inc3 */ + 0x6000000b, /* 011C(:447): DRD2A: EU0=0 EU1=0 EU2=0 EU3=11 EXT init=0 WS=0 RS=0 */ + 0x0c8cfc9f, /* 0120(:447): DRD2B1: *idx2 = EU3(); EU3(*idx2) */ + 0x000001f8, /* 0124(:0): NOP */ + 0xa146001e, /* 0128(:450): LCD: idx1 = *(var2 + var12 + 24); idx1 once var0; idx1 += inc3 */ + 0x10000b08, /* 012C(:451): DRD1A: var2 = idx1; FN=0 MORE init=0 WS=0 RS=0 */ + 0x10002050, /* 0130(:452): DRD1A: var8 = var10; FN=0 MORE init=0 WS=0 RS=0 */ + 0xb8c60018, /* 0134(:453): LCD: idx2 = *(idx1 + var12); idx2 once var0; idx2 += inc3 */ + 0x10002b10, /* 0138(:454): DRD1A: var10 = idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x7000000a, /* 013C(:455): DRD2A: EU0=0 EU1=0 EU2=0 EU3=10 EXT MORE init=0 WS=0 RS=0 */ + 0x080cf89f, /* 0140(:455): DRD2B1: idx0 = EU3(); EU3(idx2) */ + 0x6000000d, /* 0144(:456): DRD2A: EU0=0 EU1=0 EU2=0 EU3=13 EXT init=0 WS=0 RS=0 */ + 0x018cf89f, /* 0148(:456): DRD2B1: var6 = EU3(); EU3(idx2) */ + 0x000001f8, /* 014C(:0): NOP */ + 0x8618801b, /* 0150(:462): LCD: idx1 = var12; idx1 once var0; idx1 += inc3 */ + 0x7000000e, /* 0154(:463): DRD2A: EU0=0 EU1=0 EU2=0 EU3=14 EXT MORE init=0 WS=0 RS=0 */ + 0x084cf21f, /* 0158(:463): DRD2B1: idx1 = EU3(); EU3(var8) */ + 0xd8990336, /* 015C(:464): LCDEXT: idx2 = idx1; idx2 > var12; idx2 += inc6 */ + 0x8019801b, /* 0160(:464): LCD: idx3 = var0; idx3 once var0; idx3 += inc3 */ + 0x040001f8, /* 0164(:465): DRD1A: FN=0 INT init=0 WS=0 RS=0 */ + 0x000001f8, /* 0168(:0): NOP */ + 0x000001f8, /* 016C(:0): NOP */ +}; +u32 MCD_SingleNoEu_TDT[]= +{ + 0x8198001b, /* 0000(:657): LCD: idx0 = var3; idx0 once var0; idx0 += inc3 */ + 0x7000000d, /* 0004(:658): DRD2A: EU0=0 EU1=0 EU2=0 EU3=13 EXT MORE init=0 WS=0 RS=0 */ + 0x080cf81f, /* 0008(:658): DRD2B1: idx0 = EU3(); EU3(idx0) */ + 0x8198801b, /* 000C(:659): LCD: idx1 = var3; idx1 once var0; idx1 += inc3 */ + 0x6000000e, /* 0010(:660): DRD2A: EU0=0 EU1=0 EU2=0 EU3=14 EXT init=0 WS=0 RS=0 */ + 0x084cf85f, /* 0014(:660): DRD2B1: idx1 = EU3(); EU3(idx1) */ + 0x000001f8, /* 0018(:0): NOP */ + 0x8298001b, /* 001C(:664): LCD: idx0 = var5; idx0 once var0; idx0 += inc3 */ + 0x7000000d, /* 0020(:665): DRD2A: EU0=0 EU1=0 EU2=0 EU3=13 EXT MORE init=0 WS=0 RS=0 */ + 0x010cf81f, /* 0024(:665): DRD2B1: var4 = EU3(); EU3(idx0) */ + 0x6000000e, /* 0028(:666): DRD2A: EU0=0 EU1=0 EU2=0 EU3=14 EXT init=0 WS=0 RS=0 */ + 0x018cf81f, /* 002C(:666): DRD2B1: var6 = EU3(); EU3(idx0) */ + 0xc202601b, /* 0030(:669): LCDEXT: idx0 = var4, idx1 = var4; ; idx0 += inc3, idx1 += inc3 */ + 0xc002221c, /* 0034(:669): LCDEXT: idx2 = var0, idx3 = var4; idx3 == var8; idx2 += inc3, idx3 += inc4 */ + 0x809a601b, /* 0038(:670): LCD: idx4 = var1; ; idx4 += inc3 */ + 0xc10420c2, /* 003C(:673): LCDEXT: idx5 = var2, idx6 = var8; idx6 < var3; idx5 += inc0, idx6 += inc2 */ + 0x839be009, /* 0040(:673): LCD: idx7 = var7; ; idx7 += inc1 */ + 0x03fed7b8, /* 0044(:676): DRD1A: *idx7; FN=0 init=31 WS=3 RS=3 */ + 0xda9b001b, /* 0048(:678): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 004C(:678): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x70000006, /* 0050(:680): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf889, /* 0054(:680): DRD2B1: idx2 = EU3(); EU3(idx2,var9) */ + 0x1000cb28, /* 0058(:681): DRD1A: *idx2 = idx5; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 005C(:682): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf889, /* 0060(:682): DRD2B1: idx2 = EU3(); EU3(idx2,var9) */ + 0x1000cb30, /* 0064(:683): DRD1A: *idx2 = idx6; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 0068(:684): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf889, /* 006C(:684): DRD2B1: idx2 = EU3(); EU3(idx2,var9) */ + 0x0000cb38, /* 0070(:685): DRD1A: *idx2 = idx7; FN=0 init=0 WS=0 RS=0 */ + 0x000001f8, /* 0074(:0): NOP */ + 0xc202601b, /* 0078(:689): LCDEXT: idx0 = var4, idx1 = var4; ; idx0 += inc3, idx1 += inc3 */ + 0xc002229c, /* 007C(:689): LCDEXT: idx2 = var0, idx3 = var4; idx3 == var10; idx2 += inc3, idx3 += inc4 */ + 0x809a601b, /* 0080(:690): LCD: idx4 = var1; ; idx4 += inc3 */ + 0xda9b001b, /* 0084(:693): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 0088(:693): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x0000d3a0, /* 008C(:694): DRD1A: *idx4; FN=0 init=0 WS=0 RS=0 */ + 0xc10420c2, /* 0090(:696): LCDEXT: idx5 = var2, idx6 = var8; idx6 < var3; idx5 += inc0, idx6 += inc2 */ + 0x839be009, /* 0094(:696): LCD: idx7 = var7; ; idx7 += inc1 */ + 0x0bfed7b8, /* 0098(:699): DRD1A: *idx7; FN=0 TFD init=31 WS=3 RS=3 */ + 0xda9b001b, /* 009C(:701): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 00A0(:701): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x70000006, /* 00A4(:703): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf889, /* 00A8(:703): DRD2B1: idx2 = EU3(); EU3(idx2,var9) */ + 0x1000cb28, /* 00AC(:704): DRD1A: *idx2 = idx5; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00B0(:705): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf889, /* 00B4(:705): DRD2B1: idx2 = EU3(); EU3(idx2,var9) */ + 0x1000cb30, /* 00B8(:706): DRD1A: *idx2 = idx6; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00BC(:707): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf889, /* 00C0(:707): DRD2B1: idx2 = EU3(); EU3(idx2,var9) */ + 0x0000cb38, /* 00C4(:708): DRD1A: *idx2 = idx7; FN=0 init=0 WS=0 RS=0 */ + 0x000001f8, /* 00C8(:0): NOP */ + 0xc318022d, /* 00CC(:712): LCDEXT: idx0 = var6; idx0 > var8; idx0 += inc5 */ + 0x8018801b, /* 00D0(:712): LCD: idx1 = var0; idx1 once var0; idx1 += inc3 */ + 0x040001f8, /* 00D4(:713): DRD1A: FN=0 INT init=0 WS=0 RS=0 */ +}; +#ifdef MCD_INCLUDE_EU +u32 MCD_ChainEu_TDT[]= +{ + 0x80004000, /* 0000(:947): LCDEXT: idx0 = 0x00000000; ; */ + 0x8198801b, /* 0004(:947): LCD: idx1 = var3; idx1 once var0; idx1 += inc3 */ + 0xb8c68018, /* 0008(:948): LCD: idx2 = *(idx1 + var13); idx2 once var0; idx2 += inc3 */ + 0x10002f10, /* 000C(:949): DRD1A: var11 = idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x7000000d, /* 0010(:950): DRD2A: EU0=0 EU1=0 EU2=0 EU3=13 EXT MORE init=0 WS=0 RS=0 */ + 0x01ccf89f, /* 0014(:950): DRD2B1: var7 = EU3(); EU3(idx2) */ + 0x6000000a, /* 0018(:951): DRD2A: EU0=0 EU1=0 EU2=0 EU3=10 EXT init=0 WS=0 RS=0 */ + 0x080cf89f, /* 001C(:951): DRD2B1: idx0 = EU3(); EU3(idx2) */ + 0x000001f8, /* 0020(:0): NOP */ + 0x981803a4, /* 0024(:955): LCD: idx0 = idx0; idx0 == var14; idx0 += inc4 */ + 0x8198801b, /* 0028(:957): LCD: idx1 = var3; idx1 once var0; idx1 += inc3 */ + 0xf8c6801a, /* 002C(:958): LCDEXT: idx2 = *(idx1 + var13 + 8); idx2 once var0; idx2 += inc3 */ + 0xb8c6e01b, /* 0030(:959): LCD: idx3 = *(idx1 + var13 + 12); ; idx3 += inc3 */ + 0x10002b10, /* 0034(:961): DRD1A: var10 = idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x00001318, /* 0038(:962): DRD1A: var4 = idx3; FN=0 init=0 WS=0 RS=0 */ + 0xb8c6801d, /* 003C(:964): LCD: idx2 = *(idx1 + var13 + 20); idx2 once var0; idx2 += inc3 */ + 0x10001710, /* 0040(:965): DRD1A: var5 = idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x60000007, /* 0044(:966): DRD2A: EU0=0 EU1=0 EU2=0 EU3=7 EXT init=0 WS=0 RS=0 */ + 0x018cf88c, /* 0048(:966): DRD2B1: var6 = EU3(); EU3(idx2,var12) */ + 0x98c6801c, /* 004C(:968): LCD: idx2 = idx1 + var13 + 4; idx2 once var0; idx2 += inc3 */ + 0x00000b10, /* 0050(:969): DRD1A: var2 = idx2; FN=0 init=0 WS=0 RS=0 */ + 0x98c78018, /* 0054(:970): LCD: idx2 = idx1 + var15; idx2 once var0; idx2 += inc3 */ + 0x10002310, /* 0058(:971): DRD1A: var8 = idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x0000c820, /* 005C(:972): DRD1A: *idx2 = var4; FN=0 init=0 WS=0 RS=0 */ + 0x000001f8, /* 0060(:0): NOP */ + 0x8698801b, /* 0064(:976): LCD: idx1 = var13; idx1 once var0; idx1 += inc3 */ + 0x7000000f, /* 0068(:977): DRD2A: EU0=0 EU1=0 EU2=0 EU3=15 EXT MORE init=0 WS=0 RS=0 */ + 0x084cf2df, /* 006C(:977): DRD2B1: idx1 = EU3(); EU3(var11) */ + 0xd899042d, /* 0070(:978): LCDEXT: idx2 = idx1; idx2 >= var16; idx2 += inc5 */ + 0x8019801b, /* 0074(:978): LCD: idx3 = var0; idx3 once var0; idx3 += inc3 */ + 0x60000003, /* 0078(:979): DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */ + 0x2cd7c7df, /* 007C(:979): DRD2B2: EU3(var13) */ + 0xd8990364, /* 0080(:980): LCDEXT: idx2 = idx1; idx2 == var13; idx2 += inc4 */ + 0x8019801b, /* 0084(:980): LCD: idx3 = var0; idx3 once var0; idx3 += inc3 */ + 0x60000003, /* 0088(:981): DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */ + 0x2c17c7df, /* 008C(:981): DRD2B2: EU3(var1) */ + 0x000001f8, /* 0090(:0): NOP */ + 0xc1c7e018, /* 0094(:984): LCDEXT: idx1 = var3 + var15; ; idx1 += inc3 */ + 0xc003a35e, /* 0098(:984): LCDEXT: idx2 = var0, idx3 = var7; idx3 == var13; idx2 += inc3, idx3 += inc6 */ + 0x819a601b, /* 009C(:985): LCD: idx4 = var3; ; idx4 += inc3 */ + 0xc206a142, /* 00A0(:988): LCDEXT: idx5 = var4, idx6 = var13; idx6 < var5; idx5 += inc0, idx6 += inc2 */ + 0x851be009, /* 00A4(:988): LCD: idx7 = var10; ; idx7 += inc1 */ + 0x63fe0000, /* 00A8(:991): DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=31 WS=3 RS=3 */ + 0x0d4cfddf, /* 00AC(:991): DRD2B1: *idx5 = EU3(); EU3(*idx7) */ + 0xda9b001b, /* 00B0(:993): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 00B4(:993): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x70000002, /* 00B8(:994): DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */ + 0x004cf81f, /* 00BC(:994): DRD2B1: var1 = EU3(); EU3(idx0) */ + 0x1000cb20, /* 00C0(:995): DRD1A: *idx2 = idx4; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00C4(:996): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf891, /* 00C8(:996): DRD2B1: idx2 = EU3(); EU3(idx2,var17) */ + 0x1000cb28, /* 00CC(:997): DRD1A: *idx2 = idx5; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00D0(:998): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf891, /* 00D4(:998): DRD2B1: idx2 = EU3(); EU3(idx2,var17) */ + 0x1000cb30, /* 00D8(:999): DRD1A: *idx2 = idx6; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00DC(:1000): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf891, /* 00E0(:1000): DRD2B1: idx2 = EU3(); EU3(idx2,var17) */ + 0x1000cb38, /* 00E4(:1001): DRD1A: *idx2 = idx7; FN=0 MORE init=0 WS=0 RS=0 */ + 0x0000c728, /* 00E8(:1002): DRD1A: *idx1 = idx5; FN=0 init=0 WS=0 RS=0 */ + 0x000001f8, /* 00EC(:0): NOP */ + 0xc1c7e018, /* 00F0(:1006): LCDEXT: idx1 = var3 + var15; ; idx1 += inc3 */ + 0xc003a49e, /* 00F4(:1006): LCDEXT: idx2 = var0, idx3 = var7; idx3 == var18; idx2 += inc3, idx3 += inc6 */ + 0x819a601b, /* 00F8(:1007): LCD: idx4 = var3; ; idx4 += inc3 */ + 0xda9b001b, /* 00FC(:1010): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 0100(:1010): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x0000d3a0, /* 0104(:1011): DRD1A: *idx4; FN=0 init=0 WS=0 RS=0 */ + 0xc206a142, /* 0108(:1013): LCDEXT: idx5 = var4, idx6 = var13; idx6 < var5; idx5 += inc0, idx6 += inc2 */ + 0x851be009, /* 010C(:1013): LCD: idx7 = var10; ; idx7 += inc1 */ + 0x6bfe0000, /* 0110(:1016): DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 TFD EXT init=31 WS=3 RS=3 */ + 0x0d4cfddf, /* 0114(:1016): DRD2B1: *idx5 = EU3(); EU3(*idx7) */ + 0xda9b001b, /* 0118(:1018): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 011C(:1018): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x70000002, /* 0120(:1019): DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */ + 0x004cf81f, /* 0124(:1019): DRD2B1: var1 = EU3(); EU3(idx0) */ + 0x1000cb20, /* 0128(:1020): DRD1A: *idx2 = idx4; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 012C(:1021): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf891, /* 0130(:1021): DRD2B1: idx2 = EU3(); EU3(idx2,var17) */ + 0x1000cb28, /* 0134(:1022): DRD1A: *idx2 = idx5; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 0138(:1023): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf891, /* 013C(:1023): DRD2B1: idx2 = EU3(); EU3(idx2,var17) */ + 0x1000cb30, /* 0140(:1024): DRD1A: *idx2 = idx6; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 0144(:1025): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf891, /* 0148(:1025): DRD2B1: idx2 = EU3(); EU3(idx2,var17) */ + 0x1000cb38, /* 014C(:1026): DRD1A: *idx2 = idx7; FN=0 MORE init=0 WS=0 RS=0 */ + 0x0000c728, /* 0150(:1027): DRD1A: *idx1 = idx5; FN=0 init=0 WS=0 RS=0 */ + 0x000001f8, /* 0154(:0): NOP */ + 0x8198801b, /* 0158(:1031): LCD: idx1 = var3; idx1 once var0; idx1 += inc3 */ + 0xd8c68018, /* 015C(:1033): LCDEXT: idx2 = idx1 + var13; idx2 once var0; idx2 += inc3 */ + 0x98c6e01c, /* 0160(:1033): LCD: idx3 = idx1 + var13 + 4; ; idx3 += inc3 */ + 0x6000000b, /* 0164(:1034): DRD2A: EU0=0 EU1=0 EU2=0 EU3=11 EXT init=0 WS=0 RS=0 */ + 0x0c8cfc9f, /* 0168(:1034): DRD2B1: *idx2 = EU3(); EU3(*idx2) */ + 0x0000cc08, /* 016C(:1035): DRD1A: *idx3 = var1; FN=0 init=0 WS=0 RS=0 */ + 0xa1c6801e, /* 0170(:1038): LCD: idx1 = *(var3 + var13 + 24); idx1 once var0; idx1 += inc3 */ + 0x10000f08, /* 0174(:1039): DRD1A: var3 = idx1; FN=0 MORE init=0 WS=0 RS=0 */ + 0x10002458, /* 0178(:1040): DRD1A: var9 = var11; FN=0 MORE init=0 WS=0 RS=0 */ + 0xb8c68018, /* 017C(:1041): LCD: idx2 = *(idx1 + var13); idx2 once var0; idx2 += inc3 */ + 0x10002f10, /* 0180(:1042): DRD1A: var11 = idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x7000000a, /* 0184(:1043): DRD2A: EU0=0 EU1=0 EU2=0 EU3=10 EXT MORE init=0 WS=0 RS=0 */ + 0x080cf89f, /* 0188(:1043): DRD2B1: idx0 = EU3(); EU3(idx2) */ + 0x6000000d, /* 018C(:1044): DRD2A: EU0=0 EU1=0 EU2=0 EU3=13 EXT init=0 WS=0 RS=0 */ + 0x01ccf89f, /* 0190(:1044): DRD2B1: var7 = EU3(); EU3(idx2) */ + 0x000001f8, /* 0194(:0): NOP */ + 0x8698801b, /* 0198(:1050): LCD: idx1 = var13; idx1 once var0; idx1 += inc3 */ + 0x7000000e, /* 019C(:1051): DRD2A: EU0=0 EU1=0 EU2=0 EU3=14 EXT MORE init=0 WS=0 RS=0 */ + 0x084cf25f, /* 01A0(:1051): DRD2B1: idx1 = EU3(); EU3(var9) */ + 0xd899037f, /* 01A4(:1052): LCDEXT: idx2 = idx1; idx2 > var13; idx2 += inc7 */ + 0x8019801b, /* 01A8(:1052): LCD: idx3 = var0; idx3 once var0; idx3 += inc3 */ + 0x040001f8, /* 01AC(:1053): DRD1A: FN=0 INT init=0 WS=0 RS=0 */ + 0x000001f8, /* 01B0(:0): NOP */ + 0x000001f8, /* 01B4(:0): NOP */ +}; +u32 MCD_SingleEu_TDT[]= +{ + 0x8218001b, /* 0000(:1248): LCD: idx0 = var4; idx0 once var0; idx0 += inc3 */ + 0x7000000d, /* 0004(:1249): DRD2A: EU0=0 EU1=0 EU2=0 EU3=13 EXT MORE init=0 WS=0 RS=0 */ + 0x080cf81f, /* 0008(:1249): DRD2B1: idx0 = EU3(); EU3(idx0) */ + 0x8218801b, /* 000C(:1250): LCD: idx1 = var4; idx1 once var0; idx1 += inc3 */ + 0x6000000e, /* 0010(:1251): DRD2A: EU0=0 EU1=0 EU2=0 EU3=14 EXT init=0 WS=0 RS=0 */ + 0x084cf85f, /* 0014(:1251): DRD2B1: idx1 = EU3(); EU3(idx1) */ + 0x000001f8, /* 0018(:0): NOP */ + 0x8318001b, /* 001C(:1255): LCD: idx0 = var6; idx0 once var0; idx0 += inc3 */ + 0x7000000d, /* 0020(:1256): DRD2A: EU0=0 EU1=0 EU2=0 EU3=13 EXT MORE init=0 WS=0 RS=0 */ + 0x014cf81f, /* 0024(:1256): DRD2B1: var5 = EU3(); EU3(idx0) */ + 0x6000000e, /* 0028(:1257): DRD2A: EU0=0 EU1=0 EU2=0 EU3=14 EXT init=0 WS=0 RS=0 */ + 0x01ccf81f, /* 002C(:1257): DRD2B1: var7 = EU3(); EU3(idx0) */ + 0x8498001b, /* 0030(:1260): LCD: idx0 = var9; idx0 once var0; idx0 += inc3 */ + 0x7000000f, /* 0034(:1261): DRD2A: EU0=0 EU1=0 EU2=0 EU3=15 EXT MORE init=0 WS=0 RS=0 */ + 0x080cf19f, /* 0038(:1261): DRD2B1: idx0 = EU3(); EU3(var6) */ + 0xd81882a4, /* 003C(:1262): LCDEXT: idx1 = idx0; idx1 >= var10; idx1 += inc4 */ + 0x8019001b, /* 0040(:1262): LCD: idx2 = var0; idx2 once var0; idx2 += inc3 */ + 0x60000003, /* 0044(:1263): DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */ + 0x2c97c7df, /* 0048(:1263): DRD2B2: EU3(var9) */ + 0xd818826d, /* 004C(:1264): LCDEXT: idx1 = idx0; idx1 == var9; idx1 += inc5 */ + 0x8019001b, /* 0050(:1264): LCD: idx2 = var0; idx2 once var0; idx2 += inc3 */ + 0x60000003, /* 0054(:1265): DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */ + 0x2c17c7df, /* 0058(:1265): DRD2B2: EU3(var1) */ + 0x000001f8, /* 005C(:0): NOP */ + 0xc282e01b, /* 0060(:1268): LCDEXT: idx0 = var5, idx1 = var5; ; idx0 += inc3, idx1 += inc3 */ + 0xc002a25e, /* 0064(:1268): LCDEXT: idx2 = var0, idx3 = var5; idx3 == var9; idx2 += inc3, idx3 += inc6 */ + 0x811a601b, /* 0068(:1269): LCD: idx4 = var2; ; idx4 += inc3 */ + 0xc184a102, /* 006C(:1272): LCDEXT: idx5 = var3, idx6 = var9; idx6 < var4; idx5 += inc0, idx6 += inc2 */ + 0x841be009, /* 0070(:1272): LCD: idx7 = var8; ; idx7 += inc1 */ + 0x63fe0000, /* 0074(:1275): DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=31 WS=3 RS=3 */ + 0x0d4cfddf, /* 0078(:1275): DRD2B1: *idx5 = EU3(); EU3(*idx7) */ + 0xda9b001b, /* 007C(:1277): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 0080(:1277): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x70000002, /* 0084(:1279): DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */ + 0x004cf99f, /* 0088(:1279): DRD2B1: var1 = EU3(); EU3(idx6) */ + 0x70000006, /* 008C(:1280): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88b, /* 0090(:1280): DRD2B1: idx2 = EU3(); EU3(idx2,var11) */ + 0x1000cb28, /* 0094(:1281): DRD1A: *idx2 = idx5; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 0098(:1282): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88b, /* 009C(:1282): DRD2B1: idx2 = EU3(); EU3(idx2,var11) */ + 0x1000cb30, /* 00A0(:1283): DRD1A: *idx2 = idx6; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00A4(:1284): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88b, /* 00A8(:1284): DRD2B1: idx2 = EU3(); EU3(idx2,var11) */ + 0x0000cb38, /* 00AC(:1285): DRD1A: *idx2 = idx7; FN=0 init=0 WS=0 RS=0 */ + 0x000001f8, /* 00B0(:0): NOP */ + 0xc282e01b, /* 00B4(:1289): LCDEXT: idx0 = var5, idx1 = var5; ; idx0 += inc3, idx1 += inc3 */ + 0xc002a31e, /* 00B8(:1289): LCDEXT: idx2 = var0, idx3 = var5; idx3 == var12; idx2 += inc3, idx3 += inc6 */ + 0x811a601b, /* 00BC(:1290): LCD: idx4 = var2; ; idx4 += inc3 */ + 0xda9b001b, /* 00C0(:1293): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 00C4(:1293): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x0000d3a0, /* 00C8(:1294): DRD1A: *idx4; FN=0 init=0 WS=0 RS=0 */ + 0xc184a102, /* 00CC(:1296): LCDEXT: idx5 = var3, idx6 = var9; idx6 < var4; idx5 += inc0, idx6 += inc2 */ + 0x841be009, /* 00D0(:1296): LCD: idx7 = var8; ; idx7 += inc1 */ + 0x6bfe0000, /* 00D4(:1299): DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 TFD EXT init=31 WS=3 RS=3 */ + 0x0d4cfddf, /* 00D8(:1299): DRD2B1: *idx5 = EU3(); EU3(*idx7) */ + 0xda9b001b, /* 00DC(:1301): LCDEXT: idx5 = idx5, idx6 = idx6; idx5 once var0; idx5 += inc3, idx6 += inc3 */ + 0x9b9be01b, /* 00E0(:1301): LCD: idx7 = idx7; ; idx7 += inc3 */ + 0x70000002, /* 00E4(:1303): DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */ + 0x004cf99f, /* 00E8(:1303): DRD2B1: var1 = EU3(); EU3(idx6) */ + 0x70000006, /* 00EC(:1304): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88b, /* 00F0(:1304): DRD2B1: idx2 = EU3(); EU3(idx2,var11) */ + 0x1000cb28, /* 00F4(:1305): DRD1A: *idx2 = idx5; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 00F8(:1306): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88b, /* 00FC(:1306): DRD2B1: idx2 = EU3(); EU3(idx2,var11) */ + 0x1000cb30, /* 0100(:1307): DRD1A: *idx2 = idx6; FN=0 MORE init=0 WS=0 RS=0 */ + 0x70000006, /* 0104(:1308): DRD2A: EU0=0 EU1=0 EU2=0 EU3=6 EXT MORE init=0 WS=0 RS=0 */ + 0x088cf88b, /* 0108(:1308): DRD2B1: idx2 = EU3(); EU3(idx2,var11) */ + 0x0000cb38, /* 010C(:1309): DRD1A: *idx2 = idx7; FN=0 init=0 WS=0 RS=0 */ + 0x000001f8, /* 0110(:0): NOP */ + 0x8144801c, /* 0114(:1312): LCD: idx0 = var2 + var9 + 4; idx0 once var0; idx0 += inc3 */ + 0x0000c008, /* 0118(:1313): DRD1A: *idx0 = var1; FN=0 init=0 WS=0 RS=0 */ + 0xc398027f, /* 011C(:1315): LCDEXT: idx0 = var7; idx0 > var9; idx0 += inc7 */ + 0x8018801b, /* 0120(:1315): LCD: idx1 = var0; idx1 once var0; idx1 += inc3 */ + 0x040001f8, /* 0124(:1316): DRD1A: FN=0 INT init=0 WS=0 RS=0 */ +}; +#endif +u32 MCD_ENetRcv_TDT[]= +{ + 0x80004000, /* 0000(:1389): LCDEXT: idx0 = 0x00000000; ; */ + 0x81988000, /* 0004(:1389): LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */ + 0x10000788, /* 0008(:1390): DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */ + 0x6000000a, /* 000C(:1391): DRD2A: EU0=0 EU1=0 EU2=0 EU3=10 EXT init=0 WS=0 RS=0 */ + 0x080cf05f, /* 0010(:1391): DRD2B1: idx0 = EU3(); EU3(var1) */ + 0x98180209, /* 0014(:1394): LCD: idx0 = idx0; idx0 != var8; idx0 += inc1 */ + 0x81c40004, /* 0018(:1396): LCD: idx1 = var3 + var8 + 4; idx1 once var0; idx1 += inc0 */ + 0x7000000e, /* 001C(:1397): DRD2A: EU0=0 EU1=0 EU2=0 EU3=14 EXT MORE init=0 WS=0 RS=0 */ + 0x010cf05f, /* 0020(:1397): DRD2B1: var4 = EU3(); EU3(var1) */ + 0x7000000c, /* 0024(:1398): DRD2A: EU0=0 EU1=0 EU2=0 EU3=12 EXT MORE init=0 WS=0 RS=0 */ + 0x01ccf05f, /* 0028(:1398): DRD2B1: var7 = EU3(); EU3(var1) */ + 0x70000004, /* 002C(:1399): DRD2A: EU0=0 EU1=0 EU2=0 EU3=4 EXT MORE init=0 WS=0 RS=0 */ + 0x014cf049, /* 0030(:1399): DRD2B1: var5 = EU3(); EU3(var1,var9) */ + 0x70000004, /* 0034(:1400): DRD2A: EU0=0 EU1=0 EU2=0 EU3=4 EXT MORE init=0 WS=0 RS=0 */ + 0x004cf04a, /* 0038(:1400): DRD2B1: var1 = EU3(); EU3(var1,var10) */ + 0x00000b88, /* 003C(:1403): DRD1A: var2 = *idx1; FN=0 init=0 WS=0 RS=0 */ + 0xc4030150, /* 0040(:1406): LCDEXT: idx1 = var8, idx2 = var6; idx1 < var5; idx1 += inc2, idx2 += inc0 */ + 0x8119e012, /* 0044(:1406): LCD: idx3 = var2; ; idx3 += inc2 */ + 0x03e0cf90, /* 0048(:1409): DRD1A: *idx3 = *idx2; FN=0 init=31 WS=0 RS=0 */ + 0x81188000, /* 004C(:1412): LCD: idx1 = var2; idx1 once var0; idx1 += inc0 */ + 0x000ac788, /* 0050(:1413): DRD1A: *idx1 = *idx1; FN=0 init=0 WS=1 RS=1 */ + 0xc4030000, /* 0054(:1415): LCDEXT: idx1 = var8, idx2 = var6; idx1 once var0; idx1 += inc0, idx2 += inc0 */ + 0x8199e000, /* 0058(:1415): LCD: idx3 = var3; ; idx3 += inc0 */ + 0x70000004, /* 005C(:1421): DRD2A: EU0=0 EU1=0 EU2=0 EU3=4 EXT MORE init=0 WS=0 RS=0 */ + 0x084cfc8b, /* 0060(:1421): DRD2B1: idx1 = EU3(); EU3(*idx2,var11) */ + 0x60000005, /* 0064(:1422): DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */ + 0x0cccf841, /* 0068(:1422): DRD2B1: *idx3 = EU3(); EU3(idx1,var1) */ + 0x81c60000, /* 006C(:1428): LCD: idx1 = var3 + var12; idx1 once var0; idx1 += inc0 */ + 0xc399021b, /* 0070(:1430): LCDEXT: idx2 = var7; idx2 > var8; idx2 += inc3 */ + 0x80198000, /* 0074(:1430): LCD: idx3 = var0; idx3 once var0; idx3 += inc0 */ + 0x00008400, /* 0078(:1431): DRD1A: idx1 = var0; FN=0 init=0 WS=0 RS=0 */ + 0x00000f08, /* 007C(:1432): DRD1A: var3 = idx1; FN=0 init=0 WS=0 RS=0 */ + 0x81988000, /* 0080(:1435): LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */ + 0x10000788, /* 0084(:1436): DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */ + 0x6000000a, /* 0088(:1437): DRD2A: EU0=0 EU1=0 EU2=0 EU3=10 EXT init=0 WS=0 RS=0 */ + 0x080cf05f, /* 008C(:1437): DRD2B1: idx0 = EU3(); EU3(var1) */ + 0xc2188209, /* 0090(:1440): LCDEXT: idx1 = var4; idx1 != var8; idx1 += inc1 */ + 0x80190000, /* 0094(:1440): LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */ + 0x040001f8, /* 0098(:1441): DRD1A: FN=0 INT init=0 WS=0 RS=0 */ + 0x000001f8, /* 009C(:0): NOP */ +}; +u32 MCD_ENetXmit_TDT[]= +{ + 0x80004000, /* 0000(:1516): LCDEXT: idx0 = 0x00000000; ; */ + 0x81988000, /* 0004(:1516): LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */ + 0x10000788, /* 0008(:1517): DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */ + 0x6000000a, /* 000C(:1518): DRD2A: EU0=0 EU1=0 EU2=0 EU3=10 EXT init=0 WS=0 RS=0 */ + 0x080cf05f, /* 0010(:1518): DRD2B1: idx0 = EU3(); EU3(var1) */ + 0x98180309, /* 0014(:1521): LCD: idx0 = idx0; idx0 != var12; idx0 += inc1 */ + 0x80004003, /* 0018(:1523): LCDEXT: idx1 = 0x00000003; ; */ + 0x81c60004, /* 001C(:1523): LCD: idx2 = var3 + var12 + 4; idx2 once var0; idx2 += inc0 */ + 0x7000000e, /* 0020(:1524): DRD2A: EU0=0 EU1=0 EU2=0 EU3=14 EXT MORE init=0 WS=0 RS=0 */ + 0x014cf05f, /* 0024(:1524): DRD2B1: var5 = EU3(); EU3(var1) */ + 0x7000000c, /* 0028(:1525): DRD2A: EU0=0 EU1=0 EU2=0 EU3=12 EXT MORE init=0 WS=0 RS=0 */ + 0x028cf05f, /* 002C(:1525): DRD2B1: var10 = EU3(); EU3(var1) */ + 0x7000000d, /* 0030(:1526): DRD2A: EU0=0 EU1=0 EU2=0 EU3=13 EXT MORE init=0 WS=0 RS=0 */ + 0x018cf05f, /* 0034(:1526): DRD2B1: var6 = EU3(); EU3(var1) */ + 0x70000004, /* 0038(:1527): DRD2A: EU0=0 EU1=0 EU2=0 EU3=4 EXT MORE init=0 WS=0 RS=0 */ + 0x01ccf04d, /* 003C(:1527): DRD2B1: var7 = EU3(); EU3(var1,var13) */ + 0x10000b90, /* 0040(:1528): DRD1A: var2 = *idx2; FN=0 MORE init=0 WS=0 RS=0 */ + 0x60000004, /* 0044(:1529): DRD2A: EU0=0 EU1=0 EU2=0 EU3=4 EXT init=0 WS=0 RS=0 */ + 0x020cf0a1, /* 0048(:1529): DRD2B1: var8 = EU3(); EU3(var2,idx1) */ + 0xc3188312, /* 004C(:1532): LCDEXT: idx1 = var6; idx1 > var12; idx1 += inc2 */ + 0x83c70000, /* 0050(:1532): LCD: idx2 = var7 + var14; idx2 once var0; idx2 += inc0 */ + 0x00001f10, /* 0054(:1533): DRD1A: var7 = idx2; FN=0 init=0 WS=0 RS=0 */ + 0xc583a3c3, /* 0058(:1535): LCDEXT: idx1 = var11, idx2 = var7; idx2 >= var15; idx1 += inc0, idx2 += inc3 */ + 0x81042325, /* 005C(:1535): LCD: idx3 = var2, idx4 = var8; idx4 == var12; idx3 += inc4, idx4 += inc5 */ + 0x03e0c798, /* 0060(:1540): DRD1A: *idx1 = *idx3; FN=0 init=31 WS=0 RS=0 */ + 0xd8990000, /* 0064(:1543): LCDEXT: idx1 = idx1, idx2 = idx2; idx1 once var0; idx1 += inc0, idx2 += inc0 */ + 0x9999e000, /* 0068(:1543): LCD: idx3 = idx3; ; idx3 += inc0 */ + 0x000acf98, /* 006C(:1544): DRD1A: *idx3 = *idx3; FN=0 init=0 WS=1 RS=1 */ + 0xd8992306, /* 0070(:1546): LCDEXT: idx1 = idx1, idx2 = idx2; idx2 > var12; idx1 += inc0, idx2 += inc6 */ + 0x9999e03f, /* 0074(:1546): LCD: idx3 = idx3; ; idx3 += inc7 */ + 0x03eac798, /* 0078(:1549): DRD1A: *idx1 = *idx3; FN=0 init=31 WS=1 RS=1 */ + 0xd8990000, /* 007C(:1552): LCDEXT: idx1 = idx1, idx2 = idx2; idx1 once var0; idx1 += inc0, idx2 += inc0 */ + 0x9999e000, /* 0080(:1552): LCD: idx3 = idx3; ; idx3 += inc0 */ + 0x000acf98, /* 0084(:1553): DRD1A: *idx3 = *idx3; FN=0 init=0 WS=1 RS=1 */ + 0xd8990000, /* 0088(:1555): LCDEXT: idx1 = idx1, idx2 = idx2; idx1 once var0; idx1 += inc0, idx2 += inc0 */ + 0x99832302, /* 008C(:1555): LCD: idx3 = idx3, idx4 = var6; idx4 > var12; idx3 += inc0, idx4 += inc2 */ + 0x0beac798, /* 0090(:1558): DRD1A: *idx1 = *idx3; FN=0 TFD init=31 WS=1 RS=1 */ + 0x81988000, /* 0094(:1560): LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */ + 0x6000000b, /* 0098(:1561): DRD2A: EU0=0 EU1=0 EU2=0 EU3=11 EXT init=0 WS=0 RS=0 */ + 0x0c4cfc5f, /* 009C(:1561): DRD2B1: *idx1 = EU3(); EU3(*idx1) */ + 0x81c80000, /* 00A0(:1563): LCD: idx1 = var3 + var16; idx1 once var0; idx1 += inc0 */ + 0xc5190312, /* 00A4(:1565): LCDEXT: idx2 = var10; idx2 > var12; idx2 += inc2 */ + 0x80198000, /* 00A8(:1565): LCD: idx3 = var0; idx3 once var0; idx3 += inc0 */ + 0x00008400, /* 00AC(:1566): DRD1A: idx1 = var0; FN=0 init=0 WS=0 RS=0 */ + 0x00000f08, /* 00B0(:1567): DRD1A: var3 = idx1; FN=0 init=0 WS=0 RS=0 */ + 0x81988000, /* 00B4(:1570): LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */ + 0x10000788, /* 00B8(:1571): DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */ + 0x6000000a, /* 00BC(:1572): DRD2A: EU0=0 EU1=0 EU2=0 EU3=10 EXT init=0 WS=0 RS=0 */ + 0x080cf05f, /* 00C0(:1572): DRD2B1: idx0 = EU3(); EU3(var1) */ + 0xc2988309, /* 00C4(:1575): LCDEXT: idx1 = var5; idx1 != var12; idx1 += inc1 */ + 0x80190000, /* 00C8(:1575): LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */ + 0x040001f8, /* 00CC(:1576): DRD1A: FN=0 INT init=0 WS=0 RS=0 */ + 0x000001f8, /* 00D0(:0): NOP */ +}; + +#ifdef MCD_INCLUDE_EU +MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; +#endif diff --git a/arch/m68k/mach-mcfv4e/mcdapi/MCD_tasksInit.c b/arch/m68k/mach-mcfv4e/mcdapi/MCD_tasksInit.c new file mode 100644 index 0000000000..14104f7185 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/mcdapi/MCD_tasksInit.c @@ -0,0 +1,225 @@ +/* + * File: MCD_tasksInit.c + * Purpose: Functions for initializing variable tables of different + * types of tasks. + * + * Notes: + */ + +/* + * Do not edit! + */ + +#include +#include + +extern dmaRegs *MCD_dmaBar; + + +/* + * Task 0 + */ + +void MCD_startDmaChainNoEu(int *currBD, short srcIncr, short destIncr, int xferSize, short xferSizeIncr, int *cSave, volatile TaskTableEntry *taskTable, int channel) +{ + + MCD_SET_VAR(taskTable+channel, 2, (u32)currBD); /* var[2] */ + MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ + MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ + MCD_SET_VAR(taskTable+channel, 11, (u32)xferSize); /* var[11] */ + MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ + MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */ + MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */ + MCD_SET_VAR(taskTable+channel, 3, (u32)0x00000000); /* var[3] */ + MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */ + MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */ + MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */ + MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */ + MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */ + MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */ + MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */ + MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000000); /* var[12] */ + MCD_SET_VAR(taskTable+channel, 13, (u32)0x80000000); /* var[13] */ + MCD_SET_VAR(taskTable+channel, 14, (u32)0x00000010); /* var[14] */ + MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000004); /* var[15] */ + MCD_SET_VAR(taskTable+channel, 16, (u32)0x08000000); /* var[16] */ + MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */ + MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000000); /* inc[4] */ + MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000001); /* inc[5] */ + MCD_SET_VAR(taskTable+channel, 30, (u32)0x40000000); /* inc[6] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16)0x8000; +} + + +/* + * Task 1 + */ + +void MCD_startDmaSingleNoEu(char *srcAddr, short srcIncr, char *destAddr, short destIncr, int dmaSize, short xferSizeIncr, int flags, int *currBD, int *cSave, volatile TaskTableEntry *taskTable, int channel) +{ + + MCD_SET_VAR(taskTable+channel, 7, (u32)srcAddr); /* var[7] */ + MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ + MCD_SET_VAR(taskTable+channel, 2, (u32)destAddr); /* var[2] */ + MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ + MCD_SET_VAR(taskTable+channel, 3, (u32)dmaSize); /* var[3] */ + MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ + MCD_SET_VAR(taskTable+channel, 5, (u32)flags); /* var[5] */ + MCD_SET_VAR(taskTable+channel, 1, (u32)currBD); /* var[1] */ + MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */ + MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */ + MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */ + MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */ + MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000004); /* var[9] */ + MCD_SET_VAR(taskTable+channel, 10, (u32)0x08000000); /* var[10] */ + MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */ + MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000001); /* inc[4] */ + MCD_SET_VAR(taskTable+channel, 29, (u32)0x40000000); /* inc[5] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16)0x8000; +} + + +/* + * Task 2 + */ + +void MCD_startDmaChainEu(int *currBD, short srcIncr, short destIncr, int xferSize, short xferSizeIncr, int *cSave, volatile TaskTableEntry *taskTable, int channel) +{ + + MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */ + MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ + MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ + MCD_SET_VAR(taskTable+channel, 12, (u32)xferSize); /* var[12] */ + MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ + MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */ + MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */ + MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */ + MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */ + MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */ + MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */ + MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */ + MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */ + MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */ + MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */ + MCD_SET_VAR(taskTable+channel, 11, (u32)0x00000000); /* var[11] */ + MCD_SET_VAR(taskTable+channel, 13, (u32)0x00000000); /* var[13] */ + MCD_SET_VAR(taskTable+channel, 14, (u32)0x80000000); /* var[14] */ + MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000010); /* var[15] */ + MCD_SET_VAR(taskTable+channel, 16, (u32)0x00000001); /* var[16] */ + MCD_SET_VAR(taskTable+channel, 17, (u32)0x00000004); /* var[17] */ + MCD_SET_VAR(taskTable+channel, 18, (u32)0x08000000); /* var[18] */ + MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */ + MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000000); /* inc[4] */ + MCD_SET_VAR(taskTable+channel, 29, (u32)0xc0000000); /* inc[5] */ + MCD_SET_VAR(taskTable+channel, 30, (u32)0x80000001); /* inc[6] */ + MCD_SET_VAR(taskTable+channel, 31, (u32)0x40000000); /* inc[7] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16)0x8000; +} + + +/* + * Task 3 + */ + +void MCD_startDmaSingleEu(char *srcAddr, short srcIncr, char *destAddr, short destIncr, int dmaSize, short xferSizeIncr, int flags, int *currBD, int *cSave, volatile TaskTableEntry *taskTable, int channel) +{ + + MCD_SET_VAR(taskTable+channel, 8, (u32)srcAddr); /* var[8] */ + MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ + MCD_SET_VAR(taskTable+channel, 3, (u32)destAddr); /* var[3] */ + MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ + MCD_SET_VAR(taskTable+channel, 4, (u32)dmaSize); /* var[4] */ + MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ + MCD_SET_VAR(taskTable+channel, 6, (u32)flags); /* var[6] */ + MCD_SET_VAR(taskTable+channel, 2, (u32)currBD); /* var[2] */ + MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */ + MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */ + MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */ + MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */ + MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */ + MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000001); /* var[10] */ + MCD_SET_VAR(taskTable+channel, 11, (u32)0x00000004); /* var[11] */ + MCD_SET_VAR(taskTable+channel, 12, (u32)0x08000000); /* var[12] */ + MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */ + MCD_SET_VAR(taskTable+channel, 28, (u32)0xc0000000); /* inc[4] */ + MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000000); /* inc[5] */ + MCD_SET_VAR(taskTable+channel, 30, (u32)0x80000001); /* inc[6] */ + MCD_SET_VAR(taskTable+channel, 31, (u32)0x40000000); /* inc[7] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16)0x8000; +} + + +/* + * Task 4 + */ + +void MCD_startDmaENetRcv(char *bDBase, char *currBD, char *rcvFifoPtr, volatile TaskTableEntry *taskTable, int channel) +{ + + MCD_SET_VAR(taskTable+channel, 0, (u32)bDBase); /* var[0] */ + MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */ + MCD_SET_VAR(taskTable+channel, 6, (u32)rcvFifoPtr); /* var[6] */ + MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */ + MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */ + MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */ + MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */ + MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */ + MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */ + MCD_SET_VAR(taskTable+channel, 9, (u32)0x0000ffff); /* var[9] */ + MCD_SET_VAR(taskTable+channel, 10, (u32)0x30000000); /* var[10] */ + MCD_SET_VAR(taskTable+channel, 11, (u32)0x0fffffff); /* var[11] */ + MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000008); /* var[12] */ + MCD_SET_VAR(taskTable+channel, 24, (u32)0x00000000); /* inc[0] */ + MCD_SET_VAR(taskTable+channel, 25, (u32)0x60000000); /* inc[1] */ + MCD_SET_VAR(taskTable+channel, 26, (u32)0x20000004); /* inc[2] */ + MCD_SET_VAR(taskTable+channel, 27, (u32)0x40000000); /* inc[3] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16)0x8000; +} + + +/* + * Task 5 + */ + +void MCD_startDmaENetXmit(char *bDBase, char *currBD, char *xmitFifoPtr, volatile TaskTableEntry *taskTable, int channel) +{ + + MCD_SET_VAR(taskTable+channel, 0, (u32)bDBase); /* var[0] */ + MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */ + MCD_SET_VAR(taskTable+channel, 11, (u32)xmitFifoPtr); /* var[11] */ + MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */ + MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */ + MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */ + MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */ + MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */ + MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */ + MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */ + MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */ + MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */ + MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000000); /* var[12] */ + MCD_SET_VAR(taskTable+channel, 13, (u32)0x0000ffff); /* var[13] */ + MCD_SET_VAR(taskTable+channel, 14, (u32)0xffffffff); /* var[14] */ + MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000004); /* var[15] */ + MCD_SET_VAR(taskTable+channel, 16, (u32)0x00000008); /* var[16] */ + MCD_SET_VAR(taskTable+channel, 24, (u32)0x00000000); /* inc[0] */ + MCD_SET_VAR(taskTable+channel, 25, (u32)0x60000000); /* inc[1] */ + MCD_SET_VAR(taskTable+channel, 26, (u32)0x40000000); /* inc[2] */ + MCD_SET_VAR(taskTable+channel, 27, (u32)0xc000fffc); /* inc[3] */ + MCD_SET_VAR(taskTable+channel, 28, (u32)0xe0000004); /* inc[4] */ + MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000000); /* inc[5] */ + MCD_SET_VAR(taskTable+channel, 30, (u32)0x4000ffff); /* inc[6] */ + MCD_SET_VAR(taskTable+channel, 31, (u32)0xe0000001); /* inc[7] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16)0x8000; +} diff --git a/arch/m68k/mach-mcfv4e/mcdapi/Makefile b/arch/m68k/mach-mcfv4e/mcdapi/Makefile new file mode 100644 index 0000000000..7e2d5ab466 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/mcdapi/Makefile @@ -0,0 +1,26 @@ +# +# (C) Copyright 2007 Carsten Schlote +# See file CREDITS for list of people who contributed to this project. +# +# This file is part of U-Boot V2. +# +# U-Boot V2 is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# U-Boot V2 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with U-Boot V2. If not, see . +# + +# +# FreeScale MultiDMA Library +# +obj-y += MCD_dmaApi.o MCD_tasks.o MCD_tasksInit.o + + diff --git a/arch/m68k/mach-mcfv4e/mcdapi/ReleaseNotes.txt b/arch/m68k/mach-mcfv4e/mcdapi/ReleaseNotes.txt new file mode 100644 index 0000000000..bc10e713f9 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/mcdapi/ReleaseNotes.txt @@ -0,0 +1,27 @@ + +Multi-channel DMA API Release Notes + +Version 0.3 + +* MCD_INCLUDE_EU functionality supported(microcode changes for all tasks +except ethernet). +* Fixed bug when using MCD_END_FRAME which would cause the DMA to transfer +zero bytes and then complete. +* Code cleanup. + + +Version 0.2 (Slight Update) + +* Modified casts and task table implementations that were causing +warnings (and even errors on certain compilers) +* Cosmetic changes to clean up MCD_dmaApi.c and MCD_dma.h +* Fixed table declarations so that MCD_tasks.c will compile if + MCD_INCLUDE_EU is defined (Note: EU functionality still not supported) + +Version 0.1 (Initial release) + +Alpha version +MCD_INCLUDE_EU functionality not supported. +MCD_INCLUDE_JBIG not supported. + + diff --git a/arch/m68k/mach-mcfv4e/mcf_clocksource.c b/arch/m68k/mach-mcfv4e/mcf_clocksource.c new file mode 100644 index 0000000000..1278bf83ec --- /dev/null +++ b/arch/m68k/mach-mcfv4e/mcf_clocksource.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Implements the clocksource for Coldfire V4E + */ +#include +#include +#include +#include +#include +#include //FIXME - move to other file + +#ifdef CONFIG_USE_IRQ + +static uint32_t mcf_sltirq_hits; // FIXME: test code + +static int slt_timer_default_isr(void *not_used, void *t) +{ + struct mcf5xxx_slt *slt = MCF_SLT_Address(0); + if ( MCF_INTC_IPRH | MCF_INTC_IPRH_INT54 ) + { + if (slt->SSR & MCF_SLT_SSR_ST) + { + slt->SSR = 0UL + | MCF_SLT_SSR_ST; + } + mcf_sltirq_hits++; + return 1; + } + return 0; +} +#endif + + +static uint64_t mcf_clocksource_read(void) +{ + struct mcf5xxx_slt *slt = MCF_SLT_Address(0); + uint32_t sltcnt; + uint64_t rc = 0; + + if (slt->SSR & MCF_SLT_SSR_ST) + { +#ifndef CONFIG_USE_IRQ + slt->SSR = 0UL + | MCF_SLT_SSR_ST; +#endif + + rc = 0xffffffffULL + 1; + } + + sltcnt = 0xffffffffUL - slt->SCNT; + + rc += sltcnt; + + return rc; +} + + +static struct clocksource cs = { + .read = mcf_clocksource_read, + .mask = 0xffffffff, + .mult = 1, + .shift = 0, +}; + +static int clocksource_init (void) +{ + struct mcf5xxx_slt *slt = MCF_SLT_Address(0); + uint32_t sltclk = mcfv4e_get_bus_clk() * 1000000; + + /* Setup a slice timer terminal count */ + slt->STCNT = 0xffffffff; + + /* Reset status bits */ + slt->SSR = 0UL + | MCF_SLT_SSR_ST + | MCF_SLT_SSR_BE; + + /* Start timer to run continously */ + slt->SCR = 0UL + | MCF_SLT_SCR_TEN + | MCF_SLT_SCR_RUN + | MCF_SLT_SCR_IEN; // FIXME - add irq handler + + /* Setup up multiplier */ + cs.mult = clocksource_hz2mult(sltclk, cs.shift); + + /* + * Register the timer interrupt handler + */ + init_clock(&cs); + + return 0; +} + +core_initcall(clocksource_init); + +#ifdef CONFIG_USE_IRQ + +static int clocksource_irq_init(void) +{ + if (!mcf_interrupts_register_handler( + 118, // FIXME! + (int (*)(void*,void*))slt_timer_default_isr, + NULL, + NULL) + ) + { + return 1; + } + // Setup ICR + MCF_INTC_ICR54 = MCF_INTC_ICRn_IL(1) | MCF_INTC_ICRn_IP(0); + // Enable IRQ source + MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK54; + return 0; +} + +postcore_initcall(clocksource_irq_init); + +#endif diff --git a/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c b/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c new file mode 100644 index 0000000000..5a3368f901 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Implements a watchdog triggered reset for V4e Coldfire cores + */ +#include +#include + +/** + * Reset the cpu by setting up the watchdog timer and let it time out + */ +void reset_cpu (ulong ignored) +{ + while ( ignored ) { ; }; + + /* Disable watchdog and set Time-Out field to minimum timeout value */ + MCF_GPT_GMS0 = 0; + MCF_GPT_GCIR0 = MCF_GPT_GCIR_PRE(1) | MCF_GPT_GCIR_CNT(0xffff); + + /* Enable watchdog */ + MCF_GPT_GMS0 = MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS_GPIO; + + while (1); + /*NOTREACHED*/ +} +EXPORT_SYMBOL(reset_cpu); + diff --git a/arch/m68k/mach-mcfv4e/multichannel_dma.c b/arch/m68k/mach-mcfv4e/multichannel_dma.c new file mode 100644 index 0000000000..11aceeb9b9 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/multichannel_dma.c @@ -0,0 +1,51 @@ +/* + * U-Boot Header File + * + * Generic Clocksource for V4E + * + * Copyright (c) 2007 Carsten Schlote + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + + +static int mcdapi_init(void) +{ + /* + * Initialize the Multi-channel DMA + */ + MCD_initDma ((dmaRegs*)(__MBAR+0x8000), + (void *)CFG_SYS_SRAM_ADDRESS, + MCD_COMM_PREFETCH_EN | MCD_RELOC_TASKS); + + /* + * Enable interrupts in DMA and INTC + */ + dma_irq_enable(DMA_INTC_LVL, DMA_INTC_PRI); + + return 0; +} + +postcore_initcall(mcdapi_init); + diff --git a/arch/m68k/mach-mcfv4e/net/Makefile b/arch/m68k/mach-mcfv4e/net/Makefile new file mode 100644 index 0000000000..45badfaaac --- /dev/null +++ b/arch/m68k/mach-mcfv4e/net/Makefile @@ -0,0 +1,26 @@ +# +# (C) Copyright 2007 Carsten Schlote +# See file CREDITS for list of people who contributed to this project. +# +# This file is part of U-Boot V2. +# +# U-Boot V2 is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# U-Boot V2 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with U-Boot V2. If not, see . +# + +# +# Support code for current FEC driver code - must be eliminated later... +# +obj-y += nbuf.o queue.o net.o + + diff --git a/arch/m68k/mach-mcfv4e/net/nbuf.c b/arch/m68k/mach-mcfv4e/net/nbuf.c new file mode 100644 index 0000000000..d7ae921bed --- /dev/null +++ b/arch/m68k/mach-mcfv4e/net/nbuf.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Implementation of network buffer scheme. + * @todo Obsolete this file + */ +#include +#include +#include + +#include +#include + +#include + + +#define ASSERT(x) + +/** + * Queues used for network buffer storage + */ +QUEUE nbuf_queue[NBUF_MAXQ]; + +/* + * Some devices require line-aligned buffers. In order to accomplish + * this, the nbuf data is over-allocated and adjusted. The following + * array keeps track of the original data pointer returned by malloc + */ +ADDRESS unaligned_buffers[NBUF_MAX]; + +/** + * Initialize all the network buffer queues + * + * Return Value: + * 0 success + * 1 failure + */ +int +nbuf_init(void) +{ + int i; + NBUF *nbuf; + + for (i=0; idata = (uint8_t *)((uint32_t)(unaligned_buffers[i] + 15) & 0xFFFFFFF0); + if (!nbuf->data) + { + ASSERT(nbuf->data); + return 1; + } + + /* Initialize the network buffer */ + nbuf->offset = 0; + nbuf->length = 0; + + /* Add the network buffer to the free list */ + queue_add(&nbuf_queue[NBUF_FREE], (QNODE *)nbuf); + } + + #ifdef CONFIG_DRIVER_NET_MCF54XX_DEBUG + printf("NBUF allocation complete\n"); + nbuf_debug_dump(); + #endif + + return 0; +} +/** + * Return all the allocated memory to the heap + */ +void +nbuf_flush(void) +{ + NBUF *nbuf; + int i, level = asm_set_ipl(7); + int n = 0; + + for (i=0; ioffset = 0; + nbuf->length = NBUF_SZ; + queue_add(&nbuf_queue[NBUF_FREE],(QNODE *)nbuf); + + asm_set_ipl(level); +} +/** + * Remove a network buffer from the specified queue + * + * Parameters: + * q The index that identifies the queue to pull the buffer from + */ +NBUF * +nbuf_remove(int q) +{ + NBUF *nbuf; + int level = asm_set_ipl(7); + + nbuf = (NBUF *)queue_remove(&nbuf_queue[q]); + asm_set_ipl(level); + return nbuf; +} +/** + * Add a network buffer to the specified queue + * + * Parameters: + * q The index that identifies the queue to add the buffer to + */ +void +nbuf_add(int q, NBUF *nbuf) +{ + int level = asm_set_ipl(7); + queue_add(&nbuf_queue[q],(QNODE *)nbuf); + asm_set_ipl(level); +} +/** + * Put all the network buffers back into the free list + */ +void +nbuf_reset(void) +{ + NBUF *nbuf; + int i, level = asm_set_ipl(7); + + for (i=1; idata, + nbuf->offset, + nbuf->length); + nbuf = (NBUF *)nbuf->node.next; + } + } + + asm_set_ipl(level); +#endif +} diff --git a/arch/m68k/mach-mcfv4e/net/net.c b/arch/m68k/mach-mcfv4e/net/net.c new file mode 100644 index 0000000000..76e28531b6 --- /dev/null +++ b/arch/m68k/mach-mcfv4e/net/net.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Network initialization for MCF V4E FEC support code + * @todo Obsolete this file + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include //FIXME - move to other file + +int netif_init(int channel) +{ + uint8_t* board_get_ethaddr(uint8_t*); + +#ifdef CONFIG_USE_IRQ + int vector; + int (*handler)(void *, void *); + + disable_interrupts(); + + /* + * Register the FEC0 interrupt handler + */ + handler = (channel == 0) ? fec0_interrupt_handler + : fec1_interrupt_handler; + vector = (channel == 0) ? 103 : 102; + + if (!mcf_interrupts_register_handler( + vector,handler, NULL,(void *)0xdeadbeef)) + { + printf("Error: Unable to register handler\n"); + return 0; + } + + /* + * Register the DMA interrupt handler + */ + handler = dma_interrupt_handler; + vector = 112; + + if (!mcf_interrupts_register_handler( + vector,handler, NULL,NULL)) + { + printf("Error: Unable to register handler\n"); + return 0; + } +#endif + /* + * Enable interrupts + */ + enable_interrupts(); + + return 1; +} + +int netif_setup(int channel) +{ + uint8_t mac[6]; + /* + * Get user programmed MAC address + */ +// board_get_ethaddr(mac); + + + /* + * Initialize the network interface structure + */ +// nif_init(&nif1); +// nif1.mtu = ETH_MTU; +// nif1.send = (DBUG_ETHERNET_PORT == 0) ? fec0_send : fec1_send; + + /* + * Initialize the dBUG Ethernet port + */ + fec_eth_setup(channel, /* Which FEC to use */ + FEC_MODE_MII, /* Use MII mode */ + FEC_MII_100BASE_TX, /* Allow 10 and 100Mbps */ + FEC_MII_FULL_DUPLEX, /* Allow Full and Half Duplex */ + mac); + + /* + * Copy the Ethernet address to the NIF structure + */ +// memcpy(nif1.hwa, mac, 6); + + #ifdef DEBUG + printf("Ethernet Address is %02X:%02X:%02X:%02X:%02X:%02X\n",\ + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + #endif + + return 1; +} + +int netif_done(int channel) +{ + /* + * Download complete, clean up + */ +#ifdef CONFIG_USE_IRQ + int (*handler)(void *, void *); +#endif + /* + * Disable interrupts + */ + disable_interrupts(); + + /* + * Disable the Instruction Cache + */ + mcf5xxx_wr_cacr(MCF5XXX_CACR_ICINVA); + + /* + * Disable the dBUG Ethernet port + */ + fec_eth_stop(channel); + + /* + * Remove the interrupt handlers + */ +#ifdef CONFIG_USE_IRQ + handler = (channel == 0) ? fec0_interrupt_handler + : fec1_interrupt_handler; + mcf_interrupts_remove_handler(handler); + mcf_interrupts_remove_handler(dma_interrupt_handler); +#endif + return 1; +} + + diff --git a/arch/m68k/mach-mcfv4e/net/queue.c b/arch/m68k/mach-mcfv4e/net/queue.c new file mode 100644 index 0000000000..55f938af3e --- /dev/null +++ b/arch/m68k/mach-mcfv4e/net/queue.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2008 Carsten Schlote + * See file CREDITS for list of people who contributed to this project. + * + * This file is part of U-Boot V2. + * + * U-Boot V2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * U-Boot V2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with U-Boot V2. If not, see . + */ + +/** @file + * Implements a first in, first out linked list + * + * @note Simple selfcontaining basic code + * @todo Replace by u-boot standard list functions + */ +#include +#include + +/** Initialize the specified queue to an empty state + * + * @param[in] + * q Pointer to queue structure + */ +void queue_init(QUEUE *q) +{ + q->head = NULL; +} + +/** + * Check for an empty queue + * + * @param[in] q Pointer to queue structure + * @return + * 1 if Queue is empty + * 0 otherwise + */ +int +queue_isempty(QUEUE *q) +{ + return (q->head == NULL); +} + +/** + * Add an item to the end of the queue + * + * @param[in] q Pointer to queue structure + * @param[in] node New node to add to the queue + */ +void queue_add(QUEUE *q, QNODE *node) +{ + if (queue_isempty(q)) + { + q->head = q->tail = node; + } + else + { + q->tail->next = node; + q->tail = node; + } + + node->next = NULL; +} + +/** Remove and return first (oldest) entry from the specified queue + * + * @param[in] q Pointer to queue structure + * @return + * Node at head of queue - NULL if queue is empty + */ +QNODE* +queue_remove(QUEUE *q) +{ + QNODE *oldest; + + if (queue_isempty(q)) + return NULL; + + oldest = q->head; + q->head = oldest->next; + return oldest; +} + +/** Peek into the queue and return pointer to first (oldest) entry. + * + * The queue is not modified + * + * @param[in] q Pointer to queue structure + * @return + * Node at head of queue - NULL if queue is empty + */ +QNODE* +queue_peek(QUEUE *q) +{ + return q->head; +} + +/** Move entire contents of one queue to the other + * + * @param[in] src Pointer to source queue + * @param[in] dst Pointer to destination queue + */ +void +queue_move(QUEUE *dst, QUEUE *src) +{ + if (queue_isempty(src)) + return; + + if (queue_isempty(dst)) + dst->head = src->head; + else + dst->tail->next = src->head; + + dst->tail = src->tail; + src->head = NULL; + return; +} + -- cgit v1.2.3